1. 程式人生 > >MVC入門——經典MVC登入例項詳解--附完整程式碼

MVC入門——經典MVC登入例項詳解--附完整程式碼

參考《JavaWeb開發實戰經典》
MVC是核心,是最重要的基礎!
“有不少人一直問,是不是應該把框架(Struts、Spring、Hibernate等成為開發框架)開發作為學習重點,其實:框架只是一種很簡單的應用,而整個JavaEE的核心並不在框架上,更多的是在MVC設計模式的應用上”。
所謂“基礎不牢,地動山搖”,只要真正掌握了內部核心原理(本質:MVC),再去學習任何一門框架都能很快上手!有興趣的可以去看下這本書,個人感覺這本書入門JavaWeb相當不錯!
進入正題,以下對書中的一個MVC登陸例項進行講解。
在講解例項前先簡單介紹下web開發模式,在web開發模式中主要有兩種:Mode1與ModeII (MVC)。
Mode1


Mode1就是指在開發模式中將顯示層、控制層、資料層的操作統一交給JSP或JavaBean來處理。類似於JSP+DAO的開發模式(優缺點這裡就不說了,網上有很多資料啦)。
這裡寫圖片描述

ModeII:Model-View-Control
在ModeII中所有的開發都是以Servlet為主體展開的,由Servlet接收所有的客戶端請求,然後根據請求呼叫相應的JavaBean,並將所有的顯示結果交給JSP完成,也就是俗稱的MVC設計模式。
這裡寫圖片描述
MVC是一個設計模式,它強制性地使應用程式的輸入、處理和輸出分開。
顯示層(View):主要負責接收Servlet傳遞的內容,並且呼叫JavaBean,將內容顯示給使用者。
控制層(Controller)

: 主要負責所有的使用者請求引數,判斷請求引數是否合法,根據請求的型別呼叫JavaBean執行操作並將最終的處理結果交由顯示層進行顯示。
模型層(Model): 完成一個獨立的業務操作元件,一般都是以JavaBean或者EJB的形式進行定義的。

下面進行MVC登陸例項講解(環境:Tomcat+MySQL)
這裡寫圖片描述
這裡寫圖片描述
1.在資料庫中建立user表
User表結構
這裡寫圖片描述

資料庫建立指令碼如下:

/*======================= 使用MLDN資料庫 =======================*/
USE mldn ;
/*======================= 刪除user資料表 =======================*/
DROP TABLE IF EXISTS user ; /*======================= 建立user資料表 =======================*/ CREATE TABLE user( userid VARCHAR(30) PRIMARY KEY , name VARCHAR(30) NOT NULL , password VARCHAR(32) NOT NULL ) ; /*======================= 插入測試資料 =======================*/ INSERT INTO user (userid,name,password) VALUES ('admin','administrator','admin') ;

2.定義VO類——User.java
定義登陸所需屬性:userid、name、password,並設定相應setting與getting方法

package org.lxh.mvcdemo.vo ;
public class User {
    private String userid ;
    private String name ;
    private String password ;

    public void setUserid(String userid){
        this.userid = userid ;
    }
    public void setName(String name){
        this.name = name ;
    }
    public void setPassword(String password){
        this.password = password ;
    }
    public String getUserid(){
        return this.userid ;
    }
    public String getName(){
        return this.name ;
    }
    public String getPassword(){
        return this.password ;
    }
}

3.定義JDBC資料庫操作類——DatabaseConnection.java
提供資料庫的連線與關閉操作

package org.lxh.mvcdemo.dbc ;
import java.sql.* ;
public class DatabaseConnection {
    private static final String DBDRIVER = "org.gjt.mm.mysql.Driver" ;
    private static final String DBURL = "jdbc:mysql://localhost:3306/mldn" ;
    private static final String DBUSER = "root" ;
    private static final String DBPASSWORD = "mysqladmin" ;
    private Connection conn = null ;
    public DatabaseConnection() throws Exception{
        try{
            Class.forName(DBDRIVER) ;
            this.conn = DriverManager.getConnection(DBURL,DBUSER,DBPASSWORD) ;
        }catch(Exception e){
            throw e ;
        }
    }
    public Connection getConnection(){
        return this.conn ;
    }
    public void close() throws Exception{
        if(this.conn != null){
            try{
                this.conn.close() ;
            }catch(Exception e){
                throw e ;
            }
        }
    }
}

4.定義DAO介面——IUserDAO.java
由於本程式的核心功能只是使用者的登陸驗證,所以在定義DAO介面時,只需定義一個登陸驗證方法即可findLogin(),當然需要擴充套件只需在此介面定義相應方法即可(CRUD)。

package org.lxh.mvcdemo.dao ;
import org.lxh.mvcdemo.vo.User ;
public interface IUserDAO {
    // 現在完成的是登陸驗證,那麼登陸操作只有兩種返回結果
    public boolean findLogin(User user) throws Exception ;
} 

現在的方法主要是用來查詢操作,並且採用findXxx()的命名形式,下面分別定義實現類(真實主題類)和代理類。

5.定義DAO實現類——UserDAOImpl.java
實現DAO介面的findLogin方法,對資料庫的操作

package org.lxh.mvcdemo.dao.impl ;
import org.lxh.mvcdemo.vo.User ;
import org.lxh.mvcdemo.dbc.* ;
import org.lxh.mvcdemo.dao.* ;
import java.sql.* ;
public class UserDAOImpl implements IUserDAO {
    private Connection conn = null ;
    private PreparedStatement pstmt = null ;
    public UserDAOImpl(Connection conn){
        this.conn = conn ;
    }
    public boolean findLogin(User user) throws Exception{
        boolean flag = false ;
        String sql = "SELECT name FROM user WHERE userid=? AND password=?" ;
        this.pstmt = this.conn.prepareStatement(sql) ;
        this.pstmt.setString(1,user.getUserid()) ;
        this.pstmt.setString(2,user.getPassword()) ;
        ResultSet rs = this.pstmt.executeQuery() ;
        if(rs.next()){
            user.setName(rs.getString(1)) ; // 取出一個使用者的真實姓名
            flag = true ;
        }
        this.pstmt.close() ;
        return flag ;
    }
} 

6.定義DAO代理操作類——UserProxy.java
取得資料庫連線,呼叫真實主題類

package org.lxh.mvcdemo.dao.proxy ;
import org.lxh.mvcdemo.vo.User ;
import org.lxh.mvcdemo.dbc.* ;
import org.lxh.mvcdemo.dao.* ;
import org.lxh.mvcdemo.dao.impl.* ;
import java.sql.* ;
public class UserDAOProxy implements IUserDAO {
    private DatabaseConnection dbc = null ;
    private IUserDAO dao = null ;
    public UserDAOProxy(){
        try{
            this.dbc = new DatabaseConnection() ;
        }catch(Exception e){
            e.printStackTrace() ;
        }
        this.dao = new UserDAOImpl(dbc.getConnection()) ;
    }
    public boolean findLogin(User user) throws Exception{
        boolean flag = false ;
        try{
            flag = this.dao.findLogin(user) ;   // 呼叫真實主題,完成操作
        }catch(Exception e){
            throw e ;
        }finally{
            this.dbc.close() ;
        }
        return flag ;
    }
} 

7.定義工廠類——DAOFactory.java
呼叫DAO介面,返回代理類

package org.lxh.mvcdemo.factory ;
import org.lxh.mvcdemo.dao.* ;
import org.lxh.mvcdemo.dao.proxy.* ;
public class DAOFactory {
    public static IUserDAO getIUserDAOInstance(){
        return new UserDAOProxy() ;
    }
}

DAO的操作完成只是資料層的操作,下面需要編寫Servlet類(控制層),在Servlet中接收客戶端發來的輸入資料,同時需要呼叫DAO,並且根據DAO的結果返回相應的資訊。

8.定義Servlet——LoginServlet.java
(1)通過request.getParameter()方法接收使用者請求傳送過來的userid與userpass兩個引數
(2)對兩個引數進行非空驗證,若為空,則在info類集物件中新增相應錯誤資訊;當驗證通過後,程式將呼叫DAO進行資料層的驗證,並根據DAO的返回結果來決定返回給客戶端的資訊;
(3)使用反射機制通過工廠類取得代理類例項,然後呼叫真實主題類的findLogin()方法,進行資料庫的驗證(判斷登入使用者是否資料庫user表中的使用者id與密碼一致),並將相應成功或錯誤資訊新增到info物件中;
(4)通過req.setAttribute(“info”,info) ;將最終響應資訊request範圍中;
(5)通過forward()方法跳轉回相應的JSP(String path = “login.jsp” ;)進行顯示

package org.lxh.mvcdemo.servlet ;
import java.io.* ;
import java.util.* ;
import javax.servlet.* ;
import javax.servlet.http.* ;
import org.lxh.mvcdemo.factory.* ;
import org.lxh.mvcdemo.vo.* ;
public class LoginServlet extends HttpServlet {
    public void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        String path = "login.jsp" ;
        String userid = req.getParameter("userid") ;
        String userpass = req.getParameter("userpass") ;
        List<String> info = new ArrayList<String>() ;   // 收集錯誤
        if(userid==null || "".equals(userid)){
            info.add("使用者id不能為空!") ;
        }
        if(userpass==null || "".equals(userpass)){
            info.add("密碼不能為空!") ;
        }
        if(info.size()==0){ // 裡面沒有記錄任何的錯誤
            User user = new User() ;
            user.setUserid(userid) ;
            user.setPassword(userpass) ;
            try{
                if(DAOFactory.getIUserDAOInstance().findLogin(user)){
                    info.add("使用者登陸成功,歡迎" + user.getName() + "光臨!") ;
                } else {
                    info.add("使用者登陸失敗,錯誤的使用者名稱和密碼!") ;
                }
            }catch(Exception e){
                e.printStackTrace() ;
            }
        }
        req.setAttribute("info",info) ;
        req.getRequestDispatcher(path).forward(req,resp) ;
    }
    public void doPost(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{
        this.doGet(req,resp) ;
    }


}

9.Servlet配置檔案web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

  <display-name>Welcome to Tomcat</display-name>
  <description>
     Welcome to Tomcat
  </description>
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>
            org.lxh.mvcdemo.servlet.LoginServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/mvclogin/LoginServlet</url-pattern>
    </servlet-mapping>
</web-app>

10.顯示層JSP——login.jsp
使用者登入介面以及接收響應資訊

<%@ page contentType="text/html" pageEncoding="GBK"%>
<%@ page import="java.util.*"%>
<html>
<head><title>www.mldnjava.cn,MLDN高階Java培訓</title></head>
<body>
<script language="javascript">
    function validate(f){
        if(!(/^\w{5,15}$/.test(f.userid.value))){
            alert("使用者ID必須是5~15位!") ;
            f.userid.focus() ;
            return false ;
        }
        if(!(/^\w{5,15}$/.test(f.userpass.value))){
            alert("密碼必須是5~15位!") ;
            f.userpass.focus() ;
            return false ;
        }
    }
</script>
<%
    request.setCharacterEncoding("GBK") ;
%>
<%
    List<String> info = (List<String>) request.getAttribute("info") ;
    if(info != null){   // 有資訊返回
        Iterator<String> iter = info.iterator() ;
        while(iter.hasNext()){
%>
            <h4><%=iter.next()%></h4>
<%
        }
    }
%>
<form action="LoginServlet" method="post" onSubmit="return validate(this)">
    使用者ID:<input type="text" name="userid"><br>
    密&nbsp;&nbsp;碼:<input type="password" name="userpass"><br>
    <input type="submit" value="登陸">
    <input type="reset" value="重置">
</form>
</body>
</html>

11.配置web.xml

<web-app xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
   version="2.5">

  <display-name>Welcome to Tomcat</display-name>
  <description>
     Welcome to Tomcat
  </description>
    <servlet>
        <servlet-name>login</servlet-name>
        <servlet-class>
            org.lxh.mvcdemo.servlet.LoginServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>login</servlet-name>
        <url-pattern>/mvclogin/LoginServlet</url-pattern>
    </servlet-mapping>
</web-app>

最終執行結果如下:
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
注:通過本MVC程式,與最初JSP開發(如JSP+JDBC或JSP+DAO)相比,現在的JSP頁面中的程式碼減少了很多,只是簡單地完成了輸出,實際上在開發中,讀者一定要記住JSP中最好只包含以下3中型別的程式碼(可以對照上面login.jsp程式碼):
1)接收屬性:接收從Servlet傳遞過來的屬性;
2)判斷語句:判斷傳遞到JSP中的屬性是否存在;
3)輸出內容:使用迭代或者VO進行輸出。
而且要記住一點:在JSP頁面中唯一允許匯入的包只能是java.util包,只要把握這一點,即可開發出一個簡潔、清晰的JSP頁面。
完整程式碼.rar