需求
1.带有验证码的注册
2.登录功能
3.各项信息不符合规范后进行错误信息的提示
4.表单数据的回显
5.服务器端的表单验证
思路
1.注册:regist.jsp–>RegistServlet.java–>UserService.java#regist()–> UserDao.java
2.登录:login.jsp–>LoginServlet.java–>UserLogin.java#login(User form)–>UserDao.java
3.使用VerifyCode类实现验证码。
4.使用request域保存数据的回显和错误信息。
5.使用request域保存数据表单校验信息。
6.登录成功后使用session域保存用户信息。
7.使用XML实现持久层数据的操作。
8.使用CommonUtils自动封装用户对象。
项目的结构图
UserDao.java
使用的是XML,通过dom4j获取到xml文件中的键值对。
package cn.wang.user.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 cn.wang.user.domain.User;
/*
*数据类 :BUG pass
*/
/**
*
* @author Zi Jian Wang
*
*/
public class UserDao {
private String path = "C:/user.xml";// 依赖数据文件
// 按用户名查询用户对象
public User findByUserName(String username) {
// 得到Document,创建解析器
SAXReader reader = new SAXReader();
try {
Document doc = reader.read(path);
Element element = (Element) doc.selectSingleNode("//user[@username='" + username + "']");
// .xpath查询,如果为null,返回null
if (element == null) {
System.out.println("没查到!");
return null;
}
// 如果不为null,需要把Element封装到User对象中
User user = new User();
String name = element.attributeValue("username");// 获取该元素的名为username的属性值
String psw = element.attributeValue("password");// 获取名为username的password的属性值
user.setUsername(name);
user.setUserpassword(psw);
return user;
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
// 插入一个用户到数据库中
public void insertUser(User user) {
// 得到document
SAXReader reader = new SAXReader();
try {
// 通过Document得到Root元素!<users>
Document doc = reader.read(path);
// 使用参数user,转换成Element对象
Element root = doc.getRootElement();
// 把element添加到root元素中
Element userEle = root.addElement("user");
userEle.addAttribute("username", user.getUsername());
userEle.addAttribute("password", user.getUserpassword());
// 保存代码
OutputFormat format = new OutputFormat("\t", true);// 缩进使用\t,是否换行,使用true
format.setTrimText(true);// 清空原有的换行和缩进
// 创建xmlWriter
XMLWriter writer;
try {
writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream(path), "utf-8"), format);
writer.write(doc);
writer.close();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} catch (DocumentException e) {
throw new RuntimeException();
}
}
}
User.java
实体类,3个属性:用户名,密码,验证码
package cn.wang.user.domain;
/*
*User实体类
*/
/**
*
* @author Zi Jian Wang
*
*/
public class User {
private String username;
private String userpassword;
private String verifyCode;
public String getVerifyCode() {
return verifyCode;
}
public void setVerifyCode(String verifyCode) {
this.verifyCode = verifyCode;
}
public User(String username, String userpassword, String verifyCode) {
super();
this.username = username;
this.userpassword = userpassword;
this.verifyCode = verifyCode;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpassword() {
return userpassword;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
public User() {
super();
// TODO Auto-generated constructor stub
}
}
UserException
自定义的异常类,只是给出父类中的构造器 ,方便用来创建对象。
package cn.wang.user.service;
/**
* 自定义的异常类,只是给出父类中的构造器 ,方便用来创建对象。
*
* @author Zijian Wang
*
*/
public class UserException extends Exception {
/**
*
*/
private static final long serialVersionUID = 1L;
public UserException() {
super();
}
public UserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
}
public UserException(String message, Throwable cause) {
super(message, cause);
// TODO Auto-generated constructor stub
}
public UserException(String message) {
super(message);
// TODO Auto-generated constructor stub
}
public UserException(Throwable cause) {
super(cause);
// TODO Auto-generated constructor stub
}
}
UserService.java
业务逻辑类:2个功能:登录,注册
package cn.wang.user.service;
import cn.wang.user.dao.UserDao;
import cn.wang.user.domain.User;
/**
*
* @author ZiJian Wang
*
*/
public class UserService {
private UserDao dao = new UserDao();
/*
* 注册
*/
// 没有返回值,但是注册失败会抛出一个自定义的异常
public void regist(User user) throws UserException {
// 检测注册用户是否已经注册了
User find_user = dao.findByUserName(user.getUsername());
if (find_user != null)
throw new UserException("用户名:" + user.getUsername() + ",已经被注册!");
dao.insertUser(user);
// 添加用户
}
/*
* 登录功能
*/
public User login(User user_form) throws UserException {
// 使用form中username进行查询
User user = dao.findByUserName(user_form.getUsername());
// 如果user为空,就抛出错误信息:“用户名不存在”
if (user == null)
throw new UserException("用户名不存在!");
// 比较user的password,如果不存在
if (!user_form.getUserpassword().equals(user.getUserpassword())) {
throw new UserException("密码错误!");
}
return user;
}
}
registServlet.java
注册Servlet类:登录的Servlet大同小异,不列出来了就。
package cn.wang.web.servlet;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import cn.wang.user.domain.User;
import cn.wang.user.service.UserException;
import cn.wang.user.service.UserService;
import cn.wang.utils.CommonUtils;
/**
*
* @author ZiJian Wang
*
*/
public class RegistServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");// 请求编码
response.setContentType("text/html;charset=UTF-8");// 响应编码
// 依赖UserService
UserService service = new UserService();
// 使用CommonUtils封装页面获取的属性的值
// 注意!!!使用这个获取的属性的必须和对象对应属性名相同!
User user_form = CommonUtils.toBean(request.getParameterMap(), User.class);
// 校验表单
// 创建map用来装载表单的错误信息
Map<String, String> errs = new HashMap<String, String>();
// 用户名校验
String username = user_form.getUsername();
if (username == null || username.trim().isEmpty()) {
errs.put("username", "用户名不能为空!");
} else if (username.length() < 3 || username.length() > 15) {
errs.put("username", "用户名长度在3~15之间");
}
// 密码校验
String userpassword = user_form.getUserpassword();
if (userpassword == null || userpassword.trim().isEmpty()) {
errs.put("userpassword", "密码不能为空!");
} else if (userpassword.length() < 3 || userpassword.length() > 15) {
errs.put("userpassword", "密码长度在3~15之间");
}
// 验证码校验
String session_Vcode = (String) request.getSession().getAttribute("image_msg");
String verifyCode = user_form.getVerifyCode();
if (verifyCode == null || verifyCode.trim().isEmpty()) {
errs.put("verifyCode", "验证码不能为空!");
} else if (verifyCode.length() != 4) {
errs.put("verifyCode", "验证码的长度必须为4!");
} else if (!verifyCode.equalsIgnoreCase(session_Vcode)) {
errs.put("verifyCode", "验证码不正确!");
}
// 判断map是否为空(不为空说明存在错误)
if (errs != null && errs.size() > 0) {
// 保存errs到request域
request.setAttribute("errs", errs);
// 保存用户的user_form到request域
request.setAttribute("user", user_form);
// 转发到regist.jsp
request.getRequestDispatcher("page/regist.jsp").forward(request, response);
return;
}
try {
service.regist(user_form);
response.getWriter().print("<h1>注册成功!</h1><a href='/page/login.jsp'>点击去登陆</a>");
} catch (UserException e) {
// 如果注册失败把失败的信息保存到request域中
request.setAttribute("msg", e.getMessage());
request.setAttribute("user", user_form);
request.getRequestDispatcher("page/regist.jsp").forward(request, response);
}
}
}
VerifyCodeServlet.java
package cn.wang.web.servlet;
import java.awt.image.BufferedImage;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import utils.VerifyCode;
/**
*
* @author ZiJian Wang
*
*/
public class VerifyCodeServlet extends HttpServlet {
/**
*
*/
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 创建验证码类
VerifyCode code = new VerifyCode();
// 生成BuffImage对象,生成对象。
BufferedImage image = code.createImage();
// 把图片上的文本保存到session域中
String image_msg = code.getText();
request.getSession().setAttribute("image_msg", image_msg);
// 把图片响应给客户端
VerifyCode.output(image, response.getOutputStream());
}
}
regist.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'regist.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<style type="text/css">
</style>
<script type="text/javascript">
function change() {
//获取<img>元素
var v_code = document.getElementById("v_code");
//重新赋值src路径,既重新加载VerifyCodeServlet
v_code.src = "<c:url value='/VerifyCodeServlet'/>?time=" + new Date().getTime();
}
</script>
</head>
<body>
<div style="margin-left: 300px">
<h1 style="margin-left: 100px">注册</h1>
<p style="color: red;font-weight:900 ">${msg}</p>
<form action="RegistServlet" method="post">
账号: <input type="text" name="username" value="${user.username }"> <span style="color:red">${errs.username}</span>
<br>密码: <input type="text" name="userpassword" value="${user.userpassword}"><span
style="color:red">${errs.userpassword}</span><br>验证码:<input type="text"
value="${user.verifyCode}" name="verifyCode" size="3"><img id="v_code"
src="<c:url value='/VerifyCodeServlet'/>" style="margin-top: 10px;" /><span style="color:red">${errs.verifyCode}</span><br>
<a href="javascript:change()" style="margin-left: 100px">换一张</a><br> <input type="submit"
value="提交" style="margin-left: 100px">
<!--验证码-->
</form>
</div>
</body>
</html>
login.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'Login.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<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> 密码:<input
type="text" name="userpassword" value="${user.userpassword}"><br> <input
type="submit" value="提交">
</form>
</body>
</html>
welcome.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()
+ path + "/";
%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<base href="<%=basePath%>">
<title>My JSP 'webcome.jsp' starting page</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
</head>
<body>
<h1>登录成功</h1>
<c:choose>
<c:when test="${empty sessionScope.session_user}"><a href="page/login.jsp">请点击这里登录</a></c:when>
<c:otherwise>${sessionScope.session_user}</c:otherwise>
</c:choose>
</body>
</html>
项目文件包: