开发约定
为了项目管理,不会从客户端直接发送请求到jsp页面,会先请求到Servlet,在由Servlet转发到JSP页面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YEyg1UiC-1606743493377)(用户注册开发流程.png)]
要求
- 对用户名进行校验
- 对密码进行确认
- 对手机好进行校验
- 验证码,可点击切换
- 注册成功,储存用户信息,并向邮箱发送激活邮件
步骤
判断用户名是否存在
- 在register.jsp页面中,为输入用户绑定失去焦点事件
<script>
$(function () {
//页面加载完毕为id为username文本框绑定失去焦点事件
$("#username").blur(function () {
//获取到用户输入的信息
var inputUsername = $(this).val();
//发送Ajax,并传递参数usename:intputUsername
$.get("userServlet?method=userExists", {username: inputUsername}, function (data) {
//alert(data);
var span = $("#username_span");
if (data.userExsit) {
span.css("color", "red");
span.html(data.msg);
} else {
span.css("color", "green");
span.html(data.msg);
}
});
});
});
</script>
- 编写UserServlet,添加useExists方法
//判断用户名是否存在
public void userExists(HttpServletRequest request, HttpServletResponse response) throws IOException, SQLException {
//设置编码
response.setContentType("application/json;charset=utf-8");
//获取请求参数
String username = request.getParameter("username");
//创建HashMap,保存键值对{userExsit:Boolean}、{msg:String}
HashMap<String, Object> map = new HashMap<>();
//调用业务层,查询用户名是否存在数据库
UserService userService = new UserServiceImp();
User user = userService.findUserByUsreName(username);
if (user != null) {
map.put("userExsit", true);
map.put("msg", "此用户名太受欢迎,请更换一个");
} else {
map.put("userExsit", false);
map.put("msg", "用户名可用");
}
//将map转为json
ObjectMapper objectMapper = new ObjectMapper();
//并且传递到客户端
objectMapper.writeValue(response.getWriter(), map);
}
- 在UserDao接口实现类里面添加查询用户方法,查询数据库中是否用在用户名为xxx的用户
public User findUserByUsreName(String um) {
try {
//1、编写sql
String sql="select * from user where username=?";
//2、调用query方法
return template.queryForObject(sql,
new BeanPropertyRowMapper<>(User.class),
um);
} catch (DataAccessException e) {
e.printStackTrace();
return null;
}
}
确认两次密码输入是否一致
<script>
$(function () {
//页面加载完毕为id为username文本框绑定失去焦点事件
$("#confirmpwd").blur(function () {
//获取到用户输入的信息
var confirmpwd = $(this).val();
var inputPassword = $("#inputPassword").val();
var span = $("#confirmpwd_span");
if (confirmpwd === inputPassword && confirmpwd != null && inputPassword != null) {
span.css("color", "green");
span.html("密码输入通过");
} else {
span.css("color", "red");
span.html("两次密码不一致,请重新输入");
}
});
});
</script>
<script>
$(function () {
//页面加载完毕为id为username文本框绑定失去焦点事件
$("#inputPassword").blur(function () {
//获取到用户输入的信息
var confirmpwd = $(this).val();
var inputPassword = $("#confirmpwd").val();
var span = $("#confirmpwd_span");
if (confirmpwd === inputPassword && confirmpwd != null && inputPassword != null) {
span.css("color", "green");
span.html("密码输入通过");
} else {
span.css("color", "red");
span.html("两次密码不一致,请重新输入");
}
});
});
</script>
校验手机号码
<script>
$(function () {
//页面加载完毕为id为username文本框绑定失去焦点事件
$("#myPhone").blur(function () {
var myreg=/^[1][3,4,5,6,7,8,9][0-9]{9}$/;
var span = $("#phone_span");
if (!myreg.test($("#myPhone").val())) {
span.css("color", "red");
span.html("请输入正确手机号");
}else {
span.html("");
}
});
});
</script>
验证码
- 编写生成验证码方法
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//1、创建一对象,在内存中图片(验证码图片对象)
int width = 100;
int height = 34;
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
//2、美化图片
//2.1填充背景色
Graphics graphics = bufferedImage.getGraphics();//画笔对象
graphics.setColor(Color.PINK);//设置画笔颜色
graphics.fillRect(0, 0, width, height);
//2.2画边框
graphics.setColor(Color.blue);
graphics.drawRect(0, 0, width - 1, height - 1);
//2.3写验证码
String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnoppqrstuvwxyz0123456789";
StringBuilder stringBuilder = new StringBuilder();
for (int i = 1; i < 5; i++) {
Random random = new Random();
int index = random.nextInt(str.length());
char c = str.charAt(index);
//将生成的验证码,存入session
stringBuilder.append(c);
String checkCodeSession = stringBuilder.toString();
req.getSession().setAttribute("checkCodeSession", checkCodeSession);
graphics.drawString(c + "", width / 5 * i, height / 2);
}
//2.4画干扰线
for (int j = 0; j < 5; j++){
int x1 = new Random().nextInt(width);
int x2 = new Random().nextInt(width);
int y1 = new Random().nextInt(height);
int y2 = new Random().nextInt(height);
graphics.drawLine(x1, y1, x2, y2);
}
//3、将图片输出到页面展示
ImageIO.write(bufferedImage, "jpg", resp.getOutputStream());
}
- 为验证码图片绑定点击事件
主要思路是,每次点击访问的路径传递不同参数,为保证每次传递参数不同,通过给路径加时间戳来实现。
<script>
window.onload = function () {
//点击更新验证码
document.getElementById("checkCodeImg").onclick = function () {
this.src = "${pageContext.request.contextPath}/checkCodeServlet?time=" + new Date().getTime();
};
var span = $("#submit_span");
span.css("color","red");
span.html("${requestScope.registCheckCodeError}");
}
</script>
用户注册
- 信息输入正确后,点击注册提交表单,接收表单数据,存入数据库
//用户注册
public String userRegist(HttpServletRequest request, HttpServletResponse response) throws IOException, SQLException {
//1、设置编码
request.setCharacterEncoding("utf-8");
//2、获取输入验证码参数
String inputCheckCode = request.getParameter("checkCode");
//3、获取生成验证码
HttpSession session = request.getSession();
String checkCodeSession = (String) session.getAttribute("checkCodeSession");
//4、移除session中存储的验证码
session.removeAttribute("checkCodeSession");
//验证码输入正确,接收用户数据,开始注册
if (checkCodeSession != null && checkCodeSession.equalsIgnoreCase(inputCheckCode)) {
//1_接受用户数据,
User user = MyBeanUtils.populate(User.class, request.getParameterMap());
//2_部分数据是通过程序来设置的:uid,state,code
user.setUid(UUIDUtils.getId());
user.setState(0);
user.setCode(UUIDUtils.getUUID64());
//3_调用业务层注册功能,向用户邮箱发送一份激活邮件
UserService userService = new UserServiceImp();
userService.userRegist(user);
//4_向客户端提示:用户注册成功,请激活,转发到提示页面
request.setAttribute("msg", "用户注册成功,请激活!");
return "/jsp/info.jsp";
} else {
//存储提示信息到request
request.setAttribute("registCheckCodeError", "验证码错误");
return "/jsp/register.jsp";
}
}
- 在UserDao接口实现类里面添加插入用户方法,向数据库添用户
public void userRegist(User user) {
try {
String sql = "INSERT INTO USER VALUES(?,?,?,?,?,?,?,?,?,?)";
Object[] params = {user.getUid(), user.getUsername(), user.getPassword(), user.getName(), user.getEmail(), user.getTelephone(), user.getBirthday(), user.getSex(), user.getState(), user.getCode()};
template.update(sql, params);
} catch (DataAccessException e) {
e.printStackTrace();
}
}
- 业务层,发送激活邮件
public void userRegist(User user01) throws SQLException {
//3_调用业务层注册功能
UserDao.userRegist(user01);
try {
//向用户邮箱发送一份激活邮件
MailUtils.sendMail(user01.getEmail(), user01.getCode());
} catch (Exception e) {
e.printStackTrace();
}
}
//邮箱工具类
public class MailUtils {
public static void sendMail(String email, String emailMsg) throws AddressException, MessagingException {
// 1.创建一个程序与邮件服务器会话对象 Session
Properties props = new Properties();
//设置发送的协议
//props.setProperty("mail.transport.protocol", "SMTP");
//设置发送邮件的服务器
//props.setProperty("mail.host", "smtp.126.com");
//props.setProperty("mail.smtp.auth", "true");// 指定验证为true
// 创建验证器
Authenticator auth = new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
//设置发送人的帐号和密码
return new PasswordAuthentication("admin@mall.com", "admin");
}
};
Session session = Session.getInstance(props, auth);
// 2.创建一个Message,它相当于是邮件内容
Message message = new MimeMessage(session);
//设置发送者
message.setFrom(new InternetAddress("admin@mall.com"));
//设置发送方式与接收者
message.setRecipient(Message.RecipientType.TO, new InternetAddress(email));
//设置邮件主题
message.setSubject("用户激活");
// message.setText("这是一封激活邮件,请<a href='#'>点击</a>");
String url="http://localhost:8080/mall/userServlet?method=active&code="+emailMsg;
String content="<h1>来自xxx商城的激活邮件!激活请点击以下链接!</h1><h3><a href='"+url+"'>"+url+"</a></h3>";
//设置邮件内容
message.setContent(content, "text/html;charset=utf-8");
// 3.创建 Transport用于将邮件发送
Transport.send(message);
}
}
用户激活
- 用户点击邮件链接即可激活成功,激活成功后跳转到登录页面,并提示:用户激活成功,请登录
public String active(HttpServletRequest request, HttpServletResponse response) throws Exception {
//服务端获取到激活码,和数据库中已经存在的激活码对比,如果存在,激活成功,更改用户激活状态1,转发到登录页面,提示:激活成功,请登录.
String code = request.getParameter("code");
//调用业务层功能:根据激活码查询用户 select * from user where code=?
UserService userService = new UserServiceImp();
Boolean flag = userService.userActive(code);
//如果用户不为空,激活码正确的,可以激活
if (flag) {
//转发到登录页面,提示:激活成功,请登录
request.setAttribute("msg", "用户激活成功,请登录");
return "/jsp/login.jsp";
} else {
//用户激活失败,向request放入提示信息,转发到提示页面
request.setAttribute("msg", "用户激活失败,请重新激活!");
return "/jsp/info.jsp";
}
}
- 业务层,根据激活码查询是否存在用户,存在则表示验证码正确,更新用户信息
public Boolean userActive(String code) throws SQLException {
User user01 = UserDao.userActive(code);
if (user01 != null){
//可以根据激活码查询到一个用户
//修改用户的状态,清除激活码
user01.setState(1);
user01.setCode(null);
UserDao.updateUser(user01);
return true;
}else {
//激活码不存在
return false;
}
}
- Dao层
- 查询激活码是否存在
public User userActive(String code) { String sql = "select * from user where code =?"; return template.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), code); }
- 更新用户信息
public void updateUser(User user01) { String sql = "UPDATE USER SET username= ? ,PASSWORD=? ,NAME =? ,email =? ,telephone =? , birthday =? ,sex =? ,state= ? , CODE = ? WHERE uid=?"; Object[] params = {user01.getUsername(), user01.getPassword(), user01.getName(), user01.getEmail(), user01.getTelephone(), user01.getBirthday(), user01.getSex(), user01.getState(), user01.getCode(), user01.getUid()}; template.update(sql, params); }
- 注意
- 中文乱码问题
request.setAttribute()中文乱码,编码不一致导致,检查.idea中encodings.xml文件,看设置的编码格式是否和你设置编码格式一致。 - sql语句含多个参数
//单个参数 template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), param);
//多个参数 template.update(sql, Object[]);