11.1 JSP Model I 體系結構
11.2 JSP Model II 體系結構/MVC設計模式
11.3 使用MVC設計模式改寫用戶註冊程序
11.3.1 使用serlvet實現Controller層
11.3.2 使用jsp實現表示層
11.3.3 使用JavaBean實現模型層
11.3.4 使用JDBC和DAO模式實現數據庫層
11.4 本章小結
JSP + DAO設計模式
使用JSP+JavaBean開發速度快,有一個問題:JSP與JavaBean之間緊密耦合在一塊兒,會對開發及維護形成麻煩。
使用JSP+JavaBean(模式1)開發適用於一次開發完成,並且團隊成員較少是使用。
JSP + Servlet + JavaBean
對於模式一JSP與JavaBean之間緊密耦合在一塊兒
分析:
JSP優勢,開發前臺界面方便,作UI開發容易
Servlet優勢:是JAVA程序,安全性高,性能高
Servlet缺點:顯示不方便
JavaBean優勢:可重複調用,須要接受用戶的請求參數,進行相應的處理
問題:
JSP跳轉到Servlet能夠經過表單或超連接
從Servlet跳轉到JSP:使用response對象
html
<h1>MVCDEMO</h1> <!-- <h1><%=request.getAttribute("name")%></h1> --> <h1><%=session.getAttribute("name")%></h1> ―――――――――
package org.sky.darkness.servlet ; import java.io.* ; import javax.servlet.* ; import javax.servlet.http.* ; public class MVCServlet extends HttpServlet { public void doGet(HttpServletRequest req,HttpServletResponse resp) throws IOException,ServletException { this.doPost(req,resp) ; } public void doPost(HttpServletRequest req,HttpServletResponse resp) throws IOException,ServletException { // 要傳遞一個值到mvcdemo.jsp中 // 要傳遞的內容只使用一次 // 一個頁面跳轉有用,request範圍 // 既然request沒法傳遞,那就擴大範圍-session // req.setAttribute("name","darkness") ; req.getSession().setAttribute("name","darkness") ; resp.sendRedirect("mvcdemo.jsp"); } };
JSP中兩種跳轉語句:
四種屬性範圍:
如今從Servlet中要傳遞的值只使用一次,若是把此值存放在session範圍之中,則此內容只要用戶一直與服務器保持鏈接,則此塊內存空間要一直被佔用,那麼性能會很低。
解決方法:RequestDispatcher接口,是用於由Servlet到JSP進行服務器端跳轉的接口
java
req.setAttribute("name","darkness") ; // 與<jsp:forward/>功能相同 req.getRequestDispatcher("mvcdemo.jsp").forward(req,resp);
-----------------mvc_login.jsp-------------------------------------- <form action="mvcdemo" method="POST"> 輸入姓名:<input type="text" name="uname"> <input type="submit" value="提交"> </form>
-----------------MVCServlet.java-------------------------------------- package org.sky.darkness.servlet ; import java.io.* ; import javax.servlet.* ; import javax.servlet.http.* ; import org.sky.darkness.bean.MVCCheck ; public class MVCServlet extends HttpServlet { public void doGet(HttpServletRequest req,HttpServletResponse resp) throws IOException,ServletException { this.doPost(req,resp) ; } public void doPost(HttpServletRequest req,HttpServletResponse resp) throws IOException,ServletException { String name = req.getParameter("uname") ; MVCCheck mc = new MVCCheck() ; // 將請求內容設置到mc對象之中 mc.setName(name) ; String path = null ; if(mc.isValidate()) { // 保存名字在request範圍之中 req.setAttribute("name",mc.getName()) ; path = "mvc_success.jsp" ; } else { path = "mvc_failure.jsp" ; } // 進行跳轉 req.getRequestDispatcher(path).forward(req,resp) ; } }; /* <servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.sky.darkness.servlet.MVCServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/mvcdemo</url-pattern> </servlet-mapping> */
------------------------------------- MVCCheck.java------------------------ package org.sky.darkness.bean ; public class MVCCheck { private String name ; public void setName(String name) { this.name = name ; } public String getName() { return this.name ; } // 驗證 public boolean isValidate() { if(this.name==null||"".equals(this.name)) { return false ; } else { return true ; } } };
<%@page contentType="text/html;charset=gb2312"%> <h1>輸入成功!!!</h1> <h2>歡迎:<%=request.getAttribute("name")%>光臨!!!</h2> <%@page contentType="text/html;charset=gb2312"%> <h1>輸入失敗!!!</h1> <h2><a href="mvc_login.htm">從新登錄</a></h2>
經過以上代碼能夠發現:
使用MVC開發程序,代碼稍微複雜
JSP與JavaBean之間沒有什麼特別明顯的直接關係
而Servlet根據JavaBean返回的內容進行跳轉
Servlet中最好只有如下幾種代碼:
接收參數
調用JavaBean
進行跳轉
有一些簡單的邏輯判斷
案例-使用mvc+DAO完成用戶登錄
sql
DROP TABLE person ; CREATE TABLE person ( id varchar(20) not null primary key , name varchar(20) not null , password varchar(20) ) ; INSERT INTO person (id,name,password) VALUES ('sky','darkness','wind') ; INSERT INTO person (id,name,password) VALUES ('cloud','hacker','creaker') ; -- 提交事務 commit ;
-----------------login.jsp-------------------------------------------------------------------- <%@page contentType="text/html;charset=gb2312"%> <%@page import="java.util.*"%> <html> <head> <title>登錄</title> </head> <body> <center> <h1>登錄範例——MVC實現</h1> <hr> <br> <br> <!-- 加入更加詳細的錯誤提示 --> <% if(request.getAttribute("errors")!=null) { // 有錯誤,要進行打印輸出 List all = (List)request.getAttribute("errors") ; Iterator iter = all.iterator() ; while(iter.hasNext()) { %> <li><%=iter.next()%> <% } } %> <form action="LoginServlet" method="post"> <table> <tr> <td colspan="2">用戶登錄</td> </tr> <tr> <td>用戶名:</td> <td><input type="text" name="id" value="${person.id}"></td> </tr> <tr> <td>密 碼:</td> <td><input type="password" name="password" value="${person.password}"></td> </tr> <tr> <td colspan="2"> <input type="submit" value="登錄"> <input type="reset" value="重置"> </td> </tr> </table> </form> </center> </body> </html> -------------------------LoginServlet.java--------------------------------------------- // 創建MVC中的C,完成JSP+Servlet+JavaBean的開發模式 package org.sky.darkness.servlet ; import java.io.* ; import java.util.* ; import javax.servlet.* ; import javax.servlet.http.* ; import org.sky.darkness.factory.* ; import org.sky.darkness.vo.* ; public class LoginServlet extends HttpServlet { public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException { this.doPost(request,response) ; } public void doPost(HttpServletRequest request,HttpServletResponse response) throws IOException,ServletException { // 聲明一個集合類,用於保存錯誤信息 List errors = new ArrayList() ; // 完成登錄驗證,替換掉login_conf.jsp String path = "login.jsp" ; // 一、接收請求內容 String id = request.getParameter("id") ; String password = request.getParameter("password") ; // 二、進行數據合法性驗證,包括是否爲空,長度是否知足等 // 要將接收到的內容設置給PersonVO對象 PersonVo pv = new PersonVo() ; pv.setId(id) ; pv.setPassword(password) ; pv.setErrors(errors) ; // 三、若是合法,則進行數據庫驗證 if(pv.invalidate()) { // 數據合法,能夠進行數據庫驗證 if(DAOFactory.getPersonDAOInstance().isLogin(pv)) { // 用戶ID、密碼合法 // 修改跳轉路徑 // 保存用戶名到request範圍之中 // request.setAttribute("name",pv.getName()) ; path = "login_success.jsp" ; } else { // 用戶ID、密碼非法 errors.add("錯誤的用戶ID及密碼!") ; } } // 將錯誤信息保存 request.setAttribute("errors",errors) ; request.setAttribute("person",pv) ; request.getRequestDispatcher(path).forward(request,response) ; } }; -------------------------login_success.jsp--------------------------- <%@page contentType="text/html;charset=gb2312"%> <html> <head> <title>登錄</title> </head> <body> <center> <h1>登錄範例——MVC實現</h1> <hr> <br> <br> <h2>登錄成功</h2> <h3>歡迎<font color="red" size="15"> ${person.name} </font>光臨!!!</h3> </center> </body> </html> -----------------------------PersonVo.java--------------------- // 只包含setter和getter方法的類 package org.sky.darkness.vo ; import java.util.* ; public class PersonVo { // 表中全部字段 private String id ; private String name ; private String password ; // 此屬性用於保存所有錯誤信息 private List errors ; public boolean invalidate() { boolean flag = true ; // 驗證ID if(this.id==null||"".equals(this.id)) { flag = false ; errors.add("ID不能爲空!") ; } else { // 進行長度驗證:3~10位 if(this.id.length()<3||this.id.length()>10) { flag = false ; errors.add("ID的長度應爲3~10位!") ; } } // 驗證密碼 if(this.password==null||"".equals(this.password)) { flag = false ; errors.add("密碼不能爲空!") ; } else { // 進行長度驗證:3~10位 if(this.password.length()<3||this.password.length()>10) { flag = false ; errors.add("密碼的長度應爲3~10位!") ; } } return flag ; } public void setErrors(List errors) { this.errors = errors ; } public List getErrors() { return this.errors ; } // 生成getter和setter方法 public void setId(String id) { this.id = id ; } public void setName(String name) { this.name = name ; } public void setPassword(String password) { this.password = password ; } public String getId() { return this.id ; } public String getName() { return this.name ; } public String getPassword() { return this.password ; } }; ----------------------------------PersonDAO.java---------------------- // 本接口定義本項目中所操做person表的所有方法 package org.sky.darkness.dao ; // 使用PersonVo類 import org.sky.darkness.vo.* ; public interface PersonDAO { // 須要一個登錄驗證的方法 public boolean isLogin(PersonVo pv) ; } ---------------------PersonDAOImpl.java--------------------------------- // 具體實現DAO接口的類 package org.sky.darkness.daoimpl ; // 須要鏈接數據庫 // 須要對VO的內容進行具體的驗證 import java.sql.* ; import org.sky.darkness.dao.* ; import org.sky.darkness.dbc.* ; import org.sky.darkness.vo.* ; public class PersonDAOImpl implements PersonDAO { public boolean isLogin(PersonVo pv) { boolean flag = false ; // 在此處成具體的數據庫驗證 // 聲明一個數據庫操做對象 PreparedStatement pstmt = null ; // 聲明一個結果集對象 ResultSet rs = null ; // 聲明一個SQL變量,用於保存SQL語句 String sql = null ; // DataBaseConnection爲具體的數據庫鏈接及關閉操做類 DataBaseConnection dbc = null ; // 鏈接數據庫 dbc = new DataBaseConnection() ; // 編寫SQL語句 sql = "SELECT name FROM person WHERE id=? and password=?" ; try { // 實例化數據庫操做對象 pstmt = dbc.getConnection().prepareStatement(sql) ; // 設置pstmt的內容,是按ID和密碼驗證 pstmt.setString(1,pv.getId()) ; pstmt.setString(2,pv.getPassword()) ; // 查詢記錄 rs = pstmt.executeQuery() ; // 判斷是否有記錄 if(rs.next()) { // 若是有記錄,則執行此段代碼 // 用戶是合法的,能夠登錄 flag = true ; pv.setName(rs.getString(1)) ; } // 依次關閉 rs.close() ; pstmt.close() ; } catch(Exception e) { System.out.println(e) ; } finally { // 最後必定要保證數據庫已被關閉 dbc.close() ; } return flag ; } }; -------------------------DAOFactory.java--------------------- // 取得DAO實例的工廠類 package org.sky.darkness.factory ; import org.sky.darkness.dao.* ; import org.sky.darkness.daoimpl.* ; public class DAOFactory { public static PersonDAO getPersonDAOInstance() { return new PersonDAOImpl() ; } }; ---------------------DataBaseConnection.java------------------ // 本類只用於數據庫鏈接及關閉操做 package org.sky.darkness.dbc ; import java.sql.* ; public class DataBaseConnection { // 屬性 // 定義數據庫操做的常量、對象 // 數據庫驅動程序 private final String DBDRIVER = "oracle.jdbc.driver.OracleDriver" ; // 數據庫鏈接地址 private final String DBURL = "jdbc:oracle:thin:@localhost:1521:sky" ; // 數據庫用戶名 private final String DBUSER = "scott" ; // 數據庫鏈接密碼 private final String DBPASSWORD = "tiger" ; // 聲明一個數據庫鏈接對象 private Connection conn = null ; // 在構造方法之中鏈接數據庫 public DataBaseConnection() { try { // 加載驅動程序 Class.forName(DBDRIVER) ; // 鏈接數據庫 conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD) ; } catch (Exception e) { System.out.println(e) ; } } // 返回一個數據庫鏈接 public Connection getConnection() { /// 返回鏈接對象 return this.conn ; } // 關閉數據庫鏈接 public void close() { try { this.conn.close() ; } catch (Exception e) { } } };