1.搭建开发环境
1.1 导入项目所需的开发包:
dom4j-1.6.1.jar
jaxen-1.1-beta-6.jar
commons-beanutils-1.8.0.jar
commons-logging.jar
jstl.jar
standard.jar
1.2 创建程序的包名
1.3 在类目录下面,创建用于保存用户数据的xml文件(users.xml)-- 简单实现XML代替数据库users.xml
xml version="1.0" encoding="UTF-8"?> <users> <user id="51db22dc-f861-417b-b929-588aec86237e" username="abc" password="123" email="[email protected]" birthday="1990-8-5 0:00:00"/> users>
2、开发实体user
1.1 User.java
package com.lich.domain; import java.util.Date; public class User { private String id; private String username; private String password; private String email; private Date birthday; public String getId() { return id; } public void setId(String id) { this.id = id; } 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 getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } }
3、开发dao
3.1 开发UserDaoXmlImpl.java
package com.lich.dao.impl; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import com.lich.dao.UserDao; import com.lich.domain.User; import com.lich.utils.XmlUtils; //根据业务需求来写 public class UserDaoXmlImpl implements UserDao { public User find(String username,String password){ try{ Document document = XmlUtils.getDocument(); Element e = (Element) document.selectSingleNode("//user[@username='"+username+"' and @password='"+password+"']"); if(e==null){ return null; } User user = new User(); user.setId(e.attributeValue("id")); user.setEmail(e.attributeValue("email")); user.setPassword(e.attributeValue("password")); user.setUsername(e.attributeValue("username")); String birth = e.attributeValue("birthday"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); user.setBirthday(sdf.parse(birth)); return user; }catch (Exception e) { throw new RuntimeException(e); } } public void add(User user){ try{ Document document = XmlUtils.getDocument(); Element root = document.getRootElement(); Element user_node = root.addElement("user"); //创建user结点,并挂到root user_node.setAttributeValue("id", user.getId()); user_node.setAttributeValue("username", user.getUsername()); user_node.setAttributeValue("password", user.getPassword()); user_node.setAttributeValue("email", user.getEmail()); user_node.setAttributeValue("birthday", user.getBirthday().toLocaleString()); XmlUtils.write2Xml(document); }catch (Exception e) { throw new RuntimeException(e); } } public User find(String username){ try{ Document document = XmlUtils.getDocument(); Element e = (Element) document.selectSingleNode("//user[@username='"+username+"']"); if(e==null){ return null; } User user = new User(); user.setId(e.attributeValue("id")); user.setEmail(e.attributeValue("email")); user.setPassword(e.attributeValue("password")); user.setUsername(e.attributeValue("username")); String birth = e.attributeValue("birthday"); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); user.setBirthday(sdf.parse(birth)); return user; }catch (Exception e) { throw new RuntimeException(e); } } }
3.2 UserDao.java 抽取接口
3.3 开发工具类: XmlUtils
package com.lich.utils; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.net.URL; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; public class XmlUtils { private static String filename = "users.xml"; public static Document getDocument() throws DocumentException{ URL url = XmlUtils.class.getClassLoader().getResource(filename); String realpath = url.getPath(); SAXReader reader = new SAXReader(); return reader.read(new File(realpath)); } public static void write2Xml(Document document) throws IOException{ URL url = XmlUtils.class.getClassLoader().getResource(filename); String realpath = url.getPath(); OutputFormat format = OutputFormat.createPrettyPrint(); XMLWriter writer = new XMLWriter(new FileOutputStream(realpath), format ); writer.write( document ); writer.close(); } }
3.4 开发测试类 UserDaoTest
package junit.test; import java.util.Date; import org.junit.Test; import com.lich.dao.UserDao; import com.lich.dao.impl.UserDaoXmlImpl; import com.lich.domain.User; public class UserDaoTest { @Test public void testAdd(){ User user = new User(); user.setId("1002"); user.setUsername("bbb"); user.setPassword("123"); user.setEmail("[email protected]"); Date date = new Date(); user.setBirthday(date); UserDao dao = new UserDaoXmlImpl(); dao.add(user); } @Test public void testFind(){ UserDao dao = new UserDaoXmlImpl(); User user = dao.find("aaa","123"); System.out.println(user); } @Test public void testFindByUsername(){ UserDao dao = new UserDaoXmlImpl(); User user = dao.find("sss"); System.out.println(user); } }
4、开发service(service 对web层提供所有的业务服务)
4.1 开发BusinessService
public void registerUser(User user) throws UserExistException
public User loginUser(String username,String password);
package com.lich.service.impl; import com.lich.dao.UserDao; import com.lich.dao.impl.UserDaoXmlImpl; import com.lich.domain.User; import com.lich.exception.UserExistException; import com.lich.service.BusinessService; //根据需求分析 public class BusinessServiceImpl implements BusinessService { UserDao dao = new UserDaoXmlImpl(); //提供注册信息 /* (non-Javadoc) * @see com.lich.service.impl.BusinessService#registerUser(com.lich.domain.User) */ public void registerUser(User user) throws UserExistException{ if( dao.find(user.getUsername())!=null){ //抛编译时异常:目的为了上一层程序处理这个异常,给用户友好提示. throw new UserExistException("注册的用户已存在!!!"); } dao.add(user); } /* (non-Javadoc) * @see com.lich.service.impl.BusinessService#loginUser(java.lang.String, java.lang.String) */ public User loginUser(String username,String password){ return dao.find(username, password); } }
4.2 抽取接口
package com.lich.service; import com.lich.domain.User; import com.lich.exception.UserExistException; public interface BusinessService { //提供注册信息 void registerUser(User user) throws UserExistException; User loginUser(String username, String password); }
5、开发web层
5.1 开发注册
5.1.1 写一个RegisterUIServlet为用户提供注册界面,它收到请求,跳到register.jsp
package com.lich.web.UI; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class RegisterUIServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward( request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
5.1.2 写register.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用户注册title> head> <body style="text-align: center;"> <form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post"> <table width="60%" border="1" > <tr> <td>用户名td> <td> <input type="text" name="username" value="${formbean.username }">${formbean.errors.username } td> tr> <tr> <td>密码td> <td> <input type="password" name="password" value="${formbean.password }">${formbean.errors.password } td> tr> <tr> <td>确认密码td> <td> <input type="password" name="password2" value="${formbean.password2 }">${formbean.errors.password2 } td> tr> <tr> <td>邮箱td> <td> <input type="text" name="email" value="${formbean.email }">${formbean.errors.email } td> tr> <tr> <td>生日td> <td> <input type="text" name="birthday" value="${formbean.birthday }">${formbean.errors.birthday } td> tr> <tr> <td> <input type="reset" value="清空"> td> <td> <input type="submit" value="注册"> td> tr> table> form> body> html>
5.1.3 register.jsp提交请求,交给RegisterServlet处理
package com.lich.web.controller;
import java.io.IOException;
import java.util.Date;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.locale.converters.DateLocaleConverter;
import com.lich.domain.User;
import com.lich.exception.UserExistException;
import com.lich.service.BusinessService;
import com.lich.service.impl.BusinessServiceImpl;
import com.lich.utils.WebUtils;
import com.lich.web.formbean.RegisterFormBean;
public class RegisterServlet extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RegisterFormBean formbean = WebUtils.request2Bean(request,RegisterFormBean.class);
// 表单校验
if (formbean.validate() == false) {
request.setAttribute("formbean", formbean);
request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(
request, response);
return;
}
//把表单的数据填充到javabean中
User user = new User();
try {
//注册字符串到日期的转换器
ConvertUtils.register(new DateLocaleConverter(), Date.class);
BeanUtils.copyProperties(user, formbean);
user.setId(WebUtils.makeId());
BusinessService service = new BusinessServiceImpl();
service.registerUser(user);
request.setAttribute("message", "注册成功!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}catch (UserExistException e) {
formbean.getErrors().put("username", "注册用户已存在!!");
request.setAttribute("formbean", formbean);
request.getRequestDispatcher("/WEB-INF/jsp/register.jsp").forward(request, response);
} catch (Exception e) {
e.printStackTrace(); //在后台记录异常
request.setAttribute("message", "对不起,注册失败!!");
request.getRequestDispatcher("/message.jsp").forward(request, response);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
5.1.4 写RegisterServlet注意:
a.设计用于校验表单数据RegisterFormbean
package com.lich.web.formbean; import java.util.HashMap; import java.util.Map; import org.apache.commons.beanutils.locale.converters.DateLocaleConverter; public class RegisterFormBean { private String username; private String password; private String password2; private String email; private String birthday; private Maperrors = new HashMap(); public Map getErrors() { return errors; } public void setErrors(Map errors) { this.errors = errors; } 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 getPassword2() { return password2; } public void setPassword2(String password2) { this.password2 = password2; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getBirthday() { return birthday; } public void setBirthday(String birthday) { this.birthday = birthday; } /* private String username; 用户名不能为空,并且要是3-8的字符 abcdABcd private String password; 密码不能为空,并且要是3-8的数字 private String password2; 两次密码要一致 private String email; 可以为空,不为空要是一个合法的邮箱 private String birthday; 可以为空,不为空时,要是一个合法的日期 * */ public boolean validate(){ boolean isOk = true; if(this.username==null || this.username.trim().equals("") ){ isOk = false; errors.put("username", "用户名不能为空!!"); }else{ if(!this.username.matches("[a-zA-Z]{3,8}")){ isOk = false; errors.put("username", "用户名必须是3-8位的字母!!"); } } if(this.password==null || this.password.trim().equals("")){ isOk = false; errors.put("password", "密码不能为空!!"); }else{ if(!this.password.matches("\\d{3,8}")){ isOk = false; errors.put("password", "密码必须是3-8位的数字!!"); } } //private String password2; 两次密码要一致 if(this.password2!=null){ if(!this.password2.equals(this.password)){ isOk = false; errors.put("password2", "两次密码不一致!!"); } } //private String email; 可以为空,不为空要是一个合法的邮箱 // [email protected] if(this.email!=null){ if(!this.email.matches("\\w+@\\w+(\\.\\w+)+")){ isOk = false; errors.put("email", "邮箱不是一个合法邮箱!!"); } } //private String birthday; 可以为空,不为空时,要是一个合法的日期 if(this.birthday!=null){ try{ DateLocaleConverter conver = new DateLocaleConverter(); conver.convert(this.birthday); }catch (Exception e) { isOk = false; errors.put("birthday", "生日必须要是一个日期!!"); } } return isOk; } }
b.写WebUtils工具类,封装请求数据到formbean中
package com.lich.utils; import java.util.Enumeration; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.BeanUtils; ////把request对象中的请求参数封装到bean中 public class WebUtils { //用一个对象来接受处理请求,传给一个类字节码来创建类接收.使用泛型来应对调用 public staticT request2Bean(HttpServletRequest request,Class clazz){ try{ T bean = clazz.newInstance(); //username=aa password=bb [email protected] Enumeration e = request.getParameterNames(); while(e.hasMoreElements()){ String name = (String) e.nextElement(); //username=aaa password=123 String value = request.getParameter(name); BeanUtils.setProperty(bean, name, value); } return bean; }catch (Exception e) { throw new RuntimeException(e); } } /* *自动产生唯一用户编号ID */ public static String makeId(){ //UUID 128 36位字符 return UUID.randomUUID().toString(); } }
c、如果校验失败跳回到register.jsp,并回显错误信息
d、如果校验通过,调用service向数据库中注册用户
5.2 开发登陆
5.2.1 写一个LoginUIServlet为用户提供注册界面,它收到请求,跳到login.jsp
package com.lich.web.UI; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LoginUIServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getRequestDispatcher("/WEB-INF/jsp/login.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>用户登陆title> head> <body> <form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post"> 用户名:<input type="text" name="username"><br/> 密码:<input type="password" name="password"><br/> <input type="submit" value="登陆"> form> body> html>
5.2.2 login.jsp提交给LoginServlet处理登陆请求
package com.lich.web.controller; 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.lich.domain.User; import com.lich.service.BusinessService; import com.lich.service.impl.BusinessServiceImpl; public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String username = request.getParameter("username"); String password = request.getParameter("password"); BusinessService service = new BusinessServiceImpl(); User user = service.loginUser(username, password); if(user==null){ request.setAttribute("message", "对不起,用户名或密码有误!!"); request.getRequestDispatcher("/message.jsp").forward(request, response); return; } request.getSession().setAttribute("user", user); request.setAttribute("message", "恭喜:"+user.getUsername()+",登陆成功!本页将在5秒后跳到首页!!); request.getRequestDispatcher("/message.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
其它 开发中常见:
① 自定义异常包: com.lich.exception.UserExistException
package com.lich.exception; public class UserExistException extends Exception { public UserExistException() { super(); // TODO Auto-generated constructor stub } public UserExistException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); // TODO Auto-generated constructor stub } public UserExistException(String message, Throwable cause) { super(message, cause); // TODO Auto-generated constructor stub } public UserExistException(String message) { super(message); // TODO Auto-generated constructor stub } public UserExistException(Throwable cause) { super(cause); // TODO Auto-generated constructor stub } }
② 全局消息显示页面 message.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>全局消息显示页面title> head> <body> ${message } body> html>
③ 简单网站首页 index.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>首页title> <script type="text/javascript"> function doLogout(){ window.location.href="${pageContext.request.contextPath}/servlet/LogoutServlet"; } script> head> <body> <h1>XX网站h1> <br/><br/> <c:if test="${user==null}"> <a href="${pageContext.request.contextPath }/servlet/RegisterUIServlet" target="_blank">注册a> <a href="${pageContext.request.contextPath }/servlet/LoginUIServlet">登陆a> c:if> <c:if test="${user!=null}"> 欢迎您:${user.username } <input type="button" value="退出登陆" onclick="doLogout()"> c:if> <hr/> body> html>
④ 注销页面LogoutServlet
package com.lich.web.UI; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class LogoutServlet extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.getSession().removeAttribute("user"); request.setAttribute("message", "注销成功,本页将在5秒后跳到首页!!); request.getRequestDispatcher("/message.jsp").forward(request, response); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
总结:该网站虽然简单,但涵盖开发中使用的三层架构中心思想,认真领会MVC开发模式,学与思相结合,不断practice,相信编码水平会有质的提高.