Java Web实战项目:注册登录(一)
javaweb项目实战:注册登录,客户关系管理系统(以xml为数据库)
●功能:
注册/登录
●页面:
-->login.jsp :登录
-->regist.jsp : 注册
-->index.jsp: 主页(登录成功才能看到)
servlet:
-->LoginServlet
-->RegistServlet
Service:
-->UserService --> 与用户相关的业务类
DAO:
-->UserDao --> 与用户相关的数据库
Domain:
-->User : username/password/verifyCode(对应数据库,还要对应所有表单)
●数据库设计:
user.xml
<users>
<users username="xxx" password="xxx">
<user username="xxx" password="xxx">
</users>
●步骤
1.创建项目
2.导包
----CommonUtils.jar(所依赖的commons-beanutils.jar,commons-logging.jar)
----xml使用的dom4j
3.建包
----com.tinstu.user.domain
----------->User
----com.tinstu.user.dao
----------->UserDao
----com.tinstu.user.service
----------->UserService
----com.tinstu.user.web.servlet
----------->LoginServlet
----------->RegistServlet
4.创建jsp
5.创建一个 users.xml
略 最后直接放代码
按照项目框架分析中的步骤,新建好所有文件
注册:需要完成
register.jsp
-》完成register的基本功能!
RegistServlet
-》封装表单数据,封装到user对象中.
-》调用service的regist()方法
---->如果这个方法没有问题,输出:注册成功
---->如果这个方法抛出了异常,把错误信息保存到request域,转发到regist.jsp(显示错误信息)
UserService
-》校验用户名是否被注册(通过用户名查询用户)(没有返回值,但注册失败抛出一个自定义的异常,在异常中添加异常信息:用户名已经被注册!)
-》添加用户
UserDao 通过业务分析得到
-》按照用户名查询用户对象:User findByUsername(String username)
-》插入一个用户到数据库中: void add (User user)
工作:
1.在service层添加一个UserException
2.DAO:
-->UserfindByUsername(String username)
-->void add(User user)
3.service
-->void regist() throws UserException
4.servlet
-->封装表单数据到User对象中
-->使用user调用service的regist的方法
-->如果得到UserException,那么把异常信息保存到request域中,转发回regist.jsp
-->输出注册成功!
package com.tinstu.dao;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
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.tinstu.domain.User;
/*
* 数据类
*/
public class UserDao {
private String path="D:/eclipse-work/xml/users.xml"; //数据文件
/*
* 按用户名查询
*/
public User fingByusername(String username) {
/*
* 1.得到document
* 2.xpath查询
* 3.校验检查结果是否为null,如果为null,返回null
* 4.如果不为null,需要把element封装到user中
*/
//1.得到document
//---创建解析器
SAXReader reader = new SAXReader();
try {
Document doc = reader.read(path);
//2.通过xpath查询Element
Element ele = (Element) doc.selectSingleNode("//user[@username='"+username+"']"); // 双斜杠表示没有深度的查询,[] 内放条件,@ 表示属性
//3.校验ele是否为null
if(ele == null)
return null;
//4.把ele的数据封装到User对象中
User user = new User();
String attrUsername = ele.attributeValue("username"); //获取元素的名为username的属性值
String attrpassword = ele.attributeValue("password"); // 获取元素的名为password的属性值
user.setUsername(attrUsername);
user.setPassword(attrpassword);
return user;
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
/*
* 添加用户
*/
public void add(User user) {
/*
* 1.得到document
* 2.通过document得到root元素
* 3.使用参数user,转发成element对象
* 4.把element添加到root元素中
* 5.保存document
*/
//得到document
SAXReader reader = new SAXReader();
try {
Document doc = reader.read(path);
//得到根元素
Element root = doc.getRootElement();
//通过根元素创建新元素
Element userEle = root.addElement("user");
//为userEle设置属性
userEle.addAttribute("username", user.getUsername());
userEle.addAttribute("password", user.getPassword());
// 保存文档
OutputFormat format = new OutputFormat("\t",true); // 缩进使用\t ,是否换行,使用是!
format.setTrimText(true); // 清楚原有换行
//创建XmlWriter
XMLWriter writer;
try {
writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream(path),"UTF-8"),format);
writer.write(doc); //保存dicument对象
writer.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
} catch (DocumentException e) {
throw new RuntimeException(e);
}
}
}
测试可使用 单元测试,右击->run as -> Junit Test
1.导入Junit的jar包
2.工程名右键→Properties→Java Build →PathLibraries→Add Library选中JUnit,然后Next
3.注意xml的格式
userexception.java
package com.tinstu.service;
/**
* 自定义一个异常类
* 只是给出父类中的构造器即可,方便用来创建对象
* @author 35582
*
*/
public class UserException extends Exception {
public UserException() {
super();
// TODO Auto-generated constructor stub
}
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
}
}
registservlet.java
package com.tinstu.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tinstu.domain.User;
import com.tinstu.service.UserException;
import com.tinstu.service.UserService;
import cn.itcast.commons.CommonUtils;
public class RegistServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//依赖UserService
UserService userService = new UserService () ;
/*
* 1.封装表单数据(封装到User对象中)
*/
User form = CommonUtils.toBean(request.getParameterMap(),User.class);
/*
* 调用userService的regist()方法,传递form过去
* 3.得到异常:获取异常信息,保存到request域,转发到regist.jsp
* 4.没有异常:输出支持成功
*/
try {
userService.regist(form);
response.getWriter().print("<h1>注册成功!</h1><a href=' "+
request.getContextPath()+ "/user/login.jsp" + " '>点击这里去登录</a>");
}catch(UserException e) {
request.setAttribute("msg", e.getMessage());
request.getRequestDispatcher("user/regist.jsp").forward(request, response);
}
}
}
regist.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
</head>
<body>
<h1>注册</h1>
<p style="color:red;font-weight:900">${ msg }</p>
<!-- ${pageContext.request.contextPath }/RegistServlet -->
<form action="<c:url value='/RegistServlet' />" method="post">
用户名: <input type="text" name="username" /> <br>
密码 : <input type="text" name="password" /> <br>
<input type="submit" value="注册">
</form>
</body>
</html>
userService.java
package com.tinstu.service;
/*
* 业务类
*/
import com.tinstu.dao.UserDao;
import com.tinstu.domain.User;
/**
* User的业务逻辑
* @author 35582
*
*/
public class UserService {
private UserDao userDao = new UserDao();
/**
* 注册功能
*/
public void regist(User user) throws UserException{
/*
* 1.使用用户名去查询,如果返回null,完成添加
* 2.如果返回的不是null,抛出异常
*
*/
User user2 = userDao.fingByusername(user.getUsername());
System.out.println(user.getUsername());
if(user2 != null) throw new UserException("用户名"+ user.getUsername() +",已经被注册!" );
userDao.add(user);
}
}
给注册添加验证码
1.VerifyCode类
- Bufferedimage getImage() ----> 获取随机的验证码图片
- String getText() ----->获取图片上的文本
- static output(BfferedImage,OutputStream) ---->把图片写入到指定的输出流中
2.VerifyCodeServlet
- 获取随机验证码图片
- 把验证码图片上的文本保存到session
- 把图片响应到response的outputStream
3.regist.jsp
- 添加<img src="指向Servlet" />
- 添加一个文本框,用来输入验证码
- “看不清,换一张”是一个超级链接,把上面的<img>的,src重新再次指向Servlet!为了处理浏览器的缓存,需要时间作为参数
4.修改RegistServlet
- 校验验证码
- 错误:保存表单数据到request域,保存错误信息到request域,转发回regist.jsp
- 正确:什么都不做向下指向原来的代码
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
<script type="text/javascript">
/*
* 如果一个表单项的name和<img>的id相同,那么可能会出现问题!一般只有IE有
*/
function _change(){
//获取<img>元素
var ele = document.getElementById("vCode");
ele.src = "<c:url value='/VerifyCodeServlet'/ >?xxx=" + new Date().getTime();
}
</script>
</head>
<body>
<h1>注册</h1>
<p style="color:red;font-weight:900">${ msg }</p>
<!-- ${pageContext.request.contextPath }/RegistServlet -->
<form action="<c:url value='/RegistServlet' />" method="post">
用户名: <input type="text" name="username" value="${user.name }" />${error.username }<br>
密码 : <input type="text" name="password" value="${user.password} " />${error.password } <br>
验证码<input type="text" name="VerifyCode" value="${user.verifyCode}" size=3">
<img id="vCode" src="<c:url value='/VerifyCodeServlet' />" border="2">
<a href="javascript:_change()">换一张</a><br>
<input type="submit" value="注册">
</form>
</body>
</html>
进行表单校验(registServlet.java)
/*
* 新添加任务:
* 校验验证码
* 1.用户填写的验证码已经封装到user中
* 2.从session获取真正的验证码
* 3.比较两者,如果不同,保存错误信息,保存表单数据,转发regist.jsp
* 4.如果相同,什么也不做,向下执行!
*/
if(!sessionVerifyCode.equalsIgnoreCase(form.getVerifyCode())) {
request.setAttribute("msg", "验证码错误!");
request.setAttribute("user", form);
request.getRequestDispatcher("/user/regist.jsp").forward(request, response);
return;
}
服务器端表单(输入)校验
我们把这段校验,放到获取表单数据之后,验证码校验之前!
1.使用Map类型来装载错误信息!
- Key:表单项名称,例如:username,password,verifycode
- value
- >>非空:用户名不能为空,或"密码不能为空"
- >>长度:用户名长度必须在3-20之间,密码长度必须在3-20之间
2.在校验失败时,项map添加错误信息! 哪个字段出错,就给哪个字段添加错误信息!
3.判断map是否为空(长度是否为0),如果不空,说明有错误存在,保存map到request域,保存form到request域(回显),转发回regist.jsp
4.在regist.jsp页面中,显示map中的错误信息。${map.username}
registServlet.java
package com.tinstu.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 com.tinstu.domain.User;
import com.tinstu.service.UserException;
import com.tinstu.service.UserService;
import cn.itcast.commons.CommonUtils;
public class RegistServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//依赖UserService
UserService userService = new UserService () ;
/*
* 1.封装表单数据(封装到User对象中)
*/
User form = CommonUtils.toBean(request.getParameterMap(),User.class);
/*
* 添加新任务(表单校验)
* 1.用户填写的验证码已经封装到user中
* 在校验过程中,如果失败,向map添加错误信息,其中key为表单字段名称
* 2.校验之后,查看map长度是否大于0,如果大于0,说明有错误。就是有错误!
* >保存map到request中,保存form到request中,转发到regist.jsp
*
* 3.如果map为空,说明没有错误信息,向下没有错误信息,向下执行!
*/
//用来装载所有错误信息
Map<String,String> errors = new HashMap<String,String>();
//对用户名进行校验
String username = form.getUsername(); //获取表单的username
if (username == null || username.trim().isEmpty()) { // ||后面表示username去掉空格之后为空
errors.put("username", "用户名不能为空");
}else if (username.length()<3 || username.length()>15) {
errors.put("username", "用户名长度必须在3-15之间");
}
//对密码进行校验
String password = form.getPassword();
if(password == null || password.trim().isEmpty()) {
errors.put("password", "密码不能为空");
}else if (password.length()<3 || password.length()>15) {
errors.put("password", "密码长度必须在3-15之间");
}
//对验证码进行校验
String sessionVerifyCode = (String) request.getSession().getAttribute("session_vaode");
String verifyCode = form.getVerifyCode();
if(verifyCode == null || verifyCode.trim().isEmpty()) {
errors.put("verifyCode", "验证码不能为空");
}else if (verifyCode.length()!= 4) {
errors.put("verifyCode", "验证码长度必须为4");
}else if (verifyCode.equalsIgnoreCase(sessionVerifyCode)){
errors.put("verifyCode", "验证码不正确");
}
/*
* 判断map是否为空,不为空,说明为存在错误
*/
if(errors != null && errors.size() > 0 ) {
/*
* 1.保存errors到request域中
* 2.保存from到request域,为了回显
* 3.转发regist.jsp
*/
request.setAttribute("errors", errors);
request.setAttribute("user", form);
request.getRequestDispatcher("/regist.jsp").forward(request, response);
return;
}
/*
* 新添加任务:
* 校验验证码
* 1.用户填写的验证码已经封装到user中
* 2.从session获取真正的验证码
* 3.比较两者,如果不同,保存错误信息,保存表单数据,转发regist.jsp
* 4.如果相同,什么也不做,向下执行!
*/
// if(!sessionVerifyCode.equalsIgnoreCase(form.getVerifyCode())) {
// request.setAttribute("msg", "验证码错误!");
// request.setAttribute("user", form);
// request.getRequestDispatcher("/user/regist.jsp").forward(request, response);
// return;
// }
/*
* 调用userService的regist()方法,传递form过去
* 3.得到异常:获取异常信息,保存到request域,转发到regist.jsp
* 4.没有异常:输出支持成功
*/
try {
userService.regist(form);
response.getWriter().print("<h1>注册成功!</h1><a href=' "+
request.getContextPath()+ "/user/login.jsp" + " '>点击这里去登录</a>");
}catch(UserException e) {
request.setAttribute("msg", e.getMessage());
request.getRequestDispatcher("/regist.jsp").forward(request, response);
}
}
}
regist.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Insert title here</title>
<script type="text/javascript">
/*
* 如果一个表单项的name和<img>的id相同,那么可能会出现问题!一般只有IE有
*/
function _change(){
//获取<img>元素
var ele = document.getElementById("verifyCode");
ele.src = "<c:url value='/VerifyCodeServlet' />?xxx=" + new Date().getTime();
}
</script>
</head>
<body>
<h1>注册</h1>
<p style="color:red;font-weight:900">${ msg }</p>
<!-- ${pageContext.request.contextPath }/RegistServlet -->
<form action="<c:url value='/RegistServlet' />" method="post">
用户名: <input type="text" name="username" value="${user.username }" />${errors.username }<br/>
密 码 : <input type="text" name="password" value="${user.password} " />${errors.password } <br/>
验证码:<input type="text" name="verifyCode" value="${user.verifyCode}" size="3" />
<img id="verifyCode" src="<c:url value='/VerifyCodeServlet' />" border="2" />
<a href="javascript:_change()">换一张</a>${errors.verifyCode}<br/>
<input type="submit" value="注册">
</form>
</body>
</html>
注册信息有误时,点击注册不清空文本框里面的内容!
RegistServlet.java中后面代码修改为
try {
userService.regist(form);
response.getWriter().print("<h1>注册成功!</h1><a href=' "+
request.getContextPath()+ "/user/login.jsp" + " '>点击这里去登录</a>");
}catch(UserException e) {
//获取异常信息保存到request域中
request.setAttribute("msg", e.getMessage());
//还要保存表单数据,到request域中
request.setAttribute("user", form); //用来在表单中回显
//转发regist.jsp
request.getRequestDispatcher("/regist.jsp").forward(request, response);
}
登录功能
页面 login.jsp ---> 登录表单
LoginServlet -->
- 1.获取表单数据,封装到user中
- 2.通过service的login( ) ,传递form过去 !
- 3.如果service的login( ),返回一个User对象!
- --4.有异常:获取异常信息,保存到request域,保存到form,转发到login.jsp
- --5.没有异常:保存返回的user对象到session中!! 重定向到welcome.jsp
UserService # login ( )
public User login ( user form){ ...... }
1.使用用户名查询数据库,得到返回的User
- 返回为null,抛出异常,异常信息为(用户名不存在)
- 返回不为null,获取查询出来的user的password域form的password的form的password进行比较!如果不同:抛出异常(密码错误!)
- 如果相同,返回查询结果!
UserDao
1.通过用户名查询用户!(已经存在了,不要再写)
loginServlet.java
package com.tinstu.web.servlet;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.tinstu.domain.User;
import com.tinstu.service.UserException;
import com.tinstu.service.UserService;
import cn.itcast.commons.CommonUtils;
public class LoginServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
public LoginServlet() {
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//依赖UserService
UserService userService = new UserService();
/*
* 1.获取表单数据,封装到user中
* 2.通过service的login( ) ,传递form过去 !
* 3.如果service的login( ),返回一个User对象!
* --4.有异常:获取异常信息,保存到request域,保存到form,转发到login.jsp
* --5.没有异常:保存返回的user对象到session中!! 重定向到welcome.jsp
*/
User form = CommonUtils.toBean(request.getParameterMap(),User.class);
try {
User user = userService.login(form);
request.getSession().setAttribute("sessionUser", user);
response.sendRedirect(request.getContextPath()+"/welcome.jsp");
} catch (Exception e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("user", form);
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
}
}
userServlet.java加入登录功能
/**
* 登录功能
* @param form
* @return
* @throws UserException
*/
public User login(User form) throws UserException {
/*
* 1.使用form中的username进行查询。得到User user
*/
User user = userDao.fingByusername(form.getUsername());
//2.如果返回null,说明用户名不存在,抛出异常,异常信息为“用户名不存在”
if (user == null) throw new UserException("用户名不存在!");
//3.比较user的password和form的password,如果不同,抛出异常,异常信息为:密码错误!
if (!form.getPassword().equals(user.getPassword())) {
throw new UserException("密码错误!");
}
//返回数据库中查询出来的user,而不是form,因为form中只有用户名和密码,而user是所有用户信息!
return user;
}
welcome.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>欢迎</title>
</head>
<body>
<h1>welcome!!!</h1>
<c:choose>
<c:when test="${empty sessionScope.sessionUser}">请先登录!</c:when>
<c:otherwise>
${sessionScope.sessionUser}
</c:otherwise>
</c:choose>
</body>
</html>