JavaWeb25.3【综合案例:注册功能(含邮箱激活账号)】
register.html

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <title>注册</title> 6 <link rel="stylesheet" type="text/css" href="css/common.css"> 7 <link rel="stylesheet" href="css/register.css"> 8 <!--导入jquery--> 9 <script src="js/jquery-3.3.1.js"></script> 10 <script> 11 /* 12 表单校验: 13 1.用户名:单词字符,长度8到20位 14 2.密码:单词字符,长度8到20位 15 3.email:邮件格式 16 4.姓名:非空 17 5.手机号:手机号格式 18 6.出生日期:非空 19 7.验证码:非空 20 */ 21 22 function checkUsername() { 23 //1.获取用户名值 24 var username = $("#username").val(); 25 //2.定义正则 26 var reg_username = /^\w{8,20}$/; 27 //3.判断,给出提示信息 28 var flag = reg_username.test(username); 29 if(flag){ 30 //用户名合法 --> 加一个绿色边框 31 // $("#username").css("border",""); //或者清空边框样式恢复原样也行 32 $("#username").css("border","1px solid green"); 33 }else{ 34 //用户名非法 --> 加一个红色边框 35 $("#username").css("border","1px solid red"); 36 } 37 return flag; 38 } 39 40 function checkPassword() { 41 //1.获取值 42 var password = $("#password").val(); 43 //2.定义正则 44 var reg_password = /^\w{8,20}$/; 45 //3.判断,给出提示信息 46 var flag = reg_password.test(password); 47 if(flag){ 48 //合法 --> 加一个绿色边框 49 $("#password").css("border","1px solid green"); 50 }else{ 51 //非法 --> 加一个红色边框 52 $("#password").css("border","1px solid red"); 53 } 54 return flag; 55 } 56 57 //tips:选中代码区域 快捷键ctrl+r 输入需要被替换的词和替换词 进行局部代码替换 58 function checkEmail() { 59 //1.获取值 60 var email = $("#email").val(); 61 //2.定义正则 62 var reg_email = /^\w+@\w+\.\w+$/; 63 //3.判断,给出提示信息 64 var flag = reg_email.test(email); 65 if(flag){ 66 //合法 --> 加一个绿色边框 67 $("#email").css("border","1px solid green"); 68 }else{ 69 //非法 --> 加一个红色边框 70 $("#email").css("border","1px solid red"); 71 } 72 return flag; 73 } 74 75 function checkName() { 76 //1.获取值 77 var name = $("#name").val(); 78 //2.判断是否为空 79 var flag = false; 80 if (name!=null && name!=""){ 81 flag = true; 82 } 83 //3.给出提示信息 84 if(flag){ 85 $("#name").css("border","1px solid green"); 86 }else{ 87 $("#name").css("border","1px solid red"); 88 } 89 return flag; 90 } 91 92 function checkTelephone() { 93 //1.获取值 94 var telephone = $("#telephone").val(); 95 //2.定义正则 96 var reg_telephone = /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/; 97 //3.判断,给出提示信息 98 var flag = reg_telephone.test(telephone); 99 if(flag){ 100 //合法 --> 加一个绿色边框 101 $("#telephone").css("border","1px solid green"); 102 }else{ 103 //非法 --> 加一个红色边框 104 $("#telephone").css("border","1px solid red"); 105 } 106 return flag; 107 } 108 109 function checkBirthday() { 110 //1.获取值 111 var birthday = $("#birthday").val(); 112 //2.判断是否为空 113 var flag = false; 114 if (birthday!=null && birthday!=""){ 115 flag = true; 116 } 117 //3.给出提示信息 118 if(flag){ 119 $("#birthday").css("border","1px solid green"); 120 }else{ 121 $("#birthday").css("border","1px solid red"); 122 } 123 return flag; 124 } 125 126 function checkCode() { 127 //1.获取值 128 var code = $("#check").val(); 129 //2.判断是否为空 130 var flag = false; 131 if (code!=null && code!=""){ 132 flag = true; 133 } 134 //3.给出提示信息 135 if(flag){ 136 $("#check").css("border","1px solid green"); 137 }else{ 138 $("#check").css("border","1px solid red"); 139 } 140 return flag; 141 } 142 143 $(function () { 144 //1、当表单提交时,调用所用校验方法 145 $("#registerForm").submit(function () { 146 /*//如果这个匿名函数没有返回值或者返回true,则表单提交;如果返回flase,则不提交 147 return checkUsername() && checkPassword() && checkEmail() && checkName() && checkCode() && checkBirthday() && checkTelephone();*/ 148 149 /*在此使用异步提交表单是为了获取服务器响应的数据。 150 因为我们前台使用的是html作为视图层,不能够直接从servlet相关的域对象获取值, 151 只能通过ajax获取响应数据*/ 152 //1.发送数据到服务器 153 if(checkUsername() && checkPassword() && checkEmail() && checkName() && checkCode() && checkBirthday() && checkTelephone()){ 154 //校验通过,发送ajax请求,提交表单的数据 155 $.post( 156 "registUserServlet", 157 $(this).serialize(), //用户填写的数据;.serialize()序列化表单内容为字符串,如username=zhangsan&password=123 158 function (data) { 159 //处理服务器响应的数据data:一个ResultInfo对象 160 if(data.flag){ 161 //注册成功,跳转成功页面 162 location.href="register_ok.html"; 163 }else{ 164 //注册失败,给errorMsg-div添加提示信息 165 $("#errorMsg").html(data.errorMsg); 166 } 167 }, 168 "json" 169 ); 170 } 171 //2.验证失败,不让页面跳转 172 return false; 173 }); 174 175 //2、当某个组件失去焦点时,调用对应的校验方法 176 $("#username").blur(checkUsername); 177 $("#password").blur(checkPassword); 178 $("#email").blur(checkEmail); 179 $("#name").blur(checkName); 180 $("#check").blur(checkCode); 181 $("#birthday").blur(checkBirthday); 182 $("#telephone").blur(checkTelephone); 183 }); 184 </script> 185 </head> 186 <body> 187 <!--引入头部--> 188 <div id="header"></div> 189 190 <!-- 主体 --> 191 <div class="rg_layout"> 192 <div class="rg_form clearfix"> 193 <div class="rg_form_left"> 194 <p>新用户注册</p> 195 <p>USER REGISTER</p> 196 </div> 197 <div class="rg_form_center"> 198 <div id="errorMsg" style="color: red;text-align: center"></div> 199 <!--注册表单--> 200 <form id="registerForm" action="user" method="get"> 201 <!--提交处理请求的标识符--> 202 <input type="hidden" name="action" value="register"> 203 <table style="margin-top: 25px;"> 204 <tr> 205 <td class="td_left"> 206 <label for="username">用户名</label> 207 </td> 208 <td class="td_right"> 209 <input type="text" id="username" name="username" placeholder="请输入账号"> 210 </td> 211 </tr> 212 <tr> 213 <td class="td_left"> 214 <label for="password">密码</label> 215 </td> 216 <td class="td_right"> 217 <input type="text" id="password" name="password" placeholder="请输入密码"> 218 </td> 219 </tr> 220 <tr> 221 <td class="td_left"> 222 <label for="email">Email</label> 223 </td> 224 <td class="td_right"> 225 <input type="text" id="email" name="email" placeholder="请输入Email"> 226 </td> 227 </tr> 228 <tr> 229 <td class="td_left"> 230 <label for="name">姓名</label> 231 </td> 232 <td class="td_right"> 233 <input type="text" id="name" name="name" placeholder="请输入真实姓名"> 234 </td> 235 </tr> 236 <tr> 237 <td class="td_left"> 238 <label for="telephone">手机号</label> 239 </td> 240 <td class="td_right"> 241 <input type="text" id="telephone" name="telephone" placeholder="请输入您的手机号"> 242 </td> 243 </tr> 244 <tr> 245 <td class="td_left"> 246 <label for="sex">性别</label> 247 </td> 248 <td class="td_right gender"> 249 <input type="radio" id="sex" name="sex" value="男" checked> 男 250 <input type="radio" name="sex" value="女"> 女 251 </td> 252 </tr> 253 <tr> 254 <td class="td_left"> 255 <label for="birthday">出生日期</label> 256 </td> 257 <td class="td_right"> 258 <input type="date" id="birthday" name="birthday" placeholder="年/月/日"> 259 </td> 260 </tr> 261 <tr> 262 <td class="td_left"> 263 <label for="check">验证码</label> 264 </td> 265 <td class="td_right check"> 266 <input type="text" id="check" name="check" class="check"> 267 <img src="checkCodeServlet" height="32px" alt="" onclick="changeCheckCode(this)"> 268 <script type="text/javascript"> 269 //图片点击事件 270 function changeCheckCode(img) { 271 img.src="checkCodeServlet?"+new Date().getTime(); 272 } 273 </script> 274 </td> 275 </tr> 276 <tr> 277 <td class="td_left"> 278 </td> 279 <td class="td_right check"> 280 <input type="submit" class="submit" value="注册"> 281 <span id="msg" style="color: red;"></span> 282 </td> 283 </tr> 284 </table> 285 </form> 286 </div> 287 <div class="rg_form_right"> 288 <p> 289 已有账号? 290 <a href="login.html">立即登录</a> 291 </p> 292 </div> 293 </div> 294 </div> 295 296 <!--引入尾部--> 297 <div id="footer"></div> 298 299 <!--导入布局js,共享header和footer--> 300 <script type="text/javascript" src="js/include.js"></script> 301 </body> 302 </html>
register_ok.html

1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <title>注册</title> 6 <link rel="stylesheet" type="text/css" href="css/common.css"> 7 <link rel="stylesheet" href="css/register.css"> 8 <!--导入jquery--> 9 <script src="js/jquery-3.3.1.js"></script> 10 </head> 11 <body> 12 <!--引入头部--> 13 <div id="header"></div> 14 <!-- 头部 end --> 15 <div style="text-align:center;red:yellow;font-weight:bold;height:150px;padding-top:100px;font-size:30px;"> 16 <h4>恭喜,注册成功!请登录您的注册邮箱进行激活您的账号,激活后才能登录。</h4> 17 </div> 18 <!--引入尾部--> 19 <div id="footer"></div> 20 <!--导入布局js,共享header和footer--> 21 <script type="text/javascript" src="js/include.js"></script> 22 </body> 23 </html>
RegistUserServlet

1 package cn.haifei.travel.web.servlet; 2 3 import cn.haifei.travel.domain.ResultInfo; 4 import cn.haifei.travel.domain.User; 5 import cn.haifei.travel.service.UserService; 6 import cn.haifei.travel.service.impl.UserServiceImpl; 7 import com.fasterxml.jackson.databind.ObjectMapper; 8 import org.apache.commons.beanutils.BeanUtils; 9 10 import javax.servlet.ServletException; 11 import javax.servlet.annotation.WebServlet; 12 import javax.servlet.http.HttpServlet; 13 import javax.servlet.http.HttpServletRequest; 14 import javax.servlet.http.HttpServletResponse; 15 import javax.servlet.http.HttpSession; 16 import java.io.IOException; 17 import java.lang.reflect.InvocationTargetException; 18 import java.util.Map; 19 20 @WebServlet("/registUserServlet") 21 public class RegistUserServlet extends HttpServlet { 22 protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 23 24 //验证校验码 25 String checkcode_userinput = request.getParameter("check"); //用户提交的验证码 26 HttpSession session = request.getSession(); 27 String checkcode_server = (String)session.getAttribute("CHECKCODE_SERVER");//服务器产生的验证码 28 session.removeAttribute("CHECKCODE_SERVER"); //保证后台产生得验证码一次性使用 29 if (checkcode_server==null || !checkcode_server.equalsIgnoreCase(checkcode_userinput)){ 30 //用户输入验证码错误 31 ResultInfo info = new ResultInfo(); 32 info.setFlag(false); 33 info.setErrorMsg("验证码错误!"); 34 ObjectMapper mapper = new ObjectMapper(); 35 String json = mapper.writeValueAsString(info); 36 response.setContentType("application/json;charset=utf-8"); 37 //因为json结果是字符串,所以此处用字节流或者字符流都行 38 //response.getOutputStream().write(json.getBytes()); //字节流 39 response.getWriter().write(json); //字符流 40 return; 41 }//用户输入验证码正确执行以下 42 43 44 //1 获取数据 45 Map<String, String[]> map = request.getParameterMap(); 46 47 //2 封装对象 48 User user = new User(); 49 try { 50 BeanUtils.populate(user, map); 51 } catch (IllegalAccessException e) { 52 e.printStackTrace(); 53 } catch (InvocationTargetException e) { 54 e.printStackTrace(); 55 } 56 57 //3 调用service完成注册 58 UserService service = new UserServiceImpl(); 59 boolean flag = service.regist(user); 60 61 //4 响应结果 62 ResultInfo info = new ResultInfo(); 63 if (flag){ 64 //注册成功 65 info.setFlag(true); 66 }else { 67 //注册失败 68 info.setFlag(false); 69 info.setErrorMsg("注册失败!"); 70 } 71 72 //5 将对象info序列化为json 73 ObjectMapper mapper = new ObjectMapper(); //利用jackson 74 String json = mapper.writeValueAsString(info); 75 76 //6 将json结果写回到客户端 77 response.setContentType("application/json;charset=utf-8"); 78 response.getWriter().write(json); 79 } 80 81 protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 82 this.doPost(request, response); 83 } 84 }
ResultInfo

1 package cn.haifei.travel.domain; 2 3 import java.io.Serializable; 4 5 /** 6 * 用于封装后端返回前端数据对象 7 */ 8 public class ResultInfo implements Serializable { 9 private boolean flag;//后端返回结果正常为true,发生异常返回false 10 private Object data;//后端返回结果数据对象 11 private String errorMsg;//发生异常的错误消息 12 13 //无参构造方法 14 public ResultInfo() { 15 } 16 public ResultInfo(boolean flag) { 17 this.flag = flag; 18 } 19 /** 20 * 有参构造方法 21 * @param flag 22 * @param errorMsg 23 */ 24 public ResultInfo(boolean flag, String errorMsg) { 25 this.flag = flag; 26 this.errorMsg = errorMsg; 27 } 28 /** 29 * 有参构造方法 30 * @param flag 31 * @param data 32 * @param errorMsg 33 */ 34 public ResultInfo(boolean flag, Object data, String errorMsg) { 35 this.flag = flag; 36 this.data = data; 37 this.errorMsg = errorMsg; 38 } 39 40 public boolean isFlag() { 41 return flag; 42 } 43 44 public void setFlag(boolean flag) { 45 this.flag = flag; 46 } 47 48 public Object getData() { 49 return data; 50 } 51 52 public void setData(Object data) { 53 this.data = data; 54 } 55 56 public String getErrorMsg() { 57 return errorMsg; 58 } 59 60 public void setErrorMsg(String errorMsg) { 61 this.errorMsg = errorMsg; 62 } 63 }
CheckCodeServlet

1 package cn.haifei.travel.web.servlet; 2 3 import javax.imageio.ImageIO; 4 import javax.servlet.ServletException; 5 import javax.servlet.annotation.WebServlet; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import java.awt.*; 10 import java.awt.image.BufferedImage; 11 import java.io.IOException; 12 import java.util.Random; 13 14 /** 15 * 验证码 16 */ 17 @WebServlet("/checkCodeServlet") 18 public class CheckCodeServlet extends HttpServlet { 19 public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException { 20 21 //服务器通知浏览器不要缓存 22 response.setHeader("pragma","no-cache"); 23 response.setHeader("cache-control","no-cache"); 24 response.setHeader("expires","0"); 25 26 //在内存中创建一个长80,宽30的图片,默认黑色背景 27 //参数一:长 28 //参数二:宽 29 //参数三:颜色 30 int width = 80; 31 int height = 30; 32 BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB); 33 34 //获取画笔 35 Graphics g = image.getGraphics(); 36 //设置画笔颜色为灰色 37 g.setColor(Color.GRAY); 38 //填充图片 39 g.fillRect(0,0, width,height); 40 41 //产生4个随机验证码,12Ey 42 String checkCode = getCheckCode(); 43 //将验证码放入HttpSession中 44 request.getSession().setAttribute("CHECKCODE_SERVER",checkCode); 45 46 //设置画笔颜色为黄色 47 g.setColor(Color.YELLOW); 48 //设置字体的小大 49 g.setFont(new Font("黑体",Font.BOLD,24)); 50 //向图片上写入验证码 51 g.drawString(checkCode,15,25); 52 53 //将内存中的图片输出到浏览器 54 //参数一:图片对象 55 //参数二:图片的格式,如PNG,JPG,GIF 56 //参数三:图片输出到哪里去 57 ImageIO.write(image,"PNG",response.getOutputStream()); 58 } 59 /** 60 * 产生4位随机字符串 61 */ 62 private String getCheckCode() { 63 String base = "0123456789ABCDEFGabcdefg"; 64 int size = base.length(); 65 Random r = new Random(); 66 StringBuffer sb = new StringBuffer(); 67 for(int i=1;i<=4;i++){ 68 //产生0到size-1的随机值 69 int index = r.nextInt(size); 70 //在base字符串中获取下标为index的字符 71 char c = base.charAt(index); 72 //将c放入到StringBuffer中去 73 sb.append(c); 74 } 75 return sb.toString(); 76 } 77 public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { 78 this.doGet(request,response); 79 } 80 }
UserService

1 /** 2 * 注册用户 3 * @param user 4 * @return 5 */ 6 boolean regist(User user); 7 8 /** 9 * 邮箱链接-激活用户账号 10 * @param code 11 * @return 12 */ 13 boolean active(String code);
UserServiceImpl

1 @Override 2 public boolean regist(User user) { 3 //根据用户名查询用户对象,防止重复用户名 4 User user1 = userDao.findByUsername(user.getUsername()); 5 if (user1 != null){ 6 System.out.println("用户名已存在,注册失败"); 7 return false; 8 } 9 10 //设置激活码,唯一字符串 11 user.setCode(UuidUtil.getUuid()); 12 //设置邮件链接激活状态 13 user.setStatus("N"); 14 //保存用户信息 15 userDao.save(user); 16 //发送激活邮件链接 17 String content="<a href='http://localhost/travel/activeUserServlet?code=" + user.getCode() + "'>点击激活【黑马旅游网】</a>"; 18 MailUtils.sendMail(user.getEmail(),content,"激活邮件"); 19 return true; 20 } 21 22 @Override 23 public boolean active(String code) { 24 //1 根据激活码查询用户对象 25 User user = userDao.findByCode(code); 26 if (user != null){ 27 //2 调用dao的修改激活状态方法 28 userDao.updateStatus(user); 29 return true; 30 }else { 31 return false; 32 } 33 }
UserDao

1 /** 2 * 根据用户名查询用户信息 3 * @param username 4 * @return 5 */ 6 public User findByUsername(String username); 7 8 /** 9 * 添加用户 10 * @param user 11 * @return 12 */ 13 public int save(User user); 14 15 /** 16 * 根据激活码查询用户信息 17 * @param code 18 * @return 19 */ 20 User findByCode(String code); 21 22 /** 23 * 更新用户账号的激活状态 24 * @param user 25 */ 26 void updateStatus(User user);
UserDaoImpl

1 @Override 2 public User findByUsername(String username) { 3 User user = null; 4 try { 5 String sql = "select * from tab_user where username = ?"; 6 user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), username); 7 } catch (Exception e) { 8 // e.printStackTrace(); 9 } 10 return user; 11 } 12 13 @Override 14 public int save(User user) { 15 String sql = "insert into tab_user(username,password,name,birthday,sex,telephone,email,status,code) values(?,?,?,?,?,?,?,?,?)"; 16 int count = template.update( 17 sql, 18 user.getUsername(), 19 user.getPassword(), 20 user.getName(), 21 user.getBirthday(), 22 user.getSex(), 23 user.getTelephone(), 24 user.getEmail(), 25 user.getStatus(), 26 user.getCode() 27 ); 28 return count; 29 } 30 31 @Override 32 public User findByCode(String code) { 33 User user = null; 34 try { 35 String sql = "select * from tab_user where code = ?"; 36 user = template.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), code); 37 } catch (DataAccessException e) { 38 // e.printStackTrace(); 39 } 40 return user; 41 } 42 43 @Override 44 public void updateStatus(User user) { 45 String sql = "update tab_user set status = 'Y' where uid = ?"; 46 /*int count = */template.update(sql, user.getUid()); 47 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!