通過上一節model1的第二種方法的改進,我們系統框架在可讀性/維護性和擴展性上有了明顯的改善,但也存在一些不足:
1、jsp技術主要做界面的,但是loginCl.jsp這裏調用了java class(模型),完成對用戶驗證,顯得有點怪怪的。
2、wel.jsp是用於顯示用戶信息的(顯示數據),但wel.jsp除了顯示數據,還調用了java class(模型),代碼的優雅就蕩然無存了。也不利於將來的分工開發。
3、Servlet技術處理頁面的跳轉是最快捷和方便的,難道我們就此不用了麼?
下面就是MVC(軟件設計模式)模型的提出。
模型(M)+視圖(V)+控制器(C)
M主要由java class來做,也可以是java bean,ejb等;V 由jsp來做;C由Servlet來做
通過對問題的分析,我們:
1、增加控制器(Servlet)
2、在控制器中去調用模型(model)去完成用戶驗證,並準備要顯示的用戶信息數據。
拿用戶登錄來說,是如何體現MVC模式的:
首先Login.jsp界面相當於v層,wel.jsp也相當於v層,即界面顯示,UserBeanCl.java相當於model層,原來我們通過LoginCl.jsp來調用UserBeanCl.java處理獲得結果,是否驗證成功並實現跳轉到wel.jsp顯得有點不倫不類。現在我們通過LoginClServelt.java來獲得用戶Login.jsp界面用戶提交的數據,並調用model模型UserBeanCl.java來驗證用戶是否正確。這裏LoginClServlet相當於一個控制器C。
下面是代碼:
login.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="gb2312"%>
<%
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>My JSP 'login.jsp' starting page</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 bgcolor="pink">
<center>
用戶登錄<br>
<hr>
<form action="LoginClServlet" method="post">
用戶名:<input type="text" name="username"/><br>
密 碼:<input type="password" name="passwd"/><br>
<input type="submit" value="登錄"/>
<input type="reset" value="重置"/>
</form>
</center>
</body>
</html>
LoginClServlet.java:
//這是一個控制器,主要完成對用戶身份的驗證
//控制器本身不會去完成業務邏輯的,他主要是去調用model模型層來完成處理
package com.jingchenyong.controller;
import com.jingchenyong.model.*;
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 LoginClServlet 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 {
//得到用戶名和密碼
String u=request.getParameter("username");
String p=request.getParameter("passwd");
//使用模型(UserBeanCl),完成對用戶的驗證
//創建一個UserBean處理對象
UserBeanCl ubc=new UserBeanCl();
if(ubc.checkUser(u, p)){
//合法
//這種事轉向跳轉方法,但是這種跳轉方向效率不是很高,這樣每次重定向後,request啥的都會消失
//response.sendRedirect("wel.jsp");
//因爲sendRedirect方法效率不高,所以軟件公司常常使用轉發的方法
//這種方法效果高,同時request中的對象還可以在下一頁面使用
request.getRequestDispatcher("wel.jsp").forward(request, response);
}else{
request.getRequestDispatcher("login.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 {
this.doGet(request, response);
}
}
wel.jsp:
<%@ page language="java" import="java.util.*,java.sql.*,com.jingchenyong.model.*" pageEncoding="gb2312"%>
<%
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>My JSP 'wel.jsp' starting page</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>
<br>登錄成功!恭喜你!<%=request.getParameter("user") %>
<a href="login.jsp">返回重新登錄</a>
<hr>
<h1>用戶信息列表</h1>
<%
//定義四個分頁會用到的變量
int pageNow=1;//默認顯示第一頁
//接收用戶希望顯示的頁數(pageNow)
String s_pageNow=request.getParameter("pageNow");
//當用戶是從初始登錄進去的話就可能爲空
if(s_pageNow!=null){
//確實接收到pageNow
pageNow=Integer.parseInt(s_pageNow);
}
//調用UserBeanCl的方法(創建一個UserBeanCl的方法,然後完成處理),完成分頁顯示
UserBeanCl ubc=new UserBeanCl();
ArrayList al=ubc.getUserByPage(pageNow);
%>
<table border="1">
<tr><td>用戶id</td><td>用戶名字</td><td>密碼</td><td>電郵</td><td>級別</td></tr>
<%
for(int i=0;i<al.size();i++)
{
//從al中取出UserBean
UserBean ub=(UserBean)al.get(i);//這裏要強轉一下,因爲al.get(i)返回的是一個object類型
%>
<tr>
<td><%=ub.getUserId() %></td>
<td><%=ub.getUsername()%></td>
<td><%=ub.getPasswd() %></td>
<td><%=ub.getEmail() %></td>
<td><%=ub.getGrade() %></td>
</tr>
<%
}
%>
</table>
<%
//上一頁
if(pageNow!=1){
out.println("<a href=wel.jsp?pageNow="+(pageNow-1)+">上一頁</a>");
}
//顯示超鏈接
for(int i=pageNow;i<=pageNow+4;i++){
out.println("<a href=wel.jsp?pageNow="+i+">["+i+"]</a>");
}
//得到pageCount
int pageCount=ubc.getPageCount();
//下一頁
if(pageNow!=pageCount)
out.println("<a href=wel.jsp?pageNow="+(pageNow+1)+">下一頁</a>");
%>
</body>
</html>
UserBeanCl.java等參考上一節。這裏只是體現他們一個調用關係。
關於LoginClServlet.java中爲什麼通過轉發的方式實現跳轉,下節介紹。
轉發方式:request.getRequestDispatcher("wel.jsp").forward(request, response);