昨天做了一个登录注册的小实例今天回忆一遍并且通过博客的方式写下来


首先先po上JavaWeb 的经典三层框架

注意 的是每个层都应该完成自己应该完成的不能完成别的层该做的事,不然耦合性太高

首先先确定登陆和注册需要两个页面 login.jsp regist.jsp 再加上一个欢迎首页 welcome.jsp 登陆成功才能看见 (session 实现)

需要LoginServlet.java 和 RegistServlet.java
因为有验证码 所以再创建一个 VerifyCodeServlet.java
servlet 用来处理页面请求 然后调用方法 把结果响应到页面
然后创建一个实体类 与登陆注册先关的实体类 User.java

业务逻辑层实现与登陆注册相关业务

数据层 以xml 代替

<?xml version="1.0" encoding="UTF-8"?><users><user username="Ashin" password="whoami"/><user username="Ben" password="whoami"/></users>

分析完了然后导入项目所需要的包
commons-logging-1.1.3 jar //用来把map中的数据封装到bean对象中
commons-beanutils-1.9.2.jar
dom4j-1.6.1.jar //以下两个是解析xml用
jaxen-1.1.6.jar
ashin-utils.jar // 自己生成的工具包 里面有生成验证码的代码

自定义jar包中的代码:

public static <T>T toBean(Map map,Class<T> clazz){try {/** 创建指定类型的javabean对象*///System.out.println(map); //有值{Ben=whoami2, Ashin=whoami, Aken=whoami3}T bean =  clazz.newInstance();/** 把数据封装到bean中*/BeanUtils.populate(bean,map);//System.out.println(bean); //无值/** 返回javabean对象*/return bean;} catch (Exception e) {throw new RuntimeException(e);}}
public class VerifyCode {private int w =70;private int h =35;private Random r = new Random();//定义有那些字体private String[] fontNames ={"宋体","华文楷体","黑体","微软雅黑","楷体_GB2312"};//定义有那些验证码的随机字符private String codes = "23456789abcdefghjkmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ";//生成背景色private Color bgColor = new Color(250,250,250);//用于gettext 方法 获得生成的验证码文本private String text;//生成随机颜色private Color randomColor(){int red =r.nextInt(150);int green =r.nextInt(150);int blue =r.nextInt(150);return new Color(red,green,blue);}//生成随机字体private Font randomFont(){int index = r.nextInt(fontNames.length);String fontName = fontNames[index];int style =r.nextInt(4);int size =r.nextInt(5)+24;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);}}//得到codes的长度内的随机数 并使用charAt 取得随机数位置上的codes中的字符private char randomChar(){int index =r.nextInt(codes.length());return codes.charAt(index);}//创建一张验证码的图片public BufferedImage createImage(){BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);Graphics2D g2 =(Graphics2D) image.getGraphics();StringBuilder sb = new StringBuilder();//向图中画四个字符for(int  i= 0 ;i < 4; i++) {String s = randomChar()+"";sb.append(s);float x = i * 1.0F * w / 4;g2.setFont(randomFont());g2.setColor(randomColor());g2.drawString(s,x,h-5);}this.text = sb.toString();drawLine(image);//返回图片return image;}//得到验证码的文本 后面是用来和用户输入的验证码 检测用public String getText(){return text;}//定义输出的对象和输出的方向public  static void output(BufferedImage bi,OutputStream fos) throws FileNotFoundException, IOException{ImageIO.write(bi, "JPEG", fos);}

创建包

com.ashin.beans     对应实体类> User.java>username>password>verifycode
com.ashin.service  业务层>UserService.java>UserException.java   //自定义异常类
com.ashin.web.servlet  web层>LoginServlet.java>RegistServlet.java>VerifyCodeServlet
com.ashin.dao     数据层>UserDao.java

下面贴部分代码 并会注释

实体类就不多写了 只是多了个VerifyCode 属性用于验证码

先把userservice 贴出来以便后面的理解


/*** 第一个方法通过名字查询用户返回一个用户对象 调用的是userdao的findUserByName()方法 * 并通过adduser()在数据库中添加一个用户* 第二个方法 登陆时调用 来判断用户名是否存在 密码是否正确* 返回的userexception都来自自定义异常类* @param user* @throws UserException*/
private UserDao userdao = new UserDao();public void regist(User user) throws UserException{User _user = userdao.findUserByName(user.getUsername());if(_user != null ) throw new UserException("用户名"+user.getUsername()+",已经被注册了");userdao.addUser(user);}public User login(User form) throws UserException  {User _user = userdao.findUserByName(form.getUsername());if(_user == null)   throw new UserException("用户名"+form.getUsername()+",不存在请去注册");if( ! _user.getPassword().equals(form.getPassword())) throw new UserException("密码不正确");return _user;}

自定义异常类

创建UserException 类 只需继承Exception 类并实现父类构造方法即可

regist.jsp

<script type="text/javascript">function _change(){var ele = document.getElementById("verifyCode"); ele.src="<c:url value='/VerifyCodeServlet'/>?xxx="+new Date().getTime();//只要后面的参数变化的话就会再次发送请求实现验证码换一张的效果}</script></head>/**注释块:这边的${msg } 用于显示错误信息 如果RegistServlet 捕获到错误会把异常加入request 域 并转发到 次页面进行输出 <c:url value="/LoginServlet"/>   需要引入标签库 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>input标签中的el表达式用于回显 用户名及密码 后面的${errors.password }是显示表单验证时返回的错误信息*/<body><h1>注册</h1><p style="color: red ; font-weight: 900">${msg }</p><form action='<c:url value="/RegistServlet"/>' method="post">用户名:<input type="text" name="username" value="${user.username }"/><font color="red" >${errors.username }</font><br><br>密 码:<input type="password" name ="password" value="${user.password }"/><font color="red" >${errors.password }</font><br>//验证码  src="<c:url value='/VerifyCodeServlet'/>"  指向/项目名/VerifyCodeServlet验证码:<input type="text" name="verifyCode" value="${user.verifyCode }" size="3"/><img  id ="verifyCode" src="<c:url value='/VerifyCodeServlet'/>"/><font color="red" >${errors.verifycode }</font><br><a href="Javascript:_change()">换一张</a><input type="submit" value="提交"></form></body>

Regist.servlet

public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset=utf-8");UserService userService = new UserService();//将表单信息封装到user对象中User form = CommonUtils.toBean(request.getParameterMap(), User.class);//创建一个map对象用来存储错误信息Map<String, String> errors = new HashMap<String, String>();/*** 下面三段都是表单验证*/String username = form.getUsername();if(username == null || username.trim().isEmpty()){errors.put("username", "用户名不能为空");}else if(username.length()<3 || username.length()>13){errors.put("username", "用户名长度应该为3~13位");}String password = form.getPassword();if(password == null || password.trim().isEmpty()){errors.put("password", "密码不能为空");}else if(password.length()<3 || password.length()>13){errors.put("password", "密码长度应该为3~13位");}String createverify = (String) request.getSession().getAttribute("session_vf");String verifycode = form.getVerifyCode();if(verifycode == null || verifycode.trim().isEmpty()){errors.put("verifycode", "验证码不能为空");}else if(verifycode.length() != 4){errors.put("verifycode", "验证码必须是四位");}else if(!verifycode.equalsIgnoreCase(createverify)){errors.put("verifycode", "验证码错误");}/** 查看是否有异常 没就执行下面的代码 有就保存异常 保存用于回显的信息  并转发到注册页面 注意return*/if(errors != null && errors.size() > 0){request.setAttribute("errors", errors);request.setAttribute("user", form);request.getRequestDispatcher("/user/Regist.jsp").forward(request, response);return; //不往下执行}//上面没有异常 就执行   调用 业务逻辑类的 regist方法    如果没有异常就显示成功  有异常就保存异常信息 转发到注册页面 同上try {userService.regist(form);response.getWriter().print("注册成功<br>");response.getWriter().print("<a href='"+request.getContextPath()+"/user/Login.jsp"+"'>点击这里去登录</a>");} catch (UserException e) {request.setAttribute("msg", e.getMessage());request.setAttribute("user", form);request.getRequestDispatcher("/user/Regist.jsp").forward(request, response);}}

login.jsp

<body><h1>登陆</h1><p style="color: red ; font-weight: 900">${msg }</p><form action='<c:url value="/LoginServlet"/>' method="post">用户名:<input type="text" name="username" value="${user.username }"/><br><br>密 码:<input type="password" name ="password" value="${user.password }"/><br><input type="submit" value="登陆"></form></body>

LoginServlet
//与注册的servlet 类似 调用的业务逻辑方法不同

public void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {request.setCharacterEncoding("utf-8");response.setContentType("text/html;charset:utf-8");UserService userService = new UserService();User form = CommonUtils.toBean(request.getParameterMap(), User.class);try {User user = userService.login(form);request.getSession().setAttribute("sessionUser", user);response.sendRedirect(request.getContextPath()+"/user/Welcome.jsp");} catch (UserException e) {request.setAttribute("msg", e.getMessage());request.setAttribute("user", form);request.getRequestDispatcher("/user/Login.jsp").forward(request, response);}}
//get方法 因为前面刷新验证码 采用的是 +参数的形式
//所用的类在开头自定义jar包中的代码
public void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {/*** 创建验证码类*/VerifyCode vf = new VerifyCode();/*** 生成验证码图片*/BufferedImage  image = vf.createImage();/*** 把验证码文本存在session中*/request.getSession().setAttribute("session_vf", vf.getText());/*** 把图片相应给客户端*/VerifyCode.output(image, response.getOutputStream());}

最后贴上userdao 的代码

package com.ashin.dao;import java.io.FileOutputStream;
import java.io.OutputStreamWriter;import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;import com.ashin.domain.User;/*** 数据类* @author Ashin**/
public class UserDao {String path ="F://users.xml";public User findUserByName(String username){/*** 获得一个解析器*/SAXReader reader = new SAXReader();/*** 通过路径取得一个文档对象*/try {Document doc = reader.read(path);/*** 通过xpah查询得到element*/Element element = (Element) doc.selectSingleNode("//user[@username='"+username+"']");/*** 查看是否存在 返回null则不存在  直接返回*/if(element == null) return null;/*** 把element数据封装到user对象中*/User u = new User();String attrUsername = element.attributeValue("username");String attrPassword = element.attributeValue("password");u.setUsername(attrUsername);u.setPassword(attrPassword);return u;} catch (Exception e) {throw new RuntimeException(e);}}public boolean addUser(User user ){SAXReader reader = new SAXReader();try {Document document = reader.read(path);/*** 获得文档的根节点*/Element root = document.getRootElement();/*** 在根节点下添加子元素*/Element userEle = root.addElement("user");/*** 设置元素的属性*/userEle.addAttribute("username", user.getUsername());userEle.addAttribute("password", user.getPassword());/*** 保存文档*/OutputFormat outputFormat = new OutputFormat("\t",true); //缩进使用\t  换行选择trueoutputFormat.setTrimText(true);//是否删除原有的换行和缩进try {XMLWriter writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream(path), "utf-8"),outputFormat);writer.write(document);writer.close();} catch (Exception e) {throw new RuntimeException(e);} } catch (DocumentException e) {throw new RuntimeException(e);}return false;}
}

此次实例让我很直观的理解到了三层框架的好处,每个层都各司其职 完成对应的功能

简单的登陆注册的实现+验证码和表单验证相关推荐

  1. 获取手机验证码——Vant表单验证/后端框架express/前后端交互

    完成一个获取手机验证码的功能,在获取之前要对手机号进行表单验证,判断是否输入/输入的是否为正确格式,获取手机验证码后可等待n秒重新获取,代码如下: <template><div cl ...

  2. (二)简单的登陆注册系统--增加验证码部分

    2019独角兽企业重金招聘Python工程师标准>>> login.html <html> <meta http-equiv="Content-Type& ...

  3. 简单php登陆注册模块

    前一段时间刚刚开始学习php 很简单很实用 开发效率很高 很适合我这样的新手 于是做了一个简单的登陆注册模块 里面包含了很多常用的表单提交数据 也加入了验证码 供新手们借鉴 说实话 我只会写网页  做 ...

  4. Android借助bmob实现简单的登陆注册

    借助bmob实现简单的登陆注册 实现步骤 1注册bmob 2配置Bomb相关 3扩展自己的用户列表 4实现注册 5实现登陆 欢迎下载 https://github.com/kurumi2501314/ ...

  5. Android 实现简单的登陆注册功能(SharedPreferences和SQLite)

    最近刚好做了一个Android的登录注册界面,将数据利用SharedPreferences或者SQLite绑定到Android程序中,实现简单的登陆注册功能,本文未涉及到与服务器的交流. 首先,对于登 ...

  6. 关于unity连接MySQL数据库做一个简单的登陆注册系统

    这段时间为了大作业,作为一个菜鸟研究了好久的Unity连接数据库,那就整理一下然后写下来当作记录吧. 首先,unity连接MySQL要先在Assets板上创建pluging文件夹再导入一些必要的dll ...

  7. php登陆页面修改密码的功能,使用bootstrap创建登录注册页面并实现表单验证功能...

    本篇文章给大家介绍一下使用bootstrap创建登录注册页面并实现单验证功能的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 用bootstrap做登入注册页面,使用valid ...

  8. 小程序之简单登录注册表单验证

    这段时间在做员工管理的小程序,前期在登录注册上花了不少功夫,今天就给大家分享下. 效果图,wxss的内容较简单,自己编写即可. ##主要内容 一.首先我是在util.js中引入表单正则验证规则,给予l ...

  9. java注册登录小程序,详解小程序之简单登录注册表单验证

    这段时间在做员工管理的小程序,前期在登录注册上花了不少功夫,今天就给大家分享下. 效果图,wxss的内容较简单,自己编写即可. ##主要内容 一.首先我是在util.js中引入表单正则验证规则,给予l ...

最新文章

  1. 【青少年编程(第27周)】报名考级的小朋友注意截止时间!
  2. java 关闭oracle连接_Java应用中Oracle连接不关闭
  3. JavaScript前端框架的思考
  4. linux alpine 用dockerfile创建的ssh镜像
  5. 67.数据库系统的三级模式
  6. 【LeetCode从零单排】No 3 Longest Substring Without Repeating Characters
  7. 胡珀:从危到机,AI 时代下的安全挑战
  8. idea下org.apache.commons.dbcp.BasicDataSourc找不到
  9. mysql的explain怎么看_mysql中explain用法详解
  10. ClassNotFoundException:是否减慢了您的JVM?
  11. java 年份对应的中国生肖
  12. 怎么批量在数字里加入网页_手把手教你爬取天堂网1920*1080大图片(批量下载)——理论篇
  13. Spring配置与第一Spring HelloWorld
  14. rabbitMQ消息队列 consume详解
  15. greasyfork脚本怎么取消_更新了js脚本,回答一些常见问题
  16. 浙江计算机三级考试单片机试题,历年浙江省计算机三级单片机
  17. 利用Oracle Enterprise Manager Cloud Control 12c创建DataGuard Standby
  18. 张亚勤寄语哥伦比亚大学2020年毕业生:引领未知时代
  19. 请问下面这段代码哪里有错? private static final String s=
  20. python列表查找元素用什么运算符_【Python】第012课,定义和使用列表,列表的运算符,列表元素的遍历i,列表的方法,元素位置和次数,元素排序和反转。...

热门文章

  1. 基于 Websocket 协议的压力测试
  2. DevOps死了吗?平台工程能否取代DevOps?
  3. vue2 + vue-video-player 视频播放器
  4. c235delc杂合变异遗传吗_新生儿235delc杂合突变
  5. 小麦数据集-聚类应用
  6. 编程辅助插件BitoAI使用指南(以VSCode开发环境为例安装并使用BitoAI插件从而提高生产效率)
  7. 使用CxImage进行图形和格式转换(CBitmap to jpg or png or gif or bmp)
  8. 【教程】Spire.PDF教程:C# 设置 PDF 缩放比例和页面显示设置
  9. GTP科普——简单入门资料
  10. web安全入门课程推荐--Web 安全恩仇录:漏洞原理