JavaWeb学习笔记--day14--注册案例

day13复习 JavaWeb学习笔记--day14--注册案例
文章图片

功能分析 页面及功能概述
JSP:
login.jsp 登录页面
regist.jsp 注册页面,服务器表单验证,注册成功添加跳转到登录的超链接,验证码
Servlet
RegistServlet
VerifyCodeServlet
Service
UserException 用户异常
UserService 与用户相关的业务类
VerifyCode 验证码类,个人编写的,也可以使用itcast包中的验证码类
Dao:
JdbcUtils 数据库连接工具类,单例模式
UserDao 与用户相关的数据类
Domain:
User(对应数据库,还要对应表单)
所导jar包
JavaWeb学习笔记--day14--注册案例
文章图片

项目目录结构
JavaWeb学习笔记--day14--注册案例
文章图片

数据库设计
略,选用SQLServer,UserDemo数据库中Users(username,password)表
注册流程图
JavaWeb学习笔记--day14--注册案例
文章图片

Domain层实现 user类

/* * dao-与用户相关的实体类 * 对应数据库,还对应相应表单 */ public class User { private String username; private String password; private String verifyCode; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getVerifyCode() { return verifyCode; } public void setVerifyCode(String verifyCode) { this.verifyCode = verifyCode; } public User() { super(); } public User(String username, String password, String verifyCode) { super(); this.username = username; this.password = password; this.verifyCode = verifyCode; } @Override public String toString() { return "User [username=" + username + ", password=" + password + ", verifyCode=" + verifyCode + "]"; } }

Dao层实现 JdbcUtils类
/* * 连接SQLServer数据库的工具类 * 单例模式 */ public final class JdbcUtils { private String url = "jdbc:sqlserver://127.0.0.1:1433; DatabaseName=UserDemo"; private String user = "sa"; private String password = "123456"; private JdbcUtils() { super(); } private static JdbcUtils instance = null; //获取实例 public static JdbcUtils getInstance() { if(instance==null) { synchronized (JdbcUtils.class) {//并发知识 加锁 if(instance==null) {//双重检查 instance=new JdbcUtils(); //延迟加载 } } } return instance; } //静态代码段,实现注册驱动 static { try { Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); } catch (Exception e) { // TODO: handle exception throw new ExceptionInInitializerError(e); } } //获得连接 public Connection getConnection() throws SQLException { return DriverManager.getConnection(url, user, password); } //释放资源 public void free(ResultSet rs, PreparedStatement psmt, Connection con) { try { if(rs!=null) rs.close(); } catch (SQLException e) { e.printStackTrace(); } finally { try { psmt.close(); } catch (SQLException e) { e.printStackTrace(); } finally { try { con.close(); } catch (SQLException e) { e.printStackTrace(); } } } } }

UserDao类
/* * 与用户相关的数据类 */ public class UserDao { /* * 根据用户名查询 * 1.调用JdbcUtils获得连接 * 2.得到prepareStatement * 3.对占位符进行设值 * 4.得到结果并处理 * 5.释放资源 */ public User searchUser(String username) { Connection con = null; PreparedStatement psmt = null; ResultSet rs = null; String sql = "select * from users where username like ?"; JdbcUtils ju = JdbcUtils.getInstance(); try { con = ju.getConnection(); psmt=con.prepareStatement(sql); psmt.setString(1, username); rs = psmt.executeQuery(); User u = new User(); while(rs.next()) { u.setUsername(rs.getString(1)); u.setPassword(rs.getString(2)); } return u; } catch (SQLException e) { // TODO Auto-generated catch block throw new RuntimeException(e); } finally { ju.free(rs, psmt, con); } } /* * 插入用户 */ public void addUser(User user) { Connection con = null; PreparedStatement psmt = null; ResultSet rs = null; JdbcUtils ju = JdbcUtils.getInstance(); String addSql = "insert into users values(?,?)"; try { con = ju.getConnection(); psmt= con.prepareStatement(addSql); psmt.setString(1, user.getUsername()); psmt.setString(2, user.getPassword()); psmt.execute(); System.out.println("插入成功"); } catch (Exception e) { // TODO: handle exception throw new RuntimeException(e); } finally { ju.free(rs, psmt, con); } } }

Service层实现 UserException类
/* * 用户异常类 */ public class UserException extends Exception { public UserException() { // TODO Auto-generated constructor stub } public UserException(String arg0) { super(arg0); // TODO Auto-generated constructor stub } public UserException(Throwable arg0) { super(arg0); // TODO Auto-generated constructor stub } public UserException(String arg0, Throwable arg1) { super(arg0, arg1); // TODO Auto-generated constructor stub } }

UserService
public class UserService { UserDao ud =new UserDao(); /* * 注册功能 * 使用用户名去查询,如果返回null,完成添加 * 如果返回不是空 抛出异常 */ public void regist(User user) throws UserException { User _user = ud.searchUser(user.getUsername()); if(_user.getUsername()!=null) throw new UserException("用户名"+user.getUsername()+"已被注册"); ud.addUser(user); } }

VerifyCode类
public class VerifyCode { private int w = 70; private int h = 35; private Random r = new Random(); private String[] fontNames = {"宋体","华文楷体","微软雅黑","楷体_GB2312"}; //可选字符,无1liI; private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ"; //背景色 private Color bgColor = new Color(255,255,255); //验证码上的文本 private String text; //随机获得颜色 private Color randomColor() { int R = r.nextInt(150); int G = r.nextInt(150); int B = r.nextInt(150); return new Color(R,G,B); } //获得随机字体 private Font randomFont() { int index = r.nextInt(fontNames.length); //随机得到字体数组中的一个 String fontName = fontNames[index]; int style = r.nextInt(4); //生成随机样式:0(无样式),1(粗体),2(斜体),3(粗体加斜体) int size = r.nextInt(5)+24; //生成随机字号,24~28 return new Font(fontName, style, size); } //画干扰线 private void drawLine (BufferedImage image) { int num = 3; //一共画三条 Graphics2D g2 = (Graphics2D) image.getGraphics(); for (int i = 0; i < num; i++) {//生成两个点的坐标 int x1 = r.nextInt(w); int y1 = r.nextInt(h); int x2 = r.nextInt(w); int y2 = r.nextInt(h); g2.setStroke(new BasicStroke(1.5F)); g2.setColor(Color.BLUE); //蓝色干扰线 g2.drawLine(x1, y1, x2, y2); //画线 } } //随机生成一个字符 private char randomChar() { int index = r.nextInt(codes.length()); return codes.charAt(index); //获取字符串的第index个字符 } private BufferedImage createImg() { BufferedImage image = new BufferedImage(w,h,BufferedImage.TYPE_INT_RGB); Graphics2D g2 = (Graphics2D) image.getGraphics(); g2.setColor(this.bgColor); g2.fillRect(0, 0, w, h); return image; } //调用这个方法得到验证码 public BufferedImage getImg() { BufferedImage image = createImg(); //创建图片缓冲区 Graphics2D g2 = (Graphics2D) image.getGraphics(); //得到绘制环境 StringBuilder sb = new StringBuilder(); //用来装载生成的验证码文本 //向图片中画4个字符 for (int i = 0; i < 4; i++) { String s =randomChar() + ""; //随机生成一个字母 sb.append(s); //把字母添加到sb中 float x = i*1.0F *w/4; //设置当前字符的x轴坐标 g2.setFont(randomFont()); //设置随机字体 g2.setColor(randomColor()); //设置随机颜色 g2.drawString(s, x, h-5); //画图 } this.text = sb.toString(); //把生成的字符串赋给this.text drawLine(image); //添加干扰线 return image; } //返回验证码图片上的文本 public String getText() { return text; } //保存图片到指定的输出流 public static void output(BufferedImage image, OutputStream out) throws IOException { ImageIO.write(image,"JPEG",out); } }

Servlet层实现 VerifyCode类
@WebServlet("/VerifyCodeServlet") public class VerifyCodeServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // TODO Auto-generated method stub //生成图片 //保存图片上的文本到Session域中 //把图片响应给客户端 VerifyCode vc = new VerifyCode(); BufferedImage bi = vc.getImg(); VerifyCode.output(bi, response.getOutputStream()); request.getSession().setAttribute("session_code", vc.getText()); } }

RegistServlet类
@WebServlet("/RegistServlet") public class RegistServlet extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //处理编码 request.setCharacterEncoding("utf-8"); response.setContentType("text/html; charset=utf-8"); //依赖UserService UserService us =new UserService(); /* * 封装表单数据到User对象中 * */ User form = CommonUtils.toBean(request.getParameterMap(), User.class); /* * 服务器端表单验证 * 1.创建一个Map,用来装载所有表单错误信息 * 2.在校验过程中,如果失败,向map添加错误信息,其中key为表单字段名 * 3.校验之后查看map长度是否大于0,如果大于零证明有错误信息,保存map到request中, * 4.保存form到request中,转发到regist.jsp中 * 5.如果map为空,向下执行 */ Map,String> errors = new HashMap,String>(); //用户名格式校验 String username = form.getUsername(); //获取表单中的username if(username == null||username.trim().isEmpty()) { errors.put("username", "用户名不能为空!"); }else if(username.length() < 3||username.length() > 15) { errors.put("username", "用户名长度必须在3~15之间!"); } //密码格式校验 String password = form.getPassword(); //获取表单中的password if(password == null||password.trim().isEmpty()) { errors.put("password", "密码不能为空!"); }else if(password.length() < 3||password.length() > 15) { errors.put("password", "密码长度必须在3~15之间!"); }//对验证码进行校验 String sessionCode = (String)request.getSession().getAttribute("session_code"); String verifyCode = form.getVerifyCode(); //获取表单中的VerifyCode if(verifyCode == null||verifyCode.trim().isEmpty()) { errors.put("verifyCode", "验证码不能为空!"); }else if(verifyCode.length() != 4) { errors.put("verifyCode", "验证码长度必须为4!"); }else if(verifyCode.equalsIgnoreCase(sessionCode) ) { errors.put("verifyCode", "验证码错误!"); }//判断map是否为空,不为空说明有问题 if(errors != null && errors.size() > 0) {//健壮性 /* * 1.保存errors到request域 * 2.保存form到request域,用于回显 * 3.转发到regist.jsp */ request.setAttribute("errors", errors); request.setAttribute("user", form); request.getRequestDispatcher("/user/regist.jsp").forward(request, response); return; } /* * 调用us的方法 传递form过去 * 得到异常:获取异常信息,保存到request域中,转发到regist.jsp中显示 * 没有异常:输出注册成功 */ try { us.regist(form); response.getWriter().print("注册成功!+ request.getContextPath()+"/user/login.jsp" + "'>点击这里去登陆"); } catch (UserException e) { //获取异常信息保存到request域中,并且转发到注册页面 request.setAttribute("msg", e.getMessage()); request.setAttribute("user", form); //用来在表单中回显,EL表达式特点,没有啥也不显示,不是NULL request.getRequestDispatcher("/user/regist.jsp").forward(request, response); } } }

页面代码实现 regist.jsp
Insert title here - 锐客网 ="text/javascript"> function _change(){ /* 得到img元素 修改其src为/LoginDemo/VerifyCodeServet */ var imgEle = document.getElementById("img"); imgEle.src = "https://www.it610.com/article/${pageContext.request.contextPath }/VerifyCodeServlet?a="+new Date().getTime(); //不加个时间会因为浏览器缓存而更换失败 } 注册
用户名:${errors.username }
密码:${errors.password }
验证码:JavaWeb学习笔记--day14--注册案例
文章图片
换一张${errors.verifyCode }

【JavaWeb学习笔记--day14--注册案例】login.jsp
Insert title here - 锐客网
用户名:
密码:

    推荐阅读