javaee之黑马旅游网1
这是一个用来锻炼javaweb基础知识的项目,先来导入一些我们准备好的文件
下面这些东西是我们项目必备的,我们提前准备好了 ,这个我会上传到我的资源,你们可以自己去下载
利用maven来创建一个项目
选择无骨架创建项目,域名、项目名、版本号
把该导入的东西全部导入进来
上面的初级项目我会直接打包放到资源里面,你们可以直接Maven导入就行
导入完了项目之后, 我们用maven运行一下项目
然后去访问下面这个位置
展示
下面我们来说一下整体需要用到的技术,从三个层面来进行分析
web层:
service层:
dao层:
下面主要是先来做注册与登录的功能
先来创建数据库和相应的数据表
这里涉及到大量插入的sql数据,文章数据太大粘贴不上来,我还是放到资源里面去,可以直接下载,这里就贴一部分
set names utf8;drop table if exists tab_favorite;
drop table if exists tab_route_img;
drop table if exists tab_route;
drop table if exists tab_category;
drop table if exists tab_seller;
drop table if exists tab_user;/*==============================================================*/
/* Table: tab_category */
/*==============================================================*/
create table tab_category
(cid int not null auto_increment,cname varchar(100) not null,primary key (cid),unique key AK_nq_categoryname (cname)
);/*==============================================================*/
/* Table: tab_favorite */
/*==============================================================*/
create table tab_favorite
(rid int not null,date date not null,uid int not null,primary key (rid, uid)
);/*==============================================================*/
/* Table: tab_route */
/*==============================================================*/
create table tab_route
(rid int not null auto_increment,rname varchar(500) not null,price double not null,routeIntroduce varchar(1000),rflag char(1) not null,rdate varchar(19),isThemeTour char(1) not null,count int default 0,cid int not null,rimage varchar(200),sid int,sourceId varchar(50),primary key (rid),unique key AK_nq_sourceId (sourceId)
);/*==============================================================*/
/* Table: tab_route_img */
/*==============================================================*/
create table tab_route_img
(rgid int not null auto_increment,rid int not null,bigPic varchar(200) not null,smallPic varchar(200),primary key (rgid)
);/*==============================================================*/
/* Table: tab_seller */
/*==============================================================*/
create table tab_seller
(sid int not null auto_increment,sname varchar(200) not null,consphone varchar(20) not null,address varchar(200),primary key (sid),unique key AK_Key_2 (sname)
);/*==============================================================*/
/* Table: tab_user */
/*==============================================================*/
create table tab_user
(uid int not null auto_increment,username varchar(100) not null,password varchar(32) not null,name varchar(100),birthday date,sex char(1),telephone varchar(11),email varchar(100),status char(1) ,code varchar(50),primary key (uid),unique key AK_nq_username (username),unique key AK_nq_code (code)
);alter table tab_favorite add constraint FK_route_favorite foreign key (rid)references tab_route (rid) on delete restrict on update restrict;alter table tab_favorite add constraint FK_user_favorite foreign key (uid)references tab_user (uid) on delete restrict on update restrict;alter table tab_route add constraint FK_category_route foreign key (cid)references tab_category (cid) on delete restrict on update restrict;alter table tab_route add constraint FK_seller_route foreign key (sid)references tab_seller (sid) on delete restrict on update restrict;alter table tab_route_img add constraint FK_route_routeimg foreign key (rid)references tab_route (rid) on delete restrict on update restrict;insert into `tab_category`(`cid`,`cname`) values (8,'全球自由行'),(5,'国内游'),(4,'处境游'),(7,'抱团定制'),(6,'港澳游'),(2,'酒店'),(1,'门票'),(3,'香港车票');
insert into `tab_seller`(`sid`,`sname`,`consphone`,`address`) values (1,'黑马程序员','12345678901','传智播客javaEE学院');/*Data for the table `tab_route` */insert into `tab_route`(`rid`,`rname`,`price`,`routeIntroduce`,`rflag`,`rdate`,`isThemeTour`,`count`,`cid`,`rimage`,`sid`,`sourceId`) values (1,'【旅展 半价特惠 重走丝路•漫游宁夏 双飞4天】银川西部影视城 穆民新村 中卫沙坡头【品美酒 回族学唱花儿 感悟民俗】',999,'走进【宁夏沙坡头】,感受西北大漠风情、体会“大漠孤烟直,长河落日圆”的塞上风光!','1','2018-02-09 01:13:16','0',0,5,'img/product/small/m304b69a4c8328f7d6b8d5dadef020fe07.jpg',1,'23677')
先按照上面给的创建表与数据的语句,把表和数据插入进去,后来再来分析表与表之间的关系,在次之前我们需要创建一个项目对应的库。比如travel
拿到这个数据库之后,再来执行相应的sql语句,把这些表都创建好
上面这些表也可以先不用创建,我们等会直接采用source sql语句位置 ,先来看一下我这个sql语句的位置
直接导入这个语句的位置
先来实现注册功能
注册功能实现原理
下面再来说一下,表单校验需要注意的一些问题:
1.用户名:单词字符,长度8到20位
2.密码:单词字符,长度8到20位
3.email:邮件格式
4.姓名:非空
5.手机号:十一位全数字,第一位按照1开头
6.出生日期:非空
7.验证码:非空
先看一下前端界面
上面这些框都要做一些检查,也就是会单独写一个js函数来判断是否合理,有一点我们需要注意的是,当表单框失去焦点的时候,就要调用这个函数进行判断
先把这部分代码给贴过来
register.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>注册</title><link rel="stylesheet" type="text/css" href="css/common.css"><link rel="stylesheet" href="css/register.css"><!--导入jquery--><script src="js/jquery-3.3.1.js"></script><script type="text/javascript">//先来检验用户名function checkUsername() {//拿到用户名的值//这里通过jquery来获取值var username = $("#username").val();//输入框里面的值//定义一个正则,规定输入格式//这里的意思就是匹配字母数字下划线,最少8个,最多20个var regUsername = /^\w{8,20}$/;//这就是一个正则表达式对象//这里调用js对象里面的test判断字符串与正则是否匹配var flag = regUsername.test(username);//if(flag) {//输入正确,就成正常的颜色,//你这如果啥也不做,那么一旦框变红了//那就不能变回来啦$("#username").css("border","");} else {//输入错误,让边框变成红色$("#username").css("border","1px solid red");}return flag;//决定表单能否提交}//检验密码function checkPassword() {//获取密码var password = $("#password").val();//定义正则,和上面一样操作var regPassword = /^\w{8,20}$/;//用test判断var flag = regPassword.test(password);if(flag) {//也不能啥也不做$("#password").css("border","");} else {//把边框变成红色$("#password").css("border","1px solid red");}return flag;}//检验邮件function checkEmail() {//获取邮件//邮件的操作性质与上面基本一样var email = $("#email").val();var regEmail = /^\w+@\w+\.\w+$/;var flag = regEmail.test(email);if(flag) {$("#email").css("border","");} else {$("#email").css("border","1px solid red");}return flag;}//然后要进行异步的ajax请求//当失去焦点的时候,就要进行一个检验//利用jquery来实现ajax对吗$(function(){//当表单提交的时候,我们要干嘛//是不是要提交检测,也就是上面js做的一些检测函数//如果返回false,是不是就相当于说,你不能提交//获取表单,然后添加一个提交事件$("#registerForm").submit(function (){//上面函数都有一个布尔类型的值//这里进行一个联合判断return checkUsername() && checkPassword() && checkEmail();});//当失去焦点的时候,进行一个正则检查//也就是说是否符合规则//拿到这个input框框,然后给一个失去焦点的事件$("#username").blur(checkUsername);$("#password").blur(checkPassword);$("#email").blur(checkEmail);});</script></head><body><!--引入头部--><div id="header"></div><!-- 头部 end --><div class="rg_layout"><div class="rg_form clearfix"><div class="rg_form_left"><p>新用户注册</p><p>USER REGISTER</p></div><div class="rg_form_center"><!--注册表单--><form id="registerForm"><!--提交处理请求的标识符--><input type="hidden" name="action" value="register"><table style="margin-top: 25px;"><tr><td class="td_left"><label for="username">用户名</label></td><td class="td_right"><input type="text" id="username" name="username" placeholder="请输入账号"></td></tr><tr><td class="td_left"><label for="password">密码</label></td><td class="td_right"><input type="text" id="password" name="password" placeholder="请输入密码"></td></tr><tr><td class="td_left"><label for="email">Email</label></td><td class="td_right"><input type="text" id="email" name="email" placeholder="请输入Email"></td></tr><tr><td class="td_left"><label for="name">姓名</label></td><td class="td_right"><input type="text" id="name" name="name" placeholder="请输入真实姓名"></td></tr><tr><td class="td_left"><label for="telephone">手机号</label></td><td class="td_right"><input type="text" id="telephone" name="telephone" placeholder="请输入您的手机号"></td></tr><tr><td class="td_left"><label for="sex">性别</label></td><td class="td_right gender"><input type="radio" id="sex" name="sex" value="男" checked> 男<input type="radio" name="sex" value="女"> 女</td></tr><tr><td class="td_left"><label for="birthday">出生日期</label></td><td class="td_right"><input type="date" id="birthday" name="birthday" placeholder="年/月/日"></td></tr><tr><td class="td_left"><label for="check">验证码</label></td><td class="td_right check"><input type="text" id="check" name="check" class="check"><img src="checkCode" height="32px" alt="" onclick="changeCheckCode(this)"><script type="text/javascript">//图片点击事件function changeCheckCode(img) {img.src="checkCode?"+new Date().getTime();}</script></td></tr><tr><td class="td_left"> </td><td class="td_right check"> <input type="submit" class="submit" value="注册"><span id="msg" style="color: red;"></span></td></tr></table></form></div><div class="rg_form_right"><p>已有账号?<a href="#">立即登录</a></p></div></div></div><!--引入尾部--><div id="footer"></div><!--导入布局js,共享header和footer--><script type="text/javascript" src="js/include.js"></script></body>
</html>
那么上面还有一部分我们需要修改
这里一点击注册,就必须给我们提交数据啊,也就是我们需要在这里做一个异步的ajax请求
直接改动上面的register.htm里面的这部分代码
$(function(){//当表单提交的时候,我们要干嘛//是不是要提交检测,也就是上面js做的一些检测函数//如果返回false,是不是就相当于说,你不能提交//获取表单,然后添加一个提交事件$("#registerForm").submit(function (){//上面的正则检测全部通过,就提交请求if(checkEmail() && checkPassword() && checkUsername()) {//第二个直接把表单序列化成格式字符串往服务器传递$.post("registUserServlet",$(this).serialize(),function(data){});}//上面没有通过,这里就不提交表单,直接返回falsereturn false;});
也就是说,上面的页面是往registUserServlet提交的,那么我们就要后台实现这个页面
我们知道一个servlet页面后面都会跟着访问servcie层,然后访问dao层,所以这里先把每一个层的文件实现出来,就是这个图下面的所有文件
把相应的文件先全部创建出来
先来做RegistUserServlet文件
package web.servlet;import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import service.UserService;
import service.impl.UserServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//获取从前端传过来的数据Map<String,String[]> map = request.getParameterMap();//把这些集合数据封装成一个对象//这里利用BeanUtils工具User user = new User();//这个user类之前就已经做好了try {BeanUtils.populate(user,map);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}//调用service中的方法完成注册UserService service = new UserServiceImpl();//内部我们先假定存在一个regist方法boolean flag = service.regist(user);//响应结果}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}
代码写到上面这样,我们就必须来说一下,我们假定了一个regist方法在service里面,那么我们就要去到service里面实现这样的方法
去到我们的UserService里面
package service;import domain.User;public interface UserService {/*** @describe 注册用户* @param user* @return*/boolean regist(User user);
}
然后在UserServiceImpl里面实现这个方法
package service.impl;import domain.User;
import service.UserService;public class UserServiceImpl implements UserService {/*** @describe 注册用户* @param user* @return*/@Overridepublic boolean regist(User user) {//这里大致分成两步走,每一步都对应dao的两个功能//第一步根据用户名来查询对象//第二步保存用户信息return false;}
}
当我们去分析service里面的regist方法的时候,发现需要去调用dao层的两个方法,一个是通过用户名来查询用户,另外一个是保存用户信息,那么我们又要去到dao层实现这两个方法
先来看UserDao
package dao;import domain.User;public interface UserDao {/*** 通过用户名查找用户* @param name* @return*/public User findByUsername(String name);/*** 保存* @param user*/public void save(User user);
}
再去看UserDaoImpl
package dao.impl;import dao.UserDao;
import domain.User;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import util.JDBCUtils;public class UserDaoImpl implements UserDao {//这里要操作数据库,所以我们需要一个JdbcTemplate模板//这个模板大家都知道需要一个连接池Druid的连接池//我们已经在JDBCUtils里面做好了private JdbcTemplate template = new JdbcTemplate(JDBCUtils.getDataSource());/*** 根据用户名查找用户** @param name* @return*/@Overridepublic User findByUsername(String name) {//1.定义sqlString sql = "select * from tab_user where username = ?";//2.执行sql//这里必须清楚我们要用到JdbcTemplate模板中的哪一个方法//比如这里通过用户名查询只会返回一个对象,就用queryForObject(sql,BeanPropertyRowMapper)//注意这个方法存在很多重载的方法User user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), name);return user;}/*** 保存用户信息到数据库中* 这里在做数据库插入的时候,注意数据要与数据表中的数据一一匹配* @param user*/@Overridepublic void save(User user) {//1.定义sqlString sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email)" +"values (?,?,?,?,?,?,?)";//执行sql,获取响应的数据然后插进去template.update(sql,user.getUsername(),user.getPassword(),user.getName(),user.getSex(),user.getTelephone(),user.getEmail());}}
然后再去完成我们的service层,这一层主要是去调用dao层的方法
这里就是UserServiceImpl.java
package service.impl;import dao.UserDao;
import dao.impl.UserDaoImpl;
import domain.User;
import service.UserService;public class UserServiceImpl implements UserService {private UserDao userDao = new UserDaoImpl();/*** @describe 注册用户* @param user* @return*/@Overridepublic boolean regist(User user) {//这里大致分成两步走,每一步都对应dao的两个功能//第一步根据用户名来查询对象User u = userDao.findByUsername(user.getUsername());//这里需要判断一下用户是否注册成功if(u != null) {//用户名存在,注册失败return false;}//第二步保存用户信息userDao.save(u);return true;}
}
有个地方我们需要注意
这里findByUsername能不能返回null,去看一下这个位置
上面红色箭头指向的位置,会抛出一个异常,换句话也就是说,这里如果查询失败不会给我们返回一个NULL,所以必须把这个位置捕获一下异常
也就是说在UserDaoImpl文件中,把这个findByUsername方法修改一下
/*** 根据用户名查找用户** @param name* @return*/@Overridepublic User findByUsername(String name) {User user = null;//先定义一个null,等会好返回//1.定义sqlString sql = "select * from tab_user where username = ?";//2.执行sql//这里必须清楚我们要用到JdbcTemplate模板中的哪一个方法//比如这里通过用户名查询只会返回一个对象,就用queryForObject(sql,BeanPropertyRowMapper)//注意这个方法存在很多重载的方法try {user = template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), name);} catch (DataAccessException e) {e.printStackTrace();}return user;}
上面做完了之后,基本上就可以实现用户的添加注册了,把RegistUserServlet页面修改一下,因为这个页面给我们的提示信息不够完整,比如找到用户给我们返回一个什么信息,没找到用户又给我们返回一个什么信息
首先我们到domain包里面去看一个类ResultInfo
package domain;import java.io.Serializable;
import java.util.Objects;/*** 用于封装后端返回前端数据对象*/
public class ResultInfo implements Serializable {private boolean flag;//后端返回结果正常为true,发生异常返回falseprivate Object data;//后端返回结果数据对象private String errorMsg;//发生异常的错误消息//无参构造方法public ResultInfo() {}public ResultInfo(boolean flag) {this.flag = flag;}/*** 有参构造方法* @param flag* @param errorMsg*/public ResultInfo(boolean flag, String errorMsg) {this.flag = flag;this.errorMsg = errorMsg;}/*** 有参构造方法* @param flag* @param data* @param errorMsg*/public ResultInfo(boolean flag, Object data, String errorMsg) {this.flag = flag;this.data = data;this.errorMsg = errorMsg;}public boolean isFlag() {return flag;}public void setFlag(boolean flag) {this.flag = flag;}public Object getData() {return data;}public void setData(Object data) {this.data = data;}public String getErrorMsg() {return errorMsg;}public void setErrorMsg(String errorMsg) {this.errorMsg = errorMsg;}
}
上面也就是说,把后端传递给前端的信息,封装到一个对象里面,后面我们可以把这个对象转换成json对象,返回给前端,前端就可以通过这个对象来得到相应的数据,比如通过falg去判断是否查找正常,通过errorMsg来打印出相应的错误信息。
然后我们来看修改之后的RegisterUserServlet
package web.servlet;import com.fasterxml.jackson.databind.ObjectMapper;
import domain.ResultInfo;
import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import service.UserService;
import service.impl.UserServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//验证校验//获取从前端传过来的数据Map<String,String[]> map = request.getParameterMap();//把这些集合数据封装成一个对象//这里利用BeanUtils工具User user = new User();//这个user类之前就已经做好了try {BeanUtils.populate(user,map);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}//调用service中的方法完成注册UserService service = new UserServiceImpl();//内部我们先假定存在一个regist方法boolean flag = service.regist(user);//做一个信息结果返回的对象ResultInfo info = new ResultInfo();//响应结果//注册成功返回true,失败返回falseif(flag) {//成功//成功info.setFlag(true);} else {info.setFlag(false);info.setErrorMsg("注册失败");}//将info对象序列化为json对象ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(info);//将json数据写回给客户端response.setContentType("application/json;charset=utf-8");response.getWriter().write(json);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}
我们现在去把验证码的东西做一下,还是去到RegistUserServlet里面,进行一个验证码校验,这里的意思就是,验证码不通过,啥都免谈
验证码之前我们已经做好了,我们把这个CheckCodeServlet页面给贴过来
package web.servlet;import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;/*** 验证码*/
@WebServlet("/checkCode")
public class CheckCodeServlet extends HttpServlet {public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {//服务器通知浏览器不要缓存response.setHeader("pragma","no-cache");response.setHeader("cache-control","no-cache");response.setHeader("expires","0");//在内存中创建一个长80,宽30的图片,默认黑色背景//参数一:长//参数二:宽//参数三:颜色int width = 80;int height = 30;BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);//获取画笔Graphics g = image.getGraphics();//设置画笔颜色为灰色g.setColor(Color.GRAY);//填充图片g.fillRect(0,0, width,height);//产生4个随机验证码String checkCode = getCheckCode();//将验证码放入HttpSession中request.getSession().setAttribute("CHECKCODE_SERVER",checkCode);//设置画笔颜色为黄色g.setColor(Color.YELLOW);//设置字体的小大g.setFont(new Font("黑体",Font.BOLD,24));//向图片上写入验证码g.drawString(checkCode,15,25);//将内存中的图片输出到浏览器//参数一:图片对象//参数二:图片的格式,如PNG,JPG,GIF//参数三:图片输出到哪里去ImageIO.write(image,"PNG",response.getOutputStream());}/*** 产生4位随机字符串 */private String getCheckCode() {String base = "0123456789ABCDEFGabcdefg";int size = base.length();Random r = new Random();StringBuffer sb = new StringBuffer();for(int i=1;i<=4;i++){//产生0到size-1的随机值int index = r.nextInt(size);//在base字符串中获取下标为index的字符char c = base.charAt(index);//将c放入到StringBuffer中去sb.append(c);}return sb.toString();}public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doGet(request,response);}
}
下面去完善一下RegistUserServlet.java页面,加入验证码检验功能
package web.servlet;import com.fasterxml.jackson.databind.ObjectMapper;
import domain.ResultInfo;
import domain.User;
import org.apache.commons.beanutils.BeanUtils;
import service.UserService;
import service.impl.UserServiceImpl;import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;@WebServlet("/registUserServlet")
public class RegistUserServlet extends HttpServlet {protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {//验证校验String check = request.getParameter("check");//从session中获取验证码//这个是做验证码的时候,就给我们放到服务器里面了String checkcodeServer = (String)request.getSession().getAttribute("CHECKCODE_SERVER");//这里判断一下验证码是否是正确的,如果不正确,直接return结束if(checkcodeServer == null || !check.equalsIgnoreCase(checkcodeServer)) {//这里验证码错误//还是调用一个后端结果信息处理对象ResultInfo resultInfo = new ResultInfo();resultInfo.setFlag(false);resultInfo.setErrorMsg("验证码错误");//将resultInfo对象转变为json对象,响应给请求端ObjectMapper objectMapper = new ObjectMapper();String json = objectMapper.writeValueAsString(resultInfo);//设置响应格式并且传送数据response.setContentType("application/json;charset=utf-8");response.getWriter().write(json);//让程序在这个位置结束,不往下执行了return;}//获取从前端传过来的数据Map<String,String[]> map = request.getParameterMap();//把这些集合数据封装成一个对象//这里利用BeanUtils工具User user = new User();//这个user类之前就已经做好了try {BeanUtils.populate(user,map);} catch (IllegalAccessException e) {e.printStackTrace();} catch (InvocationTargetException e) {e.printStackTrace();}//调用service中的方法完成注册UserService service = new UserServiceImpl();//内部我们先假定存在一个regist方法boolean flag = service.regist(user);//做一个信息结果返回的对象ResultInfo info = new ResultInfo();//响应结果//注册成功返回true,失败返回falseif(flag) {//成功//成功info.setFlag(true);} else {info.setFlag(false);info.setErrorMsg("注册失败");}//将info对象序列化为json对象ObjectMapper mapper = new ObjectMapper();String json = mapper.writeValueAsString(info);//将json数据写回给客户端response.setContentType("application/json;charset=utf-8");response.getWriter().write(json);}protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {this.doPost(request, response);}
}
上面基本上就能够实现了数据库注册了,我们修改一下前端页面,改写异步向服务器registUserServlet页面提交数据
register.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>注册</title><link rel="stylesheet" type="text/css" href="css/common.css"><link rel="stylesheet" href="css/register.css"><!--导入jquery--><script src="js/jquery-3.3.1.js"></script><script type="text/javascript">//先来检验用户名function checkUsername() {//拿到用户名的值//这里通过jquery来获取值var username = $("#username").val();//输入框里面的值//定义一个正则,规定输入格式//这里的意思就是匹配字母数字下划线,最少8个,最多20个var regUsername = /^\w{8,20}$/;//这就是一个正则表达式对象//这里调用js对象里面的test判断字符串与正则是否匹配var flag = regUsername.test(username);//if(flag) {//输入正确,就成正常的颜色,//你这如果啥也不做,那么一旦框变红了//那就不能变回来啦$("#username").css("border","");} else {//输入错误,让边框变成红色$("#username").css("border","1px solid red");}return flag;//决定表单能否提交}//检验密码function checkPassword() {//获取密码var password = $("#password").val();//定义正则,和上面一样操作var regPassword = /^\w{8,20}$/;//用test判断var flag = regPassword.test(password);if(flag) {//也不能啥也不做$("#password").css("border","");} else {//把边框变成红色$("#password").css("border","1px solid red");}return flag;}//检验邮件function checkEmail() {//获取邮件//邮件的操作性质与上面基本一样var email = $("#email").val();var regEmail = /^\w+@\w+\.\w+$/;var flag = regEmail.test(email);if(flag) {$("#email").css("border","");} else {$("#email").css("border","1px solid red");}return flag;}//然后要进行异步的ajax请求//当失去焦点的时候,就要进行一个检验//利用jquery来实现ajax对吗$(function(){//当表单提交的时候,我们要干嘛//是不是要提交检测,也就是上面js做的一些检测函数//如果返回false,是不是就相当于说,你不能提交//获取表单,然后添加一个提交事件$("#registerForm").submit(function (){//上面的正则检测全部通过,就提交请求if(checkEmail() && checkPassword() && checkUsername()) {//第二个直接把表单序列化成格式字符串往服务器传递//通过ajax进行异步提交数据$.post("registUserServlet",$(this).serialize(),function(data){//处理服务器的响应结果//服务器给我们响应的数据});}//上面没有通过,这里就不提交表单,直接返回falsereturn false;});//当失去焦点的时候,进行一个正则检查//也就是说是否符合规则//拿到这个input框框,然后给一个失去焦点的事件$("#username").blur(checkUsername);$("#password").blur(checkPassword);$("#email").blur(checkEmail);});</script></head><body><!--引入头部--><div id="header"></div><!-- 头部 end --><div class="rg_layout"><div class="rg_form clearfix"><div class="rg_form_left"><p>新用户注册</p><p>USER REGISTER</p></div><div class="rg_form_center"><!--注册表单--><form id="registerForm"><!--提交处理请求的标识符--><input type="hidden" name="action" value="register"><table style="margin-top: 25px;"><tr><td class="td_left"><label for="username">用户名</label></td><td class="td_right"><input type="text" id="username" name="username" placeholder="请输入账号"></td></tr><tr><td class="td_left"><label for="password">密码</label></td><td class="td_right"><input type="text" id="password" name="password" placeholder="请输入密码"></td></tr><tr><td class="td_left"><label for="email">Email</label></td><td class="td_right"><input type="text" id="email" name="email" placeholder="请输入Email"></td></tr><tr><td class="td_left"><label for="name">姓名</label></td><td class="td_right"><input type="text" id="name" name="name" placeholder="请输入真实姓名"></td></tr><tr><td class="td_left"><label for="telephone">手机号</label></td><td class="td_right"><input type="text" id="telephone" name="telephone" placeholder="请输入您的手机号"></td></tr><tr><td class="td_left"><label for="sex">性别</label></td><td class="td_right gender"><input type="radio" id="sex" name="sex" value="男" checked> 男<input type="radio" name="sex" value="女"> 女</td></tr><tr><td class="td_left"><label for="birthday">出生日期</label></td><td class="td_right"><input type="date" id="birthday" name="birthday" placeholder="年/月/日"></td></tr><tr><td class="td_left"><label for="check">验证码</label></td><td class="td_right check"><input type="text" id="check" name="check" class="check"><img src="checkCode" height="32px" alt="" onclick="changeCheckCode(this)"><script type="text/javascript">//图片点击事件function changeCheckCode(img) {img.src="checkCode?"+new Date().getTime();}</script></td></tr><tr><td class="td_left"> </td><td class="td_right check"> <input type="submit" class="submit" value="注册"><span id="msg" style="color: red;"></span></td></tr></table></form></div><div class="rg_form_right"><p>已有账号?<a href="#">立即登录</a></p></div></div></div><!--引入尾部--><div id="footer"></div><!--导入布局js,共享header和footer--><script type="text/javascript" src="js/include.js"></script></body>
</html>
现在去访问注册页面,先在注册页面填写一些数据
然后点击注册就会发送一个请求到registUserServlet页面
先在去看数据库内部有没有插上这条数据
很明显就是数据插入也没有问题。
上面在处理数据的时候,没有处理数据编码问题,是因为我们已经通过filter进行过滤了,直接在filter包里面放了如下文件
CharchaterFilter.java
package web.filter;import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;/*** 解决全站乱码问题,处理所有的请求*/
@WebFilter("/*")
public class CharchaterFilter implements Filter {@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest req, ServletResponse rep, FilterChain filterChain) throws IOException, ServletException {//将父接口转为子接口HttpServletRequest request = (HttpServletRequest) req;HttpServletResponse response = (HttpServletResponse) rep;//获取请求方法String method = request.getMethod();//解决post请求中文数据乱码问题if(method.equalsIgnoreCase("post")){request.setCharacterEncoding("utf-8");}//处理响应乱码response.setContentType("text/html;charset=utf-8");filterChain.doFilter(request,response);}@Overridepublic void destroy() {}
}
下面我们要去做如下部分
在register.html页面处理一下服务器响应过来的数据
这里很明显servlet会给我们响应一个对象的信息的json数据的格式
在前端页面这个位置增加提示信息
好了,来说一下注册成功的情况,如果注册成功,就跳转到一个一个注册成功页面,这里我们也已经做好了register_ok.html
<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8"><title>注册</title><link rel="stylesheet" type="text/css" href="css/common.css"><link rel="stylesheet" href="css/register.css"><!--导入jquery--><script src="js/jquery-3.3.1.js"></script></head><body><!--引入头部--><div id="header"></div><!-- 头部 end --><div style="text-align:center;red:yellow;font-weight:bold;height:150px;padding-top:100px;font-size:30px;"><h4>恭喜,注册成功!请登录您的注册邮箱进行激活您的账号,激活后才能登录。</h4></div><!--引入尾部--><div id="footer"></div><!--导入布局js,共享header和footer--><script type="text/javascript" src="js/include.js"></script></body>
</html>
如果注册失败了,就给刚刚那个div,就是需要我们添加错误信息的div提示一些错误信息
现在把服务器关掉重新启动一下
我刻意把验证码写错或者把用户名写成数据库当中已经存在的用户名,并没有给我提示错误,于是去看一下控制台
发现好像给我们response的json数据也没有写错,于是再去检查一下
发现这个M应该是小写的m
然后刻意把验证码写错
如果把用户名写错,程序就会走这个地方
简单说就是用户名已经存在,就会提示注册失败这条路
刚刚我改变了一下输入验证码正确,然后用户名输入与数据库里插入的名字相同
但是发现数据有,但是回写到html页面,缺提示undefined
插入一个测试代码
看一下网页中的数据传输
发现数据是存在的,那么为什么会提示undefined呢 ?
原因就在于回写json数据的时候,没有假如如下语句
然后重新启动服务器,提示注册失败,运行成功
相关文章:

javaee之黑马旅游网1
这是一个用来锻炼javaweb基础知识的项目,先来导入一些我们准备好的文件 下面这些东西是我们项目必备的,我们提前准备好了 ,这个我会上传到我的资源,你们可以自己去下载 利用maven来创建一个项目 选择无骨架创建项目,域…...

【高并发基础】理解 MVCC 及提炼实现思想
文章目录1. 前言2. MVCC 概念2.1 MVCC 版本链2.2 MVCC trx_id2.3 MVCC Read View3. 提出问题4. 解决问题4.1 不读未提交的数据4.1.1 一般的并发情况4.1.2 特殊的并发情况4.1.3 剩下的并发情况4.2 如果自己修改了数据,要第一时间读到5. MySQL RC 使用 MVCC5.1 MVCC D…...

Flow-vue源码中的应用
认识 Flow Flow 是 facebook 出品的 JavaScript 静态类型检查工具。Vue.js 的源码利用了 Flow 做了静态类型检查,所以了解 Flow 有助于我们阅读源码。 #为什么用 Flow JavaScript 是动态类型语言,它的灵活性有目共睹,但是过于灵活的副作用…...

学习python第一天(数据类型)
关于Python的数据类型 Python数据类型包括: 数字类型,字符类型,布尔类型,空类型,列表类型,元组类型,字典类型 1、数字类型 包括:整型int 浮点型float(有小数位的都是是浮点型) 注…...

echarts:nuxt项目使用echarts
一、项目环境 nuxt 2.X vue2.X vuex webpack 二、安装 yarn add echarts 三、使用 3.1、plugins目录下创建echarts.js import Vue from vue import * as echarts from echarts // 引入echarts Vue.prototype.$echarts echarts // 引入组件(将echarts注册为全…...

认证服务-----技术点及亮点
大技术 Nacos做注册中心 把新建的微服务注册到Nacos上去 两个步骤 在配置文件中配置应用名称、nacos的发现注册ip地址,端口号在启动类上用EnableDiscoveryClient注解开启注册功能 使用Redis存验证码信息 加入依赖配置地址和端口号即可 直接注入StringRedisTempla…...

【计算机毕业设计】74.家教平台系统源码
一、系统截图(需要演示视频可以私聊) 摘 要 21世纪的今天,随着社会的不断发展与进步,人们对于信息科学化的认识,已由低层次向高层次发展,由原来的感性认识向理性认识提高,管理工作的重要性已逐…...

Hbase的SQL接口之Phoenix使用心得
PHOENIX 官方定义 A SQL layer over HBase delivered as a client-embedded JDBC drivertargeting low latency queries over HBase data 不同于Hive on HBase的方式,Phoenix将Query Plan直接使用HBaseAPI实现,目的是规避MapReduce框架,减少…...

Springboot萌宠社交分享系统的设计与实现hfdwz计算机毕业设计-课程设计-期末作业-毕设程序代做
Springboot萌宠社交分享系统的设计与实现hfdwz计算机毕业设计-课程设计-期末作业-毕设程序代做 【免费赠送源码】Springboot萌宠社交分享系统的设计与实现hfdwz计算机毕业设计-课程设计-期末作业-毕设程序代做本源码技术栈: 项目架构:B/S架构 开发语言…...

线性代数与解析几何——Part4 欧式空间 酉空间
线性代数与解析几何——Part4 欧式空间 & 酉空间 1. 欧氏空间 1. 定义 & 性质2. 内积表示与标准正交基3. 欧氏空间的同构4. 欧氏空间的线性变换5. 欧氏空间的子空间 2. 酉空间 1. 定义 & 性质2. 酉变换3. Hermite变换4. 规范变换 1. 欧氏空间 1. 定义 & 性质…...

带头双向循环链表的实现
目录前言节点声明链表的初始化尾插打印链表头插尾删头删查找节点指定位置插入指定位置删除链表销毁前言 之前讲过单链表的实现,在实现的过程中,我们会发现每次删除或者在前面插入节点的时候,都要提前保存上一个节点的地址。这样做十分麻烦&a…...

07【C语言 趣味算法】最佳存款方案(采用 从后往前 递推解决)
目录 一、前情回顾二、Problem:最佳存款方案2.1 Description of the problem2.2 Analysis of the problem2.3 Algorithm design2.4 The complete code and the results of the run(完整的代码 以及 运行结果)一、前情回顾 06【C语言 & 趣味算法】牛顿迭代法求方程根(可…...

游戏开发36课 cocoscreator scrollview优化
在cocoscreator内,ScrollView控件封装的挺完美的了,不过对于一些对性能要求比较高的场景,会存在问题,以top100排行榜排行榜举例子 1、应用卡顿甚至崩溃 按照官方用例使用ScrollView,插入100个玩家的item,理…...

屏幕开发学习 -- 迪文串口屏
一 前言 最近学习了一款基于图形化开发的屏幕,在摸索一周后,基本熟悉了这款产品的一个开发过程,今天给大家分享一下迪文串口屏的学习过程,有不足之处,还请见谅😁,包含了环境搭建和功能DEMO 二 …...

微机-------CPU与外设之间的数据传送方式
目录 一、无条件方式二、查询方式三、中断方式四、DMA方式一、无条件方式 外设要求:简单、数据变化缓慢。 外设被认为始终处于就绪状态。始终准备好数据或者始终准备好接收数据。 IN AL,数据端口 数据端口的地址通过CPU的地址总线送到地址译码器进行译码,同时该指令进行的是…...

从源码上解决rosdep update失败问题
(一)卸载官方的rosdep、rosdistro 卸载rosdistro # python2 sudo apt-get purge python-rosdistro# python3 sudo apt-get purge python3-rosdistro卸载rosdep # python2 sudo apt-get purge python-rosdep# python3 sudo apt-get purge python3-rosd…...

常用的shell命令
常用的shell命令 1、ls命令 功能:显示文件和目录的信息 ls 以默认方式显示当前目录文件列表 ls -a 显示所有文件包括隐藏文件 ls -l 显示文件属性,包括大小,日期,符号连接,是否可读写及是否可执行 ls -lh 显示文件的…...

新手入门SLAM必备资料
新手入门SLAM必备资料 文章目录 新手入门SLAM必备资料一、SLAM学习书籍1.必读经典2.有很多期,跟着会议一起出的文集3.入门书籍,简单实现及代码4.SLAM入门教材吐血推荐,对深入理解SLAM实质非常有帮助5.作者Joan Sola关于Graph-SLAM的教程,包含位姿变换、传感器模型、图优化以…...

如何选择和使用腾讯云服务器的方法新手教程
本文将介绍如何选择和使用腾讯云服务器的方法新手教程。云服务器能帮助快速构建更稳定、安全的应用,降低开发运维的难度和整体IT成本。腾讯云CVM云服务器提供多种类型的实例、操作系统和软件包。各实例中的 CPU、内存、硬盘和带宽可以灵活调整,以满足应用…...

亚马逊云科技re:Invent:Serverless是所有构想的核心
12月2日,2022亚马逊云科技re:Invent全球大会上,Amazon.com副总裁兼首席技术官Werner Vogels博士向开发者们展示了另一种可能。在一系列Serverless工具的帮助下,一些代码可以少写,因为未来你可能再也不需要写它们了。这恐怕是自云原…...

数据链路层(必备知识)
文章目录1、数据链路层的作用2、认识以太网<1>以太网帧格式<2>认识MAC地址<3>认识MTU<4>查看硬件地址和MTU3、ARP协议<1>什么是ARP协议<2>ARP数据报格式<3>ARP协议的工作机制4、其他重要协议或技术<1> DNS<2>NAT技术1、…...

【Spring系列】- Spring循环依赖
Spring循环依赖 😄生命不息,写作不止 🔥 继续踏上学习之路,学之分享笔记 👊 总有一天我也能像各位大佬一样 🏆 一个有梦有戏的人 怒放吧德德 🌝分享学习心得,欢迎指正,大…...

Python学习基础笔记二十一——迭代器
列表,我们使用for循环来取值,我们把每个值都取到,不需要关心每一个值的位置,因为只能顺序的取值,并不能跳过任何一个去取其他位置的值。那么我们为什么可以使用for循环来取值,for循环内部是怎么工作的呢&am…...

【云原生之Docker实战】使用docker部署IT资产管理系统GLPI
【云原生之Docker实战】使用docker部署IT资产管理系统GLPI 一、GLPI介绍1.GLPI简介2.GLPI功能二、检查本地docker环境1.检查docker版本2.检查docker状态三、下载GLPI镜像四、编辑docker-compose.yaml文件五、部署GLPI系统1.创建数据目录2.使用docker compose创建容器应用3.查看…...

【SSM框架 二】Spring
文章目录二、Spring1、简介2、IOC理论思想3、Hello Spring4、IOC创建对象的方式4.1 无参构造构造器注入4.2 有参构造器注入5、Spring的配置5.1 别名5.2 Bean的配置5.3 import6、DI依赖注入6.1 构造方法注入6.2 set方法注入6.3 扩展注入6.4、Bean的作用域7、Bean的自动装配7.1 正…...

基于java+ssm+vue+mysql的社区流浪猫狗救助网站
项目介绍 随着迅速的发展,宠物饲养也较以前发生很大的变化,社区流浪猫狗救助网站系统以其独有的优势脱颖而出。“社区流浪猫狗救助网站”是以JAVA程序设计语言课为基础的设计出适合社区流浪猫狗救助网站,其开发过程主要包括后台数据库的建立…...

推特营销引流入门指南
一、关注 当您关注另一个Twitter用户时,您进行订阅,即可立即阅读其内容分享。因此,请评估您关注的人,尤其是刚开始时。跟踪新用户的一种简单方法是找到他们的个人资料,然后单击“关注”按钮。 Twitter对于那些疯狂点…...

Seata概述基础
分布式事务原因: 单体架构的spring事务不能跨机器,不能跨数据源 分布式事务的概念: 一个业务流程,在分布式系统(微服务)中,每个业务模块都是一个分支,保证每个业务分支一起成功&am…...

Python学习基础笔记二十二——生成器
一个包含yield关键字的函数就是一个生成器函数。yield可以为我们从函数中返回值,但是yield又不同于return,return的执行意味着程序的结束,调用生成器函数不会得到返回的具体的值,而是得到一个可迭代的对象。每一次获取这个可迭代对…...

python -- PyQt5(designer)中文详细教程(四)事件和信号
事件 signals and slots也 被其他⼈翻译成信号和槽机制。 所有的应用都是事件驱动的。事件大部分都是由用户的行为产⽣的,当然也有其他的事件产生方式,比如网络的连接,窗口管理器或者定时器等。调⽤应⽤的exec_()⽅法时,应⽤会进⼊…...

你绝对想象不到的端对端通信的几种方式
一、前言 今天要和大家说的是我们常用的一些端对端的通信方式,这里我们会以python和php语言为主,举例说明客户端、浏览器端和服务器端通信,部分代码可能展示不全,不过我会放在文末链接供大家下载测试,下面我们先来让大…...

序列化--Serial
序列化:将数据结构或对象转换成二进制串的过程。 反序列化:将在序列化过程中所生成的二进制串转换成数据结构或者对象的过程。 Parcelable 与 Serializeable 的区别 SerializableParcelable通过IO对硬盘操作,速度较慢直接在内存操作&#x…...

BDD - SpecFlow ExternalData Plugin 导入外部测试数据
BDD - SpecFlow ExternalData Plugin 导入外部测试数据引言SpecFlow ExternalData 插件支持的数据源Tags实践创建一个 Class Libary Project添加 NuGet Packages添加测试数据源文件CSV 文件Excel 文件添加 Feature 文件实现 Step Definition执行Scenario 导入测试数据源Scenari…...

[Power Query] 日期和时间处理
Power Query查询编辑器为日期和时间数据提供了强大而快捷的处理方式 例1: 从日期中提取年、月份、日、季度、周、天等信息 数据源 步骤1:将数据源导入到Power BI Desktop,单击【转换数据】选项,进入Power Query查询编辑器界面 步骤2:选中"日期&qu…...

设计模式之抽象工厂模式
利用反射技术简单梳理抽象工厂模式 工厂模式实现 通常我们在实际工作中,经常遇到需要访问数据库的场景。 而常见的数据库又多种多样,怎么样针对不同的数据库来建立不同的数据库连接呢? 我们可以看下用抽象工厂模式加上反射技术来如何实现。…...

JavaWeb_第5章_会话技术_Cookie+Session
JavaWeb_第5章_会话技术_CookieSession 文章目录JavaWeb_第5章_会话技术_CookieSession1,会话跟踪技术的概述2,Cookie2.1 Cookie的基本使用2.2 Cookie的原理分析2.3 Cookie的使用细节2.3.1 Cookie的存活时间2.3.2 Cookie存储中文3,Session3.1…...

跟着实例学Go语言(一)
本教程全面涵盖了Go语言基础的各个方面。一共80个例子,每个例子对应一个语言特性点,非常适合新人快速上手。 教程代码示例来自go by example,文字部分来自本人自己的理解。 本文是教程系列的第一部分,共计20个例子、约1万字。 目…...

数据库基础 - 数据类型、关键字、cmd中操作数据库的命令
cmd中操作数据库的命令 mysql -hlocalhost -用户名 -密码 show database;查询数据库中的小数据库 show 数据库名;查询某一个小数据库 show 表名;查询表的结构 exit 退出数据类型 数值类型 int :整形 double:双精度&…...

2022SDNU-ACM结训赛题解
首先感谢一下各位出题人的精心准备、验题人的辛勤付出、以及选手的积极参加 题解 Problem A 柳予欣的归来【数学】 出题人: bhq 没想到一血是被打完山大的牛客比赛后来结训赛玩的wyx拿走的! 题目描述: 计算(∑0<d<pd−1)m(\sum_{0…...

《人类简史》笔记三—— 历史从无正义
目录 一、尽管把人人生而平等喊得震天响,其实还是把人分成了上下等级 二、恶性循环 三、当男人究竟有什么好的? 一、尽管把人人生而平等喊得震天响,其实还是把人分成了上下等级 古时候: 上等人 平民和奴隶 现在:…...

Python实现基于用户的协同过滤推荐算法构建电影推荐系统
说明:这是一个机器学习实战项目(附带数据代码文档视频讲解),如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 基于用户的协同过滤推荐(User-based CF)的原理假设:跟你喜好相似的人…...

阿里巴巴专场——第322场周赛题解
目录 模拟法:6253.回环句 排序后模拟:6254. 划分技能点相等的团队 BFS:6255. 两个城市间路径的最小分数 BFS:6256. 将节点分成尽可能多的组 模拟法:6253.回环句 这道题直接按照题目的意思暴力模拟即可:…...

【机器学习】支持向量回归
有任何的书写错误、排版错误、概念错误等,希望大家包含指正。 在阅读本篇之前建议先学习: 【机器学习】支持向量机【上】硬间隔 【机器学习】支持向量机【下】软间隔与核函数 支持向量回归 支持向量回归(support vector regression…...

Linux安装mysql
1、 查看是否已经安装 Mysql rpm -qa | grep mysql 如果你查看出来有东西,可以使用下面命令将其删除 rpm -e 文件名 2 、下载官方 Mysql 包 wget -i -c http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm 如果安装有提示:Cannot…...

JeecgBoot搭建(低代码)
环境安装 后端:JDK: 1.8 (小于11)、Maven: 3.5、MySql: 5.7、Redis: 3.2 前端:Node Js: 14.18 / 16、Npm: 5.6.0、Yarn: 1.21.1 、Pnpm 工具: IDEA、Navicat、Git、TortoiseGit拉取代码 后端:git clone https://gitee.com/jeecg/…...

【java】3-获取线程引用与线程的属性
1.获取线程的引用 在创建一个线程之后,我们很有必要去获取当前线程实例的引用,以便能够观察到线程的一些属性,或是对于当前线程进行一系列的操作 调用Thread类的静态方法currentThread,我们便能拿到当前线程的引用 Thread.curr…...

2022-12-04一周学习
这周基本上还是在对前端学习的更多一点,主要是之前没有重视vue3的学习,现在在补上来,学习了vue3的一些知识,前端的权限管理,设置路由守卫,pinia,还学习了redis的一些基本操作,之前只是照搬了别人…...

CG-34 浊度传感器 简单说明
产品概述 浊度传感器是一种智能监测水中悬浮物对光线透过时所发生的阻碍程度的仪器。允许在水中的测量点进行无人值守的操作。采用自清洗设计,可清除水中附着物以及气泡聚集而影响测量结果。具有优异的抗污染能力,即使恶劣的环境长期在线监测,…...

跟着实例学Go语言(二)
本教程全面涵盖了Go语言基础的各个方面。一共80个例子,每个例子对应一个语言特性点,非常适合新人快速上手。 教程代码示例来自go by example,文字部分来自本人自己的理解。 本文是教程系列的第二部分,共计20个例子、约1.2万字。 …...

linux+window+macos下的JDK安装
1. Linux中安装JDK (1)下载Linux版本的jdk压缩包 (2)解压 tar -zxvf 压缩包名 例如: tar -zxvf jdk-8u251-linux-x64.tar.gz(3)在系统配置文件配置java 编辑profile配置文件 vim /etc/prof…...

gitlab注册无中国区电话验证问题
众所周知gitlab对中国区不友好,无法直接注册,页面无法选择86的手机号进行验证码发送。 Google上众多的方案是修改dom,而且时间大约是21年以前。 修改dom,对于现在的VUE、React框架来说是没有用的,所以不用尝试。 直接看…...

CentOS 7 mini 运行环境搭建与测试——CentOS Mini 安装ifconfig工具【云原生开发部署实践笔记】
云原生开发部署实践笔记 一、开发测试环境搭建与测试 1.1 Linux运行环境的搭建与测试 虽然CentOS已经更新到Stream 9 版本,但基于大多数企业和单位多数使用CentOS 7版本作为运行底座,7版本也一直在更行维护,此实践基于CentOS 7 Mini版本搭…...

Python:核心知识点整理大全7-笔记
目录 4.2.5 遗漏了冒号 4.3 创建数值列表 4.3.1 使用函数 range() 4.3.2 使用 range()创建数字列表 结果如下: 4.3.3 对数字列表执行简单的统计计算 4.3.4 列表解析 4.4 使用列表的一部分 4.4.1 切片 4.4.2 遍历切片 4.4.3 复制列表 4.2.5 遗漏了冒号 fo…...

Python中的Map()函数
包含一个迭代参数 map函数的语法如下:函数是Python中的一个内置函数,它的主要功能是将给定的一个函数应用于一个或多个可迭代对象(如列表、元组、字典等)的每个元素。map函数返回一个迭代器,该迭代器将函数应用于输入的…...

[PyTorch][chapter 4][李宏毅深度学习][Gradient Descent]
前言: 目录: 1: 梯度下降原理 2: 常见问题 3: 梯度更新方案 4: 梯度下降限制 一 梯度下降原理 机器学习的目标找到最优的参数,使得Loss 最小 为什么顺着梯度方向loss 就能下降了。主要原理是泰勒公式。 假设损失函数为 忽略二阶导数, 当 …...

springboot项目使用Layui作为前端UI的一系列前后端交互的解决方法
背景: 因为比较喜欢Layui,因为多个项目都是从零开始就使用的layui开发的,并且开发过程中借鉴了很多其他项目(如Ruoyi、Pear Admin),因此最终选用大部分Pear Admin的项目中使用的一系列解决方案,…...