1.技術架構:三層架構--mvc
M: model V:View C:Controller
2.建立項目所使用的包:
bean: JavaBean
dao :Dao接口
dao.impl: Dao接口的實現
service:業務接口(注冊,登錄)
service.impl: 業務接口的實現
web:Servlet控制器,處理頁面的數據
工作流程:

User.java 定義了user的屬性
package kangjie.bean; import java.io.Serializable; import java.util.Date; public class User implements Serializable{ private String username; private String password; private String email; private Date birthday; //date類型 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; } }
UserDao接口
package kangjie.dao; import kangjie.bean.User; public interface UserDao { /** * 根據用戶名和密碼查詢用戶 * @param username * @param password * @return 查詢到,返回此用戶,否則返回null */ public User findUserByUserNameAndPassword(String username, String password); /** * 注冊用戶 * @param user 要注冊的用戶 */ public void add(User user); /** * 更加用戶名查找用戶 * @param name * @return查詢到了則返回此用戶,否則返回null */ public User findUserByUserName(String username); }
UserDaoImpl dao接口的實現
package kangjie.dao.impl; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import kangjie.bean.User; import kangjie.dao.UserDao; import kangjie.utils.JaxpUtils; import org.dom4j.Document; import org.dom4j.Element; import org.dom4j.Node; public class UserDaoImpl implements UserDao { /** * 需要從xml文件中讀取數據,需要一個類JaxpUtils.java */ @Override public User findUserByUserNameAndPassword(String username, String password) { //加載dom樹 Document document = JaxpUtils.getDocument(); //查詢需要的node節點 Node node = document.selectSingleNode("//user[@username='" + username + "' and @password='" + password + "']"); if(node != null){ //find him 封裝數據 User user = new User(); user.setUsername(username); user.setPassword(password); user.setEmail(node.valueOf("@email")); String birthday = node.valueOf("@birthday"); Date date; try { date = new SimpleDateFormat("yyyy-MM-dd").parse(birthday); //日期類型的轉化 user.setBirthday(date); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return user; } return null; } @Override public void add(User user) { //加載dom樹 Document document = JaxpUtils.getDocument(); //拿到根節點 Element root = document.getRootElement(); //添加一個user節點 root.addElement("user").addAttribute("username", user.getUsername()) .addAttribute("password", user.getPassword()) .addAttribute("email", user.getEmail()) .addAttribute("birthday", new SimpleDateFormat("yyyy-MM-dd").format(user.getBirthday())) ; //將dom樹報錯到硬盤上 JaxpUtils.write2xml(document); } @Override public User findUserByUserName(String username) { //加載dom樹 Document document = JaxpUtils.getDocument(); //查詢需要的node節點 Node node = document.selectSingleNode("//user[@username='" + username + "']"); if(node != null){ //find him 封裝數據 User user = new User(); user.setUsername(username); user.setPassword(node.valueOf("@password")); user.setEmail(node.valueOf("@email")); String birthday = node.valueOf("@birthday"); Date date; try { date = new SimpleDateFormat("yyyy-MM-dd").parse(birthday); user.setBirthday(date); } catch (ParseException e) { // TODO Auto-generated catch block e.printStackTrace(); } return user; } return null; } }
UserService 業務邏輯接口
package kangjie.service; import kangjie.bean.User; import kangjie.exception.UserExistsException; public interface UserService { /** * 根據用戶名和密碼 * @param username * @param password * @return 登錄成功返回次用戶,否則返回null */ public User login(String username, String password); /** * 用戶注冊 * @param user * @return */ public void register(User user) throws UserExistsException; //注冊失敗時,拋出異常,由該類來處理 }
UserExistsException 接手異常
package kangjie.exception; public class UserExistsException extends Exception{ }
UserServiceImpl 業務邏輯接口的實現
package kangjie.service.imple; import kangjie.bean.User; import kangjie.dao.UserDao; import kangjie.dao.impl.UserDaoImpl; import kangjie.exception.UserExistsException; import kangjie.service.UserService; public class UserServiceImpl implements UserService { UserDao dao = new UserDaoImpl(); @Override public User login(String username, String password) { // TODO Auto-generated method stub return dao.findUserByUserNameAndPassword(username, password); } @Override public void register(User user) throws UserExistsException { // 注冊成功與否,可以去servlet里去抓異常 User u = dao.findUserByUserName(user.getUsername()); if(u == null){ dao.add(user); }else{ throw new UserExistsException(); } } }
RegisterServlet 用戶注冊請求的處理
package kangjie.servlet; import java.io.IOException; import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; 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 kangjie.bean.User; import kangjie.exception.UserExistsException; import kangjie.service.UserService; import kangjie.service.imple.UserServiceImpl; import kangjie.utils.WebUtils; import kangjie.web.formbean.UserFormBean; public class ResigterServlet extends HttpServlet { /** * 完成注冊功能 * * This method is called when a form has its tag value method equals to get. */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //中文處理 request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); //先拿到數據,將數據封裝到userformbean中,因為可能會有很多的bean,所以此處應該新創建一個類來處理這個問題 //WebUtils類,專門 封裝數據 String username = request.getParameter("username"); System.out.println("---username---" + username); UserFormBean ufb = WebUtils.fillFormBean(UserFormBean.class, request); //第二步,驗證數據 if(ufb.validate()){ //驗證通過 //第三步,將formbean中的內容拷貝到user中 User user = new User(); //由於formbean中的生日是date類型,beanUtils類中不能自動轉換,因此需要注冊一個日期類型的轉換器 //BeanUtils.copy將一個對象拷貝到另一個對象中去 try { ConvertUtils.register(new DateLocaleConverter(), Date.class); BeanUtils.copyProperties(user, ufb); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } //第四步,注冊用戶 //調用業務邏輯層,完成注冊 UserService us = new UserServiceImpl(); try { us.register(user); System.out.println("注冊成功"); //注冊成功 //將用戶存入session對象中 // request.getSession().setAttribute("loginuser", user); //返回登錄頁面 //最好采用請求重定向,(請求轉發和請求重定向有什么區別) //重定向和轉發有一個重要的不同:當使用轉發時,JSP容器將使用一個內部的方法來調用目標頁面,新的頁面繼續處理同一個請求, // 而瀏覽器將不會知道這個過程。 與之相反,重定向方式的含義是第一個頁面通知瀏覽器發送一個新的頁面請求。 // 因為,當你使用重定向時,瀏覽器中所顯示的URL會變成新頁面的URL, 而當使用轉發時,該URL會保持不變。 // 重定向的速度比轉發慢,因為瀏覽器還得發出一個新的請求。同時,由於重定向方式產生了一個新的請求, // 所以經過一次重 定向后,request內的對象將無法使用。 // response.sendRedirect(request.getContextPath() + "/login.jsp"); //注冊成功,提示用戶 response.getWriter().write("注冊成功,2秒后轉向登錄頁面"); response.setHeader("Refresh", "2;url=" + request.getContextPath() + "/login.jsp"); } catch (UserExistsException e) { // 說明用戶已經注冊過了 ufb.getErrors().put("username", "此用戶已經被注冊過了"); //將ufb存入request對象中 request.setAttribute("user", ufb); request.getRequestDispatcher("/register.jsp").forward(request, response); } }else{ //驗證失敗 //打回去,同事把他原來填寫的數據回寫過去 //把ufb對象存入request對象 request.setAttribute("user", ufb); //給頁面傳遞的就是user對象,則在頁面上顯示的候,需要從user對象中拿取該數據 request.getRequestDispatcher("/register.jsp").forward(request, response); } } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
loginServlet 處理用戶登錄請求
package kangjie.servlet; 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; import kangjie.bean.User; import kangjie.service.UserService; import kangjie.service.imple.UserServiceImpl; public class loginServlet extends HttpServlet { /** * The doGet method of the servlet. <br> * * This method is called when a form has its tag value method equals to get. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { request.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); PrintWriter out = response.getWriter(); //獲取頁面數據 String username = request.getParameter("username"); String password = request.getParameter("password"); System.out.println("---username---"+ username + "---password---" +password); //驗證數據 UserService user = new UserServiceImpl(); User u = user.login(username, password); if(u != null){ //合法用戶 request.getSession().setAttribute("loginuser", u); request.getRequestDispatcher("/main.jsp").forward(request, response); }else{ //非法用戶 System.out.println("**用戶名或密碼錯誤**"); request.getSession().setAttribute("error", "用戶名或密碼錯誤"); response.sendRedirect(request.getContextPath() + "/servlet/login.jsp"); } } /** * The doPost method of the servlet. <br> * * This method is called when a form has its tag value method equals to post. * * @param request the request send by the client to the server * @param response the response send by the server to the client * @throws ServletException if an error occurred * @throws IOException if an error occurred */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { doGet(request, response); } }
JaxpUtils 處理xml文件的類,使用xml文件來充當數據庫
package kangjie.utils; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.io.OutputFormat; import org.dom4j.io.SAXReader; import org.dom4j.io.XMLWriter; //操作XML文件的方法 public class JaxpUtils { static String path; static { System.out.println("---getpath----"); path = JaxpUtils.class.getClassLoader().getResource("users.xml").getPath(); System.out.println("---path---" + path); } public static Document getDocument(){ //創建一個dom4j的解析器 try { SAXReader sx = new SAXReader(); Document doc = sx.read(path); return doc; } catch (DocumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } return null; } public static void write2xml(Document document){ try { XMLWriter writer = new XMLWriter(new FileOutputStream(path), OutputFormat.createPrettyPrint()); writer.write(document); writer.close(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
WebUtils 封裝頁面的數據
package kangjie.utils; import java.lang.reflect.InvocationTargetException; import javax.servlet.http.HttpServletRequest; import org.apache.commons.beanutils.BeanUtils; //為頁面服務,封裝頁面的數據 public class WebUtils { //寫一個泛型 public static <T> T fillFormBean(Class<T> clazz,HttpServletRequest request){ T t = null; try { t = clazz.newInstance();//反射機制 BeanUtils.populate(t, request.getParameterMap()); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return t; } }
UserFormBean 用來封裝頁面數據
package kangjie.web.formbean; import java.text.ParseException; import java.util.HashMap; import java.util.Map; import org.apache.commons.beanutils.locale.converters.DateLocaleConverter; /** * 為什么要UserFormBean * 是因為頁面上的數據類型很多,與user不匹配,所以需要UserFormBean * @author kj * */ public class UserFormBean { private String username; private String password; private String repassword; private String email; private String birthday; 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 getRepassword() { return repassword; } public void setRepassword(String repassword) { this.repassword = repassword; } 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; } /** * 驗證數據 * 服務端驗證必須要有 * @return */ public boolean validate(){ //驗證用戶名 if(username == "" || username == null){ errors.put("username", "用戶名或密碼不能為空"); }else{ if(username.length() <3 || username.length() > 11){ errors.put("username", "用戶名長度在3-8之間"); } } if(password == "" || password == null){ errors.put("password", "用戶名或密碼不能為空"); }else{ if(password.length() <3 || password.length() > 11){ errors.put("password", "密碼長度在3-8之間"); } } //驗證重復密碼 if(!repassword.equals(password)){ errors.put("repassword", "兩次密碼輸入不一致"); } //驗證郵箱 if(email == "" || email == null){ errors.put("email", "郵箱不能為空"); }else{ if(!email.matches("^([a-zA-Z0-9_\\-\\.]+)@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.)|(([a-zA-Z0-9\\-]+\\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\\]?)$")) { errors.put("email", "郵箱格式不正確"); } } //驗證生日 if(birthday == "" || birthday == null){ errors.put("birthday", "生日不能為空"); }else{ //驗證日期存在缺陷:2-30日不能驗證,需要使用另外一個類: // -----DateLocalConverter---apache // SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); DateLocaleConverter dlc = new DateLocaleConverter(); try { dlc.convert(birthday); } catch (Exception e) { // TODO Auto-generated catch block errors.put("birthday", "日期格式錯誤"); } } //如果errors為空,說明沒有錯誤產生 return errors.isEmpty(); //userbean寫好了,下邊就開始寫Servlet } //存放錯誤信息,使用Map,一對.然后只需要提供map的get方法即可 private Map<String,String> errors = new HashMap<String, String>(); public Map<String, String> getErrors() { return errors; } }
users.xml文件
<?xml version="1.0" encoding="UTF-8"?> <users> <user username="陳紫函" password="123" email="chengzihan@163.com" birthday="1980-10-10"/> </users>
register.jsp 注冊頁面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% 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>register.jsp</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"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> <form action="${pageContext.request.contextPath}/servlet/ResigterServlet" method="post"> <table border="8"> <tr> <td>姓名</td> <td><input type="text" name="username" value="${user.username }"></td> <!-- value 用來回顯數據 --> <td>${user.errors.username }</td> </tr> <tr> <td>密碼</td> <td><input type="password" name="password" value="${user.password }"></td> <td>${user.errors.password }</td> </tr> <tr> <td>確認密碼</td> <td><input type="password" name="repassword" value="${user.repassword }"></td> <td>${user.errors.repassword }</td> </tr> <tr> <td>郵箱</td> <td><input type="text" name="email" value="${user.email }"></td> <td>${user.errors.email }</td> </tr> <tr> <td>生日</td> <td><input type="text" name="birthday" value="${user.birthday }"></td> <td>${user.errors.birthday }</td> </tr> <tr> <td colspan="3" align="center"><input type="submit" value="注冊 "></td> </tr> </table> </form> </body> </html>
login.jsp 登錄頁面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% 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>登錄</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"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body>
<font color =red>${error }</font> <form action="${pageContext.request.contextPath }/servlet/loginServlet"> 用戶名:<input type="text" name="username"><br><br> 密 碼: <input type="password" name="password"><br><br> <input type="submit" value="登錄"><br> </form> </body> </html>
main.jsp 主頁面
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% 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>歡迎登錄</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"> <!-- <link rel="stylesheet" type="text/css" href="styles.css"> --> </head> <body> 歡迎回來!${loginuser.username} </body> </html>
