Servlet+JSP+JavaBean模式(MVC)適合開發複雜的web應用,在這種模式下,servlet負責處理用戶請求,jsp負責數據顯示,javabean負責封裝數據。 Servlet+JSP+JavaBean模式程序各個模塊之間層次清晰,web開發推薦採用此種模式。javascript
這裏以一個最經常使用的用戶登陸註冊程序來說解Servlet+JSP+JavaBean開發模式,經過這個用戶登陸註冊程序綜合案例,把以前的學過的XML、Xpath、Servlet、jsp的知識點都串聯起來。php
在MyEclipse中新建立一個webmvcframework項目,導入項目所須要的開發包(jar包),建立項目所須要的包,在java開發中,架構的層次是以包的形式體現出來的html
項目所須要的開發包(jar包) | ||
序號 | 開發包名稱 | 描述 |
1 | dom4j-1.6.1.jar | dom4j用於操做XML文件 |
2 | jaxen-1.1-beta-6.jar | 用於解析XPath表達式 |
3 | commons-beanutils-1.8.0.jar | 工具類,用於處理bean對象 |
4 | commons-logging.jar | commons-beanutils-1.8.0.jar的依賴jar包 |
5 | jstl.jar | jstl標籤庫和EL表達式依賴包 |
6 | standard.jar | jstl標籤庫和EL表達式依賴包 |
項目所須要的包 | |||
序號 | 包名 | 描述 | 所屬層次 |
1 | me.gacl.domain | 存放系統的JavaBean類(只包含簡單的屬性以及屬性對應的get和set方法,不包含具體的業務處理方法),提供給【數據訪問層】、【業務處理層】、【Web層】來使用 | domain(域模型)層 |
2 | me.gacl.dao | 存放訪問數據庫的操做接口類 | 數據訪問層 |
3 | me.gacl.dao.impl | 存放訪問數據庫的操做接口的實現類 | |
4 | me.gacl.service | 存放處理系統業務接口類 | 業務處理層 |
5 | me.gacl.service.impl | 存放處理系統業務接口的實現類 | |
6 | me.gacl.web.controller | 存放做爲系統控制器的Servlet | Web層(表現層) |
7 | me.gacl.web.UI | 存放爲用戶提供用戶界面的servlet(UI指的是user interface) | |
8 | me.gacl.web.filter | 存放系統的用到的過濾器(Filter) | |
9 | me.gacl.web.listener | 存放系統的用到的監聽器(Listener) | |
10 | me.gacl.util | 存放系統的通用工具類,提供給【數據訪問層】、【業務處理層】、【Web層】來使用 | |
11 | junit.test | 存放系統的測試類 |
一個良好的JavaWeb項目架構應該具備以上的11個包,這樣顯得井井有條,各個層之間的職責也很清晰明瞭,搭建JavaWeb項目架構時,就按照上面的1~11的序號順序建立包:domain→dao→dao.impl→service→service.impl→web.controller→web.UI→web.filter→web.listener→util→junit.test,包的層次建立好了,項目的架構也就定下來了,固然,在實際的項目開發中,也不必定是完徹底全按照上面說的來建立包的層次結構,而是根據項目的實際狀況,可能還須要建立其餘的包,這個得根據項目的須要來定了vue
在src目錄(類目錄)下面,建立用於保存用戶數據的xml文件(DB.xml)java
在WEB-INF目錄下建立一個pages目錄,pages目錄存放系統的一些受保護(不容許用戶直接經過URL地址訪問)的jsp頁面,用戶要想訪問這些受保護的jsp頁面,那麼只能經過me.gacl.web.UI這個包裏面的Servletnode
建立好的項目以下圖(圖-1)所示:ios
圖-1c++
分層架構的代碼也是按照【域模型層(domain)】→【數據訪問層(dao、dao.impl)】→【業務處理層(service、service.impl)】→【表現層(web.controller、web.UI、web.filter、web.listener)】→【工具類(util)】→【測試類(junit.test)】的順序進行編寫的。git
在me.gacl.domain包下建立一個User類web
User類具體代碼以下:
1 package me.gacl.domain; 2 3 import java.io.Serializable; 4 import java.util.Date; 5 /** 6 * @author gacl 7 * 用戶實體類 8 */ 9 public class User implements Serializable { 10 11 private static final long serialVersionUID = -4313782718477229465L; 12 13 // 用戶ID 14 private String id; 15 // 用戶名 16 private String userName; 17 // 用戶密碼 18 private String userPwd; 19 // 用戶郵箱 20 private String email; 21 // 用戶生日 22 private Date birthday; 23 24 public String getId() { 25 return id; 26 } 27 28 public void setId(String id) { 29 this.id = id; 30 } 31 32 public String getUserName() { 33 return userName; 34 } 35 36 public void setUserName(String userName) { 37 this.userName = userName; 38 } 39 40 public String getUserPwd() { 41 return userPwd; 42 } 43 44 public void setUserPwd(String userPwd) { 45 this.userPwd = userPwd; 46 } 47 48 public String getEmail() { 49 return email; 50 } 51 52 public void setEmail(String email) { 53 this.email = email; 54 } 55 56 public Date getBirthday() { 57 return birthday; 58 } 59 60 public void setBirthday(Date birthday) { 61 this.birthday = birthday; 62 } 63 }
在me.gacl.dao包下建立一個IUserDao接口類,對於開發接口類,我習慣以字母I做類的前綴,這樣一眼就看出當前這個類是一個接口,這也算是一種良好的開發習慣吧,經過看類名就能夠方便區分出是接口仍是具體的實現類。
IUserDao接口的具體代碼以下:
1 package me.gacl.dao; 2 3 import me.gacl.domain.User; 4 5 public interface IUserDao { 6 7 /** 8 * 根據用戶名和密碼來查找用戶 9 * @param userName 10 * @param userPwd 11 * @return 查到到的用戶 12 */ 13 User find(String userName, String userPwd); 14 15 /** 16 * 添加用戶 17 * @param user 18 */ 19 void add(User user); 20 21 /**根據用戶名來查找用戶 22 * @param userName 23 * @return 查到到的用戶 24 */ 25 User find(String userName); 26 }
對於接口中的方法定義,這個只能是根據具體的業務來分析須要定義哪些方法了,可是不管是多麼複雜的業務,都離不開基本的CRUD(增刪改查)操做,Dao層是直接和數據庫交互的,因此Dao層的接口通常都會有增刪改查這四種操做的相關方法。
在me.gacl.dao.impl包下建立一個UserDaoImpl類
UserDaoImpl類是IUserDao接口的具體實現類,對於接口的實現類命名方式,我習慣以"接口名(去除前綴I)+impl"形式或者"接口名+impl"形式來命名:IUserDao(接口)→UserDaoImpl(實現類)或者IUserDao(接口)→IUserDaoImpl(實現類),這也算是一些我的的編程習慣吧,平時看到的代碼大多數都是以這兩種形式中的一種來來命名接口的具體實現類的,反正就是要可以一眼看出接口對應的實現類是哪個就能夠了。
UserDaoImpl類的具體代碼以下:
1 package me.gacl.dao.impl; 2 3 import java.text.SimpleDateFormat; 4 import org.dom4j.Document; 5 import org.dom4j.Element; 6 import me.gacl.dao.IUserDao; 7 import me.gacl.domain.User; 8 import me.gacl.util.XmlUtils; 9 10 /** 11 * IUserDao接口的實現類 12 * @author gacl 13 */ 14 public class UserDaoImpl implements IUserDao { 15 16 @Override 17 public User find(String userName, String userPwd) { 18 try{ 19 Document document = XmlUtils.getDocument(); 20 //使用XPath表達式來操做XML節點 21 Element e = (Element) document.selectSingleNode("//user[@userName='"+userName+"' and @userPwd='"+userPwd+"']"); 22 if(e==null){ 23 return null; 24 } 25 User user = new User(); 26 user.setId(e.attributeValue("id")); 27 user.setEmail(e.attributeValue("email")); 28 user.setUserPwd(e.attributeValue("userPwd")); 29 user.setUserName(e.attributeValue("userName")); 30 String birth = e.attributeValue("birthday"); 31 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 32 user.setBirthday(sdf.parse(birth)); 33 34 return user; 35 36 }catch (Exception e) { 37 throw new RuntimeException(e); 38 } 39 } 40 41 @SuppressWarnings("deprecation") 42 @Override 43 public void add(User user) { 44 try{ 45 Document document = XmlUtils.getDocument(); 46 Element root = document.getRootElement(); 47 Element user_node = root.addElement("user"); //建立user結點,並掛到root 48 user_node.setAttributeValue("id", user.getId()); 49 user_node.setAttributeValue("userName", user.getUserName()); 50 user_node.setAttributeValue("userPwd", user.getUserPwd()); 51 user_node.setAttributeValue("email", user.getEmail()); 52 53 SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd"); 54 user_node.setAttributeValue("birthday", sdf.format(user.getBirthday())); 55 56 XmlUtils.write2Xml(document); 57 58 }catch (Exception e) { 59 throw new RuntimeException(e); 60 } 61 } 62 63 @Override 64 public User find(String userName) { 65 try{ 66 Document document = XmlUtils.getDocument(); 67 Element e = (Element) document.selectSingleNode("//user[@userName='"+userName+"']"); 68 if(e==null){ 69 return null; 70 } 71 User user = new User(); 72 user.setId(e.attributeValue("id")); 73 user.setEmail(e.attributeValue("email")); 74 user.setUserPwd(e.attributeValue("userPwd")); 75 user.setUserName(e.attributeValue("userName")); 76 String birth = e.attributeValue("birthday"); 77 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); 78 user.setBirthday(sdf.parse(birth)); 79 80 return user; 81 82 }catch (Exception e) { 83 throw new RuntimeException(e); 84 } 85 } 86 87 }
在me.gacl.service包中建立IUserService接口類
IUserService接口的具體代碼以下:
1 package me.gacl.service; 2 3 import me.gacl.domain.User; 4 import me.gacl.exception.UserExistException; 5 6 public interface IUserService { 7 8 /** 9 * 提供註冊服務 10 * @param user 11 * @throws UserExistException 12 */ 13 void registerUser(User user) throws UserExistException; 14 15 /** 16 * 提供登陸服務 17 * @param userName 18 * @param userPwd 19 * @return 20 */ 21 User loginUser(String userName, String userPwd); 22 }
在me.gacl.service.impl包中建立UserServiceImpl類
UserServiceImpl類爲IUserService接口的具體實現類,具體代碼以下:
1 package me.gacl.service.impl; 2 3 import me.gacl.dao.IUserDao; 4 import me.gacl.dao.impl.UserDaoImpl; 5 import me.gacl.domain.User; 6 import me.gacl.exception.UserExistException; 7 import me.gacl.service.IUserService; 8 9 public class UserServiceImpl implements IUserService { 10 11 private IUserDao userDao = new UserDaoImpl(); 12 13 @Override 14 public void registerUser(User user) throws UserExistException { 15 if (userDao.find(user.getUserName())!=null) { 16 //checked exception 17 //unchecked exception 18 //這裏拋編譯時異常的緣由:是我想上一層程序處理這個異常,以給用戶一個友好提示 19 throw new UserExistException("註冊的用戶名已存在!!!"); 20 } 21 userDao.add(user); 22 } 23 24 @Override 25 public User loginUser(String userName, String userPwd) { 26 return userDao.find(userName, userPwd); 27 } 28 29 }
一、在me.gacl.web.UI包下寫一個RegisterUIServlet爲用戶提供註冊界面
RegisterUIServlet收到用戶請求後,就跳到register.jsp
RegisterUIServlet的代碼以下:
1 package me.gacl.web.UI; 2 3 import java.io.IOException; 4 import javax.servlet.ServletException; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 /** 9 * @author gacl 10 * 爲用戶提供註冊的用戶界面的Servlet 11 * RegisterUIServlet負責爲用戶輸出註冊界面 12 * 當用戶訪問RegisterUIServlet時,就跳轉到WEB-INF/pages目錄下的register.jsp頁面 13 */ 14 public class RegisterUIServlet extends HttpServlet { 15 16 public void doGet(HttpServletRequest request, HttpServletResponse response) 17 throws ServletException, IOException { 18 request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response); 19 } 20 21 public void doPost(HttpServletRequest request, HttpServletResponse response) 22 throws ServletException, IOException { 23 doGet(request, response); 24 } 25 26 }
二、在/WEB-INF/pages/目錄下編寫用戶註冊的jsp頁面register.jsp
凡是位於WEB-INF目錄下的jsp頁面是沒法直接經過URL地址直接訪問的,
在開發中若是項目中有一些敏感web資源不想被外界直接訪問,那麼能夠考慮將這些敏感的web資源放到WEB-INF目錄下,這樣就能夠禁止外界直接經過URL來訪問了。
register.jsp頁面的代碼以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML> 3 <html> 4 <head> 5 <title>用戶註冊</title> 6 </head> 7 8 <body style="text-align: center;"> 9 <form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post"> 10 <table width="60%" border="1"> 11 <tr> 12 <td>用戶名</td> 13 <td> 14 15 <input type="text" name="userName"> 16 </td> 17 </tr> 18 <tr> 19 <td>密碼</td> 20 <td> 21 <input type="password" name="userPwd"> 22 </td> 23 </tr> 24 <tr> 25 <td>確認密碼</td> 26 <td> 27 <input type="password" name="confirmPwd"> 28 </td> 29 </tr> 30 <tr> 31 <td>郵箱</td> 32 <td> 33 <input type="text" name="email"> 34 </td> 35 </tr> 36 <tr> 37 <td>生日</td> 38 <td> 39 <input type="text" name="birthday"> 40 </td> 41 </tr> 42 <tr> 43 <td> 44 <input type="reset" value="清空"> 45 </td> 46 <td> 47 <input type="submit" value="註冊"> 48 </td> 49 </tr> 50 </table> 51 </form> 52 </body> 53 </html>
register.jsp中的<form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post">指明表單提交後,交給RegisterServlet進行處理
三、在me.gacl.web.controller包下編寫用於處理用戶註冊的RegisterServlet
RegisterServlet擔任着如下幾個職責:
一、接收客戶端提交到服務端的表單數據。
二、校驗表單數據的合法性,若是校驗失敗跳回到register.jsp,並回顯錯誤信息。
三、若是校驗經過,調用service層向數據庫中註冊用戶。
爲了方便RegisterServlet接收表單數據和校驗表單數據,在此我設計一個用於校驗註冊表單數據RegisterFormbean,再寫WebUtils工具類,封裝客戶端提交的表單數據到formbean中。
在me.gacl.web.formbean包下建立一個用於校驗註冊表單數據RegisterFormbean
RegisterFormbean代碼以下:
1 package me.gacl.web.formbean; 2 3 import java.util.HashMap; 4 import java.util.Map; 5 6 import org.apache.commons.beanutils.locale.converters.DateLocaleConverter; 7 8 /** 9 * 封裝的用戶註冊表單bean,用來接收register.jsp中的表單輸入項的值 10 * RegisterFormBean中的屬性與register.jsp中的表單輸入項的name一一對應 11 * RegisterFormBean的職責除了負責接收register.jsp中的表單輸入項的值以外還擔任着校驗表單輸入項的值的合法性 12 * @author gacl 13 * 14 */ 15 public class RegisterFormBean { 16 17 //RegisterFormBean中的屬性與register.jsp中的表單輸入項的name一一對應 18 //<input type="text" name="userName"/> 19 private String userName; 20 //<input type="password" name="userPwd"/> 21 private String userPwd; 22 //<input type="password" name="confirmPwd"/> 23 private String confirmPwd; 24 //<input type="text" name="email"/> 25 private String email; 26 //<input type="text" name="birthday"/> 27 private String birthday; 28 29 30 /** 31 * 存儲校驗不經過時給用戶的錯誤提示信息 32 */ 33 private Map<String, String> errors = new HashMap<String, String>(); 34 35 public Map<String, String> getErrors() { 36 return errors; 37 } 38 39 public void setErrors(Map<String, String> errors) { 40 this.errors = errors; 41 } 42 43 /* 44 * validate方法負責校驗表單輸入項 45 * 表單輸入項校驗規則: 46 * private String userName; 用戶名不能爲空,而且要是3-8的字母 abcdABcd 47 * private String userPwd; 密碼不能爲空,而且要是3-8的數字 48 * private String confirmPwd; 兩次密碼要一致 49 * private String email; 能夠爲空,不爲空要是一個合法的郵箱 50 * private String birthday; 能夠爲空,不爲空時,要是一個合法的日期 51 */ 52 public boolean validate() { 53 54 boolean isOk = true; 55 56 if (this.userName == null || this.userName.trim().equals("")) { 57 isOk = false; 58 errors.put("userName", "用戶名不能爲空!!"); 59 } else { 60 if (!this.userName.matches("[a-zA-Z]{3,8}")) { 61 isOk = false; 62 errors.put("userName", "用戶名必須是3-8位的字母!!"); 63 } 64 } 65 66 if (this.userPwd == null || this.userPwd.trim().equals("")) { 67 isOk = false; 68 errors.put("userPwd", "密碼不能爲空!!"); 69 } else { 70 if (!this.userPwd.matches("\\d{3,8}")) { 71 isOk = false; 72 errors.put("userPwd", "密碼必須是3-8位的數字!!"); 73 } 74 } 75 76 // private String password2; 兩次密碼要一致 77 if (this.confirmPwd != null) { 78 if (!this.confirmPwd.equals(this.userPwd)) { 79 isOk = false; 80 errors.put("confirmPwd", "兩次密碼不一致!!"); 81 } 82 } 83 84 // private String email; 能夠爲空,不爲空要是一個合法的郵箱 85 if (this.email != null && !this.email.trim().equals("")) { 86 if (!this.email.matches("\\w+@\\w+(\\.\\w+)+")) { 87 isOk = false; 88 errors.put("email", "郵箱不是一個合法郵箱!!"); 89 } 90 } 91 92 // private String birthday; 能夠爲空,不爲空時,要是一個合法的日期 93 if (this.birthday != null && !this.birthday.trim().equals("")) { 94 try { 95 DateLocaleConverter conver = new DateLocaleConverter(); 96 conver.convert(this.birthday); 97 } catch (Exception e) { 98 isOk = false; 99 errors.put("birthday", "生日必需要是一個日期!!"); 100 } 101 } 102 103 return isOk; 104 } 105 106 public String getUserName() { 107 return userName; 108 } 109 110 public void setUserName(String userName) { 111 this.userName = userName; 112 } 113 114 public String getUserPwd() { 115 return userPwd; 116 } 117 118 public void setUserPwd(String userPwd) { 119 this.userPwd = userPwd; 120 } 121 122 public String getConfirmPwd() { 123 return confirmPwd; 124 } 125 126 public void setConfirmPwd(String confirmPwd) { 127 this.confirmPwd = confirmPwd; 128 } 129 130 public String getEmail() { 131 return email; 132 } 133 134 public void setEmail(String email) { 135 this.email = email; 136 } 137 138 public String getBirthday() { 139 return birthday; 140 } 141 142 public void setBirthday(String birthday) { 143 this.birthday = birthday; 144 } 145 }
在me.gacl.util包下建立一個WebUtils工具類,該工具類的功能就是封裝客戶端提交的表單數據到formbean中
1 package me.gacl.util; 2 3 import java.util.Enumeration; 4 import java.util.UUID; 5 import javax.servlet.http.HttpServletRequest; 6 import org.apache.commons.beanutils.BeanUtils; 7 8 /** 9 * @author gacl 10 * 把request對象中的請求參數封裝到bean中 11 */ 12 public class WebUtils { 13 14 /** 15 * 將request對象轉換成T對象 16 * @param request 17 * @param clazz 18 * @return 19 */ 20 public static <T> T request2Bean(HttpServletRequest request,Class<T> clazz){ 21 try{ 22 T bean = clazz.newInstance(); 23 Enumeration<String> e = request.getParameterNames(); 24 while(e.hasMoreElements()){ 25 String name = (String) e.nextElement(); 26 String value = request.getParameter(name); 27 BeanUtils.setProperty(bean, name, value); 28 } 29 return bean; 30 }catch (Exception e) { 31 throw new RuntimeException(e); 32 } 33 } 34 35 /** 36 * 生成UUID 37 * @return 38 */ 39 public static String makeId(){ 40 return UUID.randomUUID().toString(); 41 } 42 43 }
最後看一下負責處理用戶註冊的RegisterServlet完整代碼:
1 package me.gacl.web.controller; 2 3 import java.io.IOException; 4 import java.util.Date; 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 import org.apache.commons.beanutils.BeanUtils; 10 import org.apache.commons.beanutils.ConvertUtils; 11 import org.apache.commons.beanutils.locale.converters.DateLocaleConverter; 12 import me.gacl.domain.User; 13 import me.gacl.exception.UserExistException; 14 import me.gacl.service.IUserService; 15 import me.gacl.service.impl.UserServiceImpl; 16 import me.gacl.util.WebUtils; 17 import me.gacl.web.formbean.RegisterFormBean; 18 /** 19 * 處理用戶註冊的Servlet 20 * @author gacl 21 * 22 */ 23 public class RegisterServlet extends HttpServlet { 24 25 public void doGet(HttpServletRequest request, HttpServletResponse response) 26 throws ServletException, IOException { 27 //將客戶端提交的表單數據封裝到RegisterFormBean對象中 28 RegisterFormBean formbean = WebUtils.request2Bean(request,RegisterFormBean.class); 29 //校驗用戶註冊填寫的表單數據 30 if (formbean.validate() == false) {//若是校驗失敗 31 //將封裝了用戶填寫的表單數據的formbean對象發送回register.jsp頁面的form表單中進行顯示 32 request.setAttribute("formbean", formbean); 33 //校驗失敗就說明是用戶填寫的表單數據有問題,那麼就跳轉回register.jsp 34 request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response); 35 return; 36 } 37 38 User user = new User(); 39 try { 40 // 註冊字符串到日期的轉換器 41 ConvertUtils.register(new DateLocaleConverter(), Date.class); 42 BeanUtils.copyProperties(user, formbean);//把表單的數據填充到javabean中 43 user.setId(WebUtils.makeId());//設置用戶的Id屬性 44 IUserService service = new UserServiceImpl(); 45 //調用service層提供的註冊用戶服務實現用戶註冊 46 service.registerUser(user); 47 String message = String.format( 48 "註冊成功!!3秒後爲您自動跳到登陸頁面!!<meta http-equiv='refresh' content='3;url=%s'/>", 49 request.getContextPath()+"/servlet/LoginUIServlet"); 50 request.setAttribute("message",message); 51 request.getRequestDispatcher("/message.jsp").forward(request,response); 52 53 } catch (UserExistException e) { 54 formbean.getErrors().put("userName", "註冊用戶已存在!!"); 55 request.setAttribute("formbean", formbean); 56 request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response); 57 } catch (Exception e) { 58 e.printStackTrace(); // 在後臺記錄異常 59 request.setAttribute("message", "對不起,註冊失敗!!"); 60 request.getRequestDispatcher("/message.jsp").forward(request,response); 61 } 62 } 63 64 public void doPost(HttpServletRequest request, HttpServletResponse response) 65 throws ServletException, IOException { 66 doGet(request, response); 67 } 68 69 }
用戶註冊時若是填寫的表單數據校驗不經過,那麼服務器端就將一個存儲了錯誤提示消息和表單數據的formbean對象存儲到request對象中,而後發送回register.jsp頁面,所以咱們須要在register.jsp頁面中取出request對象中formbean對象,而後將用戶填寫的表單數據從新回顯到對應的表單項上面,將出錯時的提示消息也顯示到form表單上面,讓用戶知道是哪些數據填寫不合法!
修改register.jsp頁面,代碼以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML> 3 <html> 4 <head> 5 <title>用戶註冊</title> 6 </head> 7 8 <body style="text-align: center;"> 9 <form action="${pageContext.request.contextPath}/servlet/RegisterServlet" method="post"> 10 <table width="60%" border="1"> 11 <tr> 12 <td>用戶名</td> 13 <td> 14 <%--使用EL表達式${}提取存儲在request對象中的formbean對象中封裝的表單數據(formbean.userName)以及錯誤提示消息(formbean.errors.userName)--%> 15 <input type="text" name="userName" value="${formbean.userName}">${formbean.errors.userName} 16 </td> 17 </tr> 18 <tr> 19 <td>密碼</td> 20 <td> 21 <input type="password" name="userPwd" value="${formbean.userPwd}">${formbean.errors.userPwd} 22 </td> 23 </tr> 24 <tr> 25 <td>確認密碼</td> 26 <td> 27 <input type="password" name="confirmPwd" value="${formbean.confirmPwd}">${formbean.errors.confirmPwd} 28 </td> 29 </tr> 30 <tr> 31 <td>郵箱</td> 32 <td> 33 <input type="text" name="email" value="${formbean.email}">${formbean.errors.email} 34 </td> 35 </tr> 36 <tr> 37 <td>生日</td> 38 <td> 39 <input type="text" name="birthday" value="${formbean.birthday}">${formbean.errors.birthday} 40 </td> 41 </tr> 42 <tr> 43 <td> 44 <input type="reset" value="清空"> 45 </td> 46 <td> 47 <input type="submit" value="註冊"> 48 </td> 49 </tr> 50 </table> 51 </form> 52 </body> 53 </html>
到此,用戶註冊功能就算是開發完成了!
下面測試一下開發好的用戶註冊功能:
輸入URL地址:http://localhost:8080/webmvcframework/servlet/RegisterUIServlet訪問register.jsp頁面,運行效果以下:
若是輸入的表單項不符合校驗規則,那麼是沒法進行註冊的,運行效果以下:
一、在me.gacl.web.UI包下寫一個LoginUIServlet爲用戶提供登陸界面
LoginUIServlet收到用戶請求後,就跳到login.jsp
LoginUIServlet的代碼以下:
1 package me.gacl.web.UI; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 /** 11 * @author gacl 12 * LoginUIServlet負責爲用戶輸出登錄界面 13 * 當用戶訪問LoginUIServlet時,就跳轉到WEB-INF/pages目錄下的login.jsp頁面 14 */ 15 public class LoginUIServlet extends HttpServlet { 16 17 public void doGet(HttpServletRequest request, HttpServletResponse response) 18 throws ServletException, IOException { 19 20 request.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(request, response); 21 } 22 23 public void doPost(HttpServletRequest request, HttpServletResponse response) 24 throws ServletException, IOException { 25 doGet(request, response); 26 } 27 28 }
二、在/WEB-INF/pages/目錄下編寫用戶登陸的jsp頁面login.jsp
login.jsp頁面的代碼以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <!DOCTYPE HTML> 3 <html> 4 <head> 5 <title>用戶登錄</title> 6 </head> 7 8 <body> 9 <form action="${pageContext.request.contextPath }/servlet/LoginServlet" method="post"> 10 用戶名:<input type="text" name="username"><br/> 11 密碼:<input type="password" name="password"><br/> 12 <input type="submit" value="登錄"> 13 </form> 14 </body> 15 </html>
login.jsp中的<form action="${pageContext.request.contextPath}/servlet/LoginServlet" method="post">指明表單提交後,交給LoginServlet進行處理。
三、在me.gacl.web.controller包下編寫用於處理用戶登陸的LoginServlet
LoginServlet的代碼以下:
1 package me.gacl.web.controller; 2 3 import java.io.IOException; 4 5 import javax.servlet.ServletException; 6 import javax.servlet.http.HttpServlet; 7 import javax.servlet.http.HttpServletRequest; 8 import javax.servlet.http.HttpServletResponse; 9 10 import me.gacl.domain.User; 11 import me.gacl.service.IUserService; 12 import me.gacl.service.impl.UserServiceImpl; 13 14 /** 15 * 處理用戶登陸的servlet 16 * @author gacl 17 * 18 */ 19 public class LoginServlet extends HttpServlet { 20 21 public void doGet(HttpServletRequest request, HttpServletResponse response) 22 throws ServletException, IOException { 23 24 //獲取用戶填寫的登陸用戶名 25 String username = request.getParameter("username"); 26 //獲取用戶填寫的登陸密碼 27 String password = request.getParameter("password"); 28 29 IUserService service = new UserServiceImpl(); 30 //用戶登陸 31 User user = service.loginUser(username, password); 32 if(user==null){ 33 String message = String.format( 34 "對不起,用戶名或密碼有誤!!請從新登陸!2秒後爲您自動跳到登陸頁面!!<meta http-equiv='refresh' content='2;url=%s'", 35 request.getContextPath()+"/servlet/LoginUIServlet"); 36 request.setAttribute("message",message); 37 request.getRequestDispatcher("/message.jsp").forward(request, response); 38 return; 39 } 40 //登陸成功後,就將用戶存儲到session中 41 request.getSession().setAttribute("user", user); 42 String message = String.format( 43 "恭喜:%s,登錄成功!本頁將在3秒後跳到首頁!!<meta http-equiv='refresh' content='3;url=%s'", 44 user.getUserName(), 45 request.getContextPath()+"/index.jsp"); 46 request.setAttribute("message",message); 47 request.getRequestDispatcher("/message.jsp").forward(request, response); 48 } 49 50 public void doPost(HttpServletRequest request, HttpServletResponse response) 51 throws ServletException, IOException { 52 doGet(request, response); 53 } 54 55 }
到此,用戶登陸的功能就算是開發完成了。
下面測試一下開發好的用戶登陸功能,輸入URL地址:http://localhost:8080/webmvcframework/servlet/LoginUIServlet訪問login.jsp頁面,輸入正確的用戶名和密碼進行登陸,運行效果以下:
若是輸入的用戶名和密碼錯誤,那麼就沒法登陸成功,運行效果以下:
在me.gacl.web.controller包下編寫用於處理用戶註銷的LogoutServlet
LogoutServlet的代碼以下:
1 package me.gacl.web.controller; 2 3 import java.io.IOException; 4 import java.text.MessageFormat; 5 6 import javax.servlet.ServletException; 7 import javax.servlet.http.HttpServlet; 8 import javax.servlet.http.HttpServletRequest; 9 import javax.servlet.http.HttpServletResponse; 10 11 public class LogoutServlet extends HttpServlet { 12 13 public void doGet(HttpServletRequest request, HttpServletResponse response) 14 throws ServletException, IOException { 15 //移除存儲在session中的user對象,實現註銷功能 16 request.getSession().removeAttribute("user"); 17 //因爲字符串中包含有單引號,在這種狀況下使用MessageFormat.format方法拼接字符串時就會有問題 18 //MessageFormat.format方法只是把字符串中的單引號去掉,不會將內容填充到指定的佔位符中 19 String tempStr1 = MessageFormat.format( 20 "註銷成功!!3秒後爲您自動跳到登陸頁面!!<meta http-equiv='refresh' content='3;url={0}'/>", 21 request.getContextPath()+"/servlet/LoginUIServlet"); 22 System.out.println(tempStr1);//輸出結果:註銷成功!!3秒後爲您自動跳到登陸頁面!!<meta http-equiv=refresh content=3;url={0}/> 23 System.out.println("---------------------------------------------------------"); 24 /** 25 * 要想解決"若是要拼接的字符串包含有單引號,那麼MessageFormat.format方法就只是把字符串中的單引號去掉,不會將內容填充到指定的佔位符中"這個問題, 26 * 那麼能夠須要使用單引號引發來的字符串中使用2個單引號引發來,例如:"<meta http-equiv=''refresh'' content=''3;url={0}''/>" 27 * 這樣MessageFormat.format("<meta http-equiv=''refresh'' content=''3;url={0}''/>","index.jsp")就能夠正常返回 28 * <meta http-equiv=''refresh'' content=''3;url=index.jsp'/> 29 */ 30 String tempStr2 = MessageFormat.format( 31 "註銷成功!!3秒後爲您自動跳到登陸頁面!!<meta http-equiv=''refresh'' content=''3;url={0}''/>", 32 request.getContextPath()+"/servlet/LoginUIServlet"); 33 /** 34 * 輸出結果: 35 * 註銷成功!!3秒後爲您自動跳到登陸頁面!! 36 * <meta http-equiv='refresh' content='3;url=/webmvcframework/servlet/LoginUIServlet'/> 37 */ 38 System.out.println(tempStr2); 39 40 String message = String.format( 41 "註銷成功!!3秒後爲您自動跳到登陸頁面!!<meta http-equiv='refresh' content='3;url=%s'/>", 42 request.getContextPath()+"/servlet/LoginUIServlet"); 43 request.setAttribute("message",message); 44 request.getRequestDispatcher("/message.jsp").forward(request, response); 45 } 46 47 public void doPost(HttpServletRequest request, HttpServletResponse response) 48 throws ServletException, IOException { 49 doGet(request, response); 50 } 51 52 }
用戶登陸成功後,會將登陸的用戶信息存儲在session中,因此咱們要將存儲在session中的user刪除掉,這樣就能夠實現用戶註銷了。
用戶登陸成功後就會跳轉到index.jsp頁面,在index.jsp頁面中放一個【退出登錄】按鈕,當點擊【退出登錄】按鈕時,就訪問LogoutServlet,將用戶註銷。
index.jsp的代碼以下:
1 <%@ page language="java" pageEncoding="UTF-8"%> 2 <%--爲了不在jsp頁面中出現java代碼,這裏引入jstl標籤庫,利用jstl標籤庫提供的標籤來作一些邏輯判斷處理 --%> 3 <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> 4 <!DOCTYPE HTML> 5 <html> 6 <head> 7 <title>首頁</title> 8 <script type="text/javascript"> 9 function doLogout(){ 10 //訪問LogoutServlet註銷當前登陸的用戶 11 window.location.href="${pageContext.request.contextPath}/servlet/LogoutServlet"; 12 } 13 </script> 14 </head> 15 16 <body> 17 <h1>孤傲蒼狼的網站</h1> 18 <hr/> 19 <c:if test="${user==null}"> 20 <a href="${pageContext.request.contextPath}/servlet/RegisterUIServlet" target="_blank">註冊</a> 21 <a href="${pageContext.request.contextPath}/servlet/LoginUIServlet">登錄</a> 22 </c:if> 23 <c:if test="${user!=null}"> 24 歡迎您:${user.userName} 25 <input type="button" value="退出登錄" onclick="doLogout()"> 26 </c:if> 27 <hr/> 28 </body> 29 </html>
測試開發好的註銷功能,效果以下:
到此,全部的功能都開發完成了,測試也經過了。
經過這個小例子,能夠了解到mvc分層架構的項目搭建,在平時的項目開發中,也都是按照以下的順序來進行開發的:
一、搭建開發環境
1.1 建立web項目
1.2 導入項目所需的開發包
1.3 建立程序的包名,在java中是以包來體現項目的分層架構的
二、開發domain
把一張要操做的表當成一個VO類(VO類只定義屬性以及屬性對應的get和set方法,沒有涉及到具體業務的操做方法),VO表示的是值對象,通俗地說,就是把表中的每一條記錄當成一個對象,表中的每個字段就做爲這個對象的屬性。每往表中插入一條記錄,就至關因而把一個VO類的實例對象插入到數據表中,對數據表進行操做時,都是直接把一個VO類的對象寫入到表中,一個VO類對象就是一條記錄。每個VO對象能夠表示一張表中的一行記錄,VO類的名稱要和表的名稱一致或者對應。
三、開發dao
3.1 DAO操做接口:每個DAO操做接口規定了,一張表在一個項目中的具體操做方法,此接口的名稱最好按照以下格式編寫:「I表名稱Dao」。
├DAO接口裏面的全部方法按照如下的命名編寫:
├更新數據庫:doXxx()
├查詢數據庫:findXxx()或getXxx()
3.2 DAO操做接口的實現類:實現類中完成具體的增刪改查操做
├此實現類完成的只是數據庫中最核心的操做,並無專門處理數據庫的打開和關閉,由於這些操做與具體的業務操做無關。
四、開發service(service 對web層提供全部的業務服務)
五、開發web層
點擊此處下載項目源碼
http://www.cnblogs.com/xdp-gacl/p/3902537.html