SUN公司推出JSP技術后,同時也推薦了兩種web應用程序的開發模式,一種是JSP+JavaBean模式,一種是Servlet+JSP+JavaBean模式。
一、JSP+JavaBean開發模式
1.1、jsp+javabean開發模式架構
jsp+javabean開發模式的架構圖如下圖(圖1-1)所示
圖1-1
在jsp+javabean架構中,JSP負責控制邏輯、表現邏輯、業務對象(javabean)的調用。
JSP+JavaBean模式適合開發業務邏輯不太復雜的web應用程序,這種模式下,JavaBean用於封裝業務數據,JSP即負責處理用戶請求,又顯示數據。
1.2、JSP+JavaBean開發模式編寫計算器
首先分析一下jsp和javabean各自的職責,jsp負責顯示計算器(calculator)頁面,供用戶輸入計算數據,並顯示計算后的結 果,javaBean負責接收用戶輸入的計算數據並且進行計算,JavaBean具有firstNum、secondNum、result、 operator屬性,並提供一個calculate方法。
1、編寫CalculatorBean,負責接收用戶輸入的計算數據並且進行計算
CalculatorBean代碼如下:
1 package me.gacl.domain;
2
3 import java.math.BigDecimal;
4
5 /**
6 * @author gacl
7 * CalculatorBean用於接收輸入參數和計算
8 */
9 public class CalculatorBean {
10
11 //用戶輸入的第一個數
12 private double firstNum;
13 //用戶輸入的第二個數
14 private double secondNum;
15 //用戶選擇的操作運算符
16 private char operator = '+';
17 //運算結果
18 private double result;
19
20 public double getFirstNum() {
21 return firstNum;
22 }
23
24 public void setFirstNum(double firstNum) {
25 this.firstNum = firstNum;
26 }
27
28 public double getSecondNum() {
29 return secondNum;
30 }
31
32 public void setSecondNum(double secondNum) {
33 this.secondNum = secondNum;
34 }
35
36 public char getOperator() {
37 return operator;
38 }
39
40 public void setOperator(char operator) {
41 this.operator = operator;
42 }
43
44 public double getResult() {
45 return result;
46 }
47
48 public void setResult(double result) {
49 this.result = result;
50 }
51
52 /**
53 * 用於計算
54 */
55 public void calculate() {
56
57 switch (this.operator) {
58 case '+': {
59 this.result = this.firstNum + this.secondNum;
60 break;
61 }
62 case '-': {
63 this.result = this.firstNum - this.secondNum;
64 break;
65 }
66 case '*': {
67 this.result = this.firstNum * this.secondNum;
68 break;
69 }
70 case '/': {
71 if (this.secondNum == 0) {
72 throw new RuntimeException("被除數不能為0!!!");
73 }
74 this.result = this.firstNum / this.secondNum;
75 // 四舍五入
76 this.result = new BigDecimal(this.result).setScale(2,
77 BigDecimal.ROUND_HALF_UP).doubleValue();
78 break;
79 }
80 default:
81 throw new RuntimeException("對不起,傳入的運算符非法!!");
82 }
83 }
84 }
2、編寫calculator.jsp,負責顯示計算器(calculator)頁面,供用戶輸入計算數據,並顯示計算后的結果
calculator.jsp頁面代碼如下:
1 <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 <%--使用me.gacl.domain.CalculatorBean --%>
3 <jsp:useBean id="calcBean" class="me.gacl.domain.CalculatorBean"/>
4 <%--接收用戶輸入的參數 --%>
5 <jsp:setProperty name="calcBean" property="*"/>
6 <%
7 //使用CalculatorBean進行計算
8 calcBean.calculate();
9 %>
10 <!DOCTYPE HTML>
11 <html>
12 <head>
13 <title>使用【jsp+javabean開發模式】開發的簡單計算器</title>
14 </head>
15
16 <body>
17 <br/>
18 計算結果是:
19 <jsp:getProperty name="calcBean" property="firstNum"/>
20 <jsp:getProperty name="calcBean" property="operator"/>
21 <jsp:getProperty name="calcBean" property="secondNum"/>
22 =
23 <jsp:getProperty name="calcBean" property="result"/>
24
25 <br/><hr> <br/>
26 <form action="${pageContext.request.contextPath}/calculator.jsp" method="post">
27 <table border="1px">
28 <tr>
29 <td colspan="2">簡單的計算器</td>
30 </tr>
31 <tr>
32 <td>第一個參數</td>
33 <td><input type="text" name="firstNum"></td>
34 </tr>
35 <tr>
36 <td>運算符</td>
37 <td><select name="operator">
38 <option value="+">+</option>
39 <option value="-">-</option>
40 <option value="*">*</option>
41 <option value="/">/</option>
42 </select></td>
43 </tr>
44 <tr>
45 <td>第二個參數</td>
46 <td><input type="text" name="secondNum"></td>
47 </tr>
48 <tr>
49 <td colspan="2"><input type="submit" value="計算"></td>
50 </tr>
51 </table>
52 </form>
53 </body>
54 </html>
運行結果如下:

二、Servlet+JSP+JavaBean開發模式
在平時的JavaWeb項目開發中,在不使用第三方mvc開發框架的情況下,通常會選擇Servlet+JSP+JavaBean開發模式來開發JavaWeb項目,Servlet+JSP+JavaBean組合開發就是一種MVC開發模式了,控制器(Controller)采用Servlet、模型(Model)采用JavaBean、視圖(View)采用JSP。在講解Servlet+JSP+JavaBean開發模式之前,先簡單了解一下MVC開發模式。
2.1、Web開發中的請求-響應模型
圖2-1
在Web世界里,具體步驟如下:
1、Web瀏覽器(如IE)發起請求,如訪問http://www.iteye.com/
2、Web服務器(如Tomcat)接收請求,處理請求(比如用戶新增,則將把用戶保存一下),最后產生響應(一般為html)。
3、web服務器處理完成后,返回內容給web客戶端(一般就是我們的瀏覽器),客戶端對接收的內容進行處理(如web瀏覽器將會對接收到的html內容進行渲染以展示給客戶)。
因此,在Web世界里:都是Web客戶端發起請求,Web服務器接收、處理並產生響應。
一般Web服務器是不能主動通知Web客戶端更新內容。雖然現在有些技術如服務器推(如Comet)、還有現在的HTML5 websocket可以實現Web服務器主動通知Web客戶端。
到此我們了解了在web開發時的請求/響應模型,接下來我們看一下標准的MVC模型是什么。
2.2、標准MVC模型概述
MVC模型:是一種架構型的模式,本身不引入新功能,只是幫助我們將開發的結構組織的更加合理,使展示與模型分離、流程控制邏輯、業務邏輯調用與展示邏輯分離。如下圖(圖2-2)所示:
圖2-2
2.3、MVC(Model-View-Controller)的概念
首先讓我們了解下MVC(Model-View-Controller)的概念:
Model(模型):數據模型,提供要展示的數據,因此包含數據和行為,可以認為是領域模型(domain)或JavaBean組件(包含數據和行為),不過現在一般都分離開來:Value Object(數據) 和 服務層(行為)。也就是模型提供了模型數據查詢和模型數據的狀態更新等功能,包括數據和業務。
View(視圖):負責進行模型的展示,一般就是我們見到的用戶界面,客戶想看到的東西。
Controller(控制器):接收用戶請求,委托給模型進行處理(狀態改變),處理完畢后把返回的模型數據返回給視圖,由視圖負責展示。 也就是說控制器做了個調度員的工作。
從圖2-1我們還看到,在標准的MVC中模型能主動推數據給視圖進行更新(觀察者設計模式,在模型上注冊視圖,當模型更新時自動更新視圖),但在Web開發中模型是無法主動推給視圖(無法主動更新用戶界面),因為在Web開發是請求-響應模型。
那接下來我們看一下在Web里MVC是什么樣子,我們稱其為 Web MVC 來區別標准的MVC。
2.4.、Web MVC概述
Web MVC中的M(模型)-V(視圖)-C(控制器)概念和標准MVC概念一樣,我們再看一下Web MVC標准架構,如下圖(圖2-3)所示:
圖2-3
在Web MVC模式下,模型無法主動推數據給視圖,如果用戶想要視圖更新,需要再發送一次請求(即請求-響應模型)。
2.5、Servlet+JSP+JavaBean開發模式介紹
Servlet+JSP+JavaBean架構其實可以認為就是我們所說的Web MVC模型,只是控制器采用Servlet、模型采用JavaBean、視圖采用JSP,如圖2-3
圖2-4
具體示例代碼:
1、模型(model)

2、視圖(View)

3、控制器(controller)

從Servlet+JSP+JavaBean(Web MVC)架構可以看出,視圖和模型分離了,控制邏輯和展示邏輯分離了。
三、Servlet+JSP+JavaBean開發模式的缺點
Servlet+JSP+JavaBean(Web MVC)架構雖然實現了視圖和模型分離以及控制邏輯和展示邏輯分離,但也有一些比較嚴重的缺點
3.1、Servlet作為控制器的缺點
此處的控制器使用Servlet,使用Servlet作為控制器有以下幾個缺點:
1、控制邏輯可能比較復雜,其實我們可以按照規約,如請求參數submitFlag=toLogin,我們其實可以直接調用toLogin方法,來簡化控制邏輯;而且每個模塊基本需要一個控制器,造成控制邏輯可能很復雜。現在流行的Web MVC框架(如Struts2)都支持"請求參數submitFlag=toAdd,就可以直接調用toAdd方法"這樣的處理機制,在Struts2中類似這樣的處理機制就稱為"動態方法調用"
2、請求參數到模型的封裝比較麻煩,如果能交給框架來做這件事情,我們可以從中得到解放。
請求參數到模型的封裝代碼:
1 // 1收集參數
2 String username = req.getParameter("username");
3 String password = req.getParameter("password");
4 // 2封裝參數
5 UserBean user = new UserBean();
6 user.setUsername(username);
7 user.setPassword(password);
當有幾十個甚至上百個參數需要封裝到模型中時,這樣寫恐怕就痛苦萬分了,要寫幾十次甚至上百次這樣的代碼,估計寫到吐了,所以現在流行的Web MVC框架(如Struts2)都提供了非常方便的獲取參數,封裝參數到模型的機制,減少這些繁瑣的工作。
3、選擇下一個視圖,嚴重依賴Servlet API,這樣很難或基本不可能更換視圖。
例如:使用Servlet API提供的request對象的getRequestDispatcher方法選擇要展示給用戶看的視圖
1 private void toLogin(HttpServletRequest req, HttpServletResponse resp)
2 throws ServletException, IOException {
3 //使用Servlet API提供的request對象的getRequestDispatcher方法選擇視圖
4 // 此處和JSP視圖技術緊密耦合,更換其他視圖技術幾乎不可能
5 request.getRequestDispatcher("/mvc/login.jsp").forward(request, response);
6 }
4、給視圖傳輸要展示的模型數據,也需要使用Servlet API,更換視圖技術也要一起更換,很麻煩。
例如:使用Servlet API提供的request對象給視圖傳輸要展示的模型數據
//使用Servlet API提供的request對象給視圖login.jsp傳輸要展示的模型數據(user)
request.setAttribute("user", user);
request.getRequestDispatcher("/mvc/login.jsp").forward(request, response)
3.2、JavaBean作為模型的缺點
此處模型使用JavaBean,JavaBean組件類既負責收集封裝數據,又要進行業務邏輯處理,這樣可能造成JavaBean組件類很龐大,所以一般現在項目都是采用三層架構,而不直接采用JavaBean。
3.3、視圖的缺點
現在被綁定在JSP,很難更換視圖,比如Velocity、FreeMarker;比如我要支持Excel、PDF視圖等等。
關於JavaWeb的兩種開發模式的講解就介紹到這里,下一篇將使用servlet+jsp+javabean來開發一個用戶登錄注冊功能,以此來加深servlet+jsp+javabean開發模式的理解。

