my.user.dao
/**
* 数据类
* @author Administrator
*
*/
public class UserDao {
private String path="D:/users.xml";//依赖数据文件
/**
* 按用户名查询
*/
public User findByUsername(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,如果为null,返回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);
}
}
/**
* 添加用户
* @param user
*/
public void add(User user){
/*
* 1、得到Document
* 2、通过Document得到root元素<users>
* 3、使用参数user,转发成Element对象
* 4、把element添加到root元素中
* 5、保存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 = new XMLWriter(new FileWriter(path),format);//没有编码方式 需要换另外的输出方式
XMLWriter writer;
try {
writer = new XMLWriter(
new OutputStreamWriter(
new FileOutputStream(path),"utf-8"),format);//保证编码方式
writer.write(doc);//保存document对象
writer.close();
} catch (Exception e) {
throw new RuntimeException(e);
}
} catch (DocumentException e) {
throw new RuntimeException();
}
}
}
my.user.domain
/**
* 实体类
* @author Administrator
*
*/
public class User {
private String username;
private String password;
private String verifyCode;
set get 空参和有参构造、toString
my.user.service
/**
* 自定义一个异常类
* 知识给出父类中的构造器即可,方便用来创建对象
* @author Administrator
*
*/
public class UserException extends Exception {
public UserException() {
super();
// TODO Auto-generated constructor stub
}
public UserException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(message, cause, enableSuppression, writableStackTrace);
// 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
}
}
my.user.service
/**
* User的业务层
* @author Administrator
*
*/
public class UserService {
private UserDao userDao = new UserDao();
/**
* 注册功能
* @param user
* @throws UserException
*/
public void regist(User user) throws UserException{
/*
* 1、使用用户名去查询,如果返回null,完成添加
* 2、如果返回的不是null,抛出异常
*/
User _user = userDao.findByUsername(user.getUsername());
if(_user!=null) throw new UserException("用户名"+user.getUsername()+",已经注册过了");
userDao.add(user);
}
/**
* 登录功能
* @param form
* @return
*/
public User login(User form) throws UserException{
/*
* 1、使用form中的username进行查询,得到User user
*/
User user = userDao.findByUsername(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;
}
}
my.user.web.servlet包中LoginServlet
public class LoginServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");//请求编码POST
response.setContentType("text/html;charset=utf-8");//响应编码
//依赖UserService
UserService userService = new UserService();
/*
* 1、封装表单数据到User form中
* 2、调用service的login()方法,得到返回的User user对象
* 如果抛出异常:获取异常信息,保存到request域,再保存form,转发到login.jsp
* 如果没有异常:保存返回值到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()+"/user/welcome.jsp");
} catch (UserException e) {
request.setAttribute("msg", e.getMessage());
request.setAttribute("user", form);
request.getRequestDispatcher("/user/login.jsp").forward(request, response);;
}
}
}
my.user.web.servlet包中RegistServlet
public class RegistServlet extends HttpServlet {
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");//对post的编码方式处理
response.setContentType("text/html;charset=utf-8");
//依赖UserServlet
UserService userService = new UserService();
/*
* 1、封装表单数据(封装到User对象中)
*/
User form = CommonUtils.toBean(request.getParameterMap(),User.class);
/*
* 表单校验
*1、创建一个map,用来装载所有的表单错误信息
* 在校验过程中,如果失败,向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()){
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_vcode");
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是否为空,不为空,说明存在错误
* 因为以后可能不都自己写的 需要对errors进行存在判断 不然抛空指针错误
*/
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;
}
/*
*校验验证码
* 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;
}
*/
/*
* 2、调用userService的regist()方法,传递form过去
* 3、得到异常:获取异常信息,保存到request域,转发到regist.jsp中显示
* 4、没有异常:输出注册成功
*/
try {
userService.regist(form);
response.getWriter().print("注册成功<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("/user/regist.jsp").forward(request,response);
}
}
}
my.user.web.servlet包中VerifyCodeServlet
public class VerifyCodeServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//响应的是图片和编码没啥关系 也不要获取什么参数
/*
* 1、创建验证码类
*/
VerifyCode vc = new VerifyCode();
/*
* 2、得到验证码图片
*/
BufferedImage image = vc.getImage();
/*
* 3、把图片上的文本保存到session中
*/
request.getSession().setAttribute("session_vcode", vc.getText());
/*
* 4、把图片响应给客户端
*/
VerifyCode.output(image, response.getOutputStream());
}
}
test.dao
/**
* UserDao的测试
* @author Administrator
*
*/
public class UserDaoTest {
@Test
public void testFindByUsername(){
UserDao userDao = new UserDao();
User user = userDao.findByUsername("李四1");
System.out.println(user);
}
@Test
public void testAdd(){
UserDao userDao = new UserDao();
User user = new User();
user.setUsername("李四1");
user.setPassword("13232111");
userDao.add(user);
}
}
下面是jsp页面 login.jsp
<body>
<h1>登录</h1>
<p style="color:red;font-weight:900">${msg }</p>
<!-- ${pageContext.request.contextPath }/RegistServlet -->
<!-- IE 如果标签的没有设置name但设置了id那么会默认id为name的值 -->
<form action="<c:url value='/LoginServlet'/>" method="post">
用户名:<input type="text" name ="username" value="${user.username }"/><br/>
密 码 :<input type="password" name ="password" value="${user.password }"><br/>
<input type="submit" value="登录"/>
</form>
</body>
regist.jsp
<script type="text/javascript">
/*
如果一个表单项的name和<img>的id相同,那么会出问题 ,一般只有IE有这问题
*/
function _change(){
/*
1、获取<img>元素
*/
var ele = document.getElementById("verifyCode");
ele.src = "<c:url value='/VerifyCodeServlet'/>?xxx="+new Date().getTime();
}
</script>
</head>
<body>
<p style="color:red;font-weight:900">${msg }</p>
<!-- ${pageContext.request.contextPath }/RegistServlet -->
<!-- IE 如果标签的没有设置name但设置了id那么会默认id为name的值 -->
<form action="<c:url value='/RegistServlet'/>" method="post">
用户名:<input type="text" name ="username" value="${user.username }"/>${errors.username }<br/>
密 码 :<input type="password" 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>
welcome.jsp
<body>
<h1>welcome</h1> <br>
<c:choose>
<c:when test="${empty sessionScope.sessionUser }">再见</c:when>
<c:otherwise>
${sessionScope.sessionUser }<!-- User [username=李四1, password=123, verifyCode=null] -->
</c:otherwise>
</c:choose>
</body>