SSH-理解struts1架構

看兩個JSP模型

一、Model1模型   

                                    

    這是model1模型,用戶在瀏覽器端輸入,發送請求,JSP頁面收集用戶輸入的數據,並通過調用JavaBean操作(增、刪、改、查)數據庫。將操作數據庫的結果返回給JSP頁面,JSP頁面接收返回的數據,在頁面上顯示給用戶。

Model1模型分析:

優點:這樣的結構簡單,JSP頁面接收了用戶的請求,並調用了操作數據庫的類,又收集了操作數據庫的類返回的結果,顯示在JSP頁面上。這些,都是JSP頁面完成的。

缺點:JSP頁面既將顯示邏輯和業務邏輯放到了一起,頁面上嵌入了驗證和控制流轉以及大量的java代碼,jsp頁面需要做的工作量很大,頁面也很亂。


二、Model2模型

                                   

 

這是Model2模型,用戶在瀏覽器輸入,發送請求,Servlet創建resquest收集用戶在JSP頁面上輸入的信息,經過處理,通過調用JavaBeans操作(增、刪、改、查)數據庫,實現邏輯處理。最後Servelt得到操作數據庫的結果信息,調用返回的JSP頁面,將數據呈現給用戶。

 

Model2模型分析:

優點:與Model1結構相比,Model1是將頁面邏輯和業務邏輯都放在了JSP頁面上,Model2是將二者分開。頁面邏輯放在JSP頁面上,業務邏輯放在了Servlet類中,頁面邏輯和業務邏輯分開了,各部分的職責和明確。調理很清晰,益於擴展。

缺點:添加了新類,結構比Model1複雜。


兩種模型比較:

Model1Model2都完成了用戶請求,Model1結構雖簡單,JSP頁面兼併了頁面邏輯和業務邏輯的功能,分工並不明確,適合小型項目開發。相比之下,Model2將頁面邏輯和業務邏輯分開,分別放在了JSP頁面和Servlet類中,雖然複雜了些,但是分工明確,邏輯很清晰,適合大型項目開發。

 

三、struts1模型

有了Model2這種MVC的結構,來了解struts1結構,就很容易瞭解了。

                                                                                                                                                                  

                                    

         通過MVC設計模式來分析Struts1的結構,如上圖:Mode(M)l業務邏輯處理,View(V)視圖,ActionServlet(C)即中央控制器Controller。用戶在瀏覽器端輸入,發送請求。中央控制器ActionServlet收集用戶請求,並訪問對應的Action,Action處理用戶請求,調用Model操作數據庫,Action得到操作數據庫的結果信息,並指定要訪問的JSP頁面。通過JSP頁面顯示給用戶。


四、詳細對比Model2和Struts1的對比

通過上面的分析,從宏觀上了解了Modle2和Struts1的結構設計,好像看不出Struts1和Model2相比,struts1的優勢在哪裏。下面通過詳細的調用流程來分析。


Model2:用戶發送請求,Servlet收集用戶的請求信息,放到request中,讀取web.xml中的配置信息。

web.xml配置文件:

<servlet>
  	<servlet-name>TestServlet</servlet-name>
  	<servlet-class>com.powernode.servlet.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
  	<servlet-name>TestServlet</servlet-name>
  	<url-pattern>*.do</url-pattern>
  </servlet-mapping>

根據<Servlet>配置信息,找到Servlet類(TestServlet)。在TestSevlet中根據用戶請求的地址,調用相應的Action。

public class TestServlet extends HttpServlet {

	@Override
	protected void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// 截取用戶請求的地址
		String userURI = request.getRequestURI();
		System.out.println("requestURI=" + userURI);
		
		String path = userURI.substring(userURI.indexOf("/",1),userURI.indexOf("."));
		System.out.println("path=" + path);
		
		//固定的請求地址和截取到的請求地址,比較,調用Action對象
		Action action = null;
		if("/servlet/addUser".equals(path)){
			action = new AddUserAction();
		}else if("/servlet/delUser".equals(path)){
			action = new DelUserAction();
		}else if("/servlet/modifyUser".equals(path)){
			action = new ModifyUserAction();
		}else if("/servlet/queryUser".equals(path)){
			action = new QueryUserAction();
		}else{
			throw new RuntimeException("請求失敗!");
		};
		String forward = null;
		try{                                                                                                                                                              //在action中業務處理,操作數據庫的結果放到request,並返回要訪問的JSP頁面地址
			forward = action.execute(request, response);
		}catch(Exception e){
			e.printStackTrace();
		}
	       //轉發到要訪問的JSP頁面                                                                                                                                   request.getRequestDispatcher(forward).forward(request, response);
	}

	@Override
	protected void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request,response);
	}
	
}

看了上面的代碼片段和註釋,就知道了在action中調用了Model,進行業務處理,操作數據得到結果以及要訪問的JSP頁面。


在Servlet中,我們可以看到兩個缺點:1.多個IF..ELSE..分支判斷。if...else..很不穩定,如果要進行擴展,就需要修改這裏的代碼,違反了對修改關閉,對擴展開放的原則。

2.分支判斷中,比較用戶訪問的請求地址時,是固定的字符串。如果要修改,也還得修改這裏的代碼。


Struts1結構:

用戶在瀏覽器端發送請求,ActionServlet收集用戶請求,讀取struts-config.xml配置文件。

struts-config.xml配置文件:

<struts-config>
	<form-beans>
		<form-bean name="loginForm" type="com.bjpowernode.struts.LoginActionForm"></form-bean>
	</form-beans>
	<action-mappings>
		<action path="/login"
				type="com.bjpowernode.struts.LoginAction"
				name="loginForm"
				scope="request"
				>
			<forward name="success" path="/login_success.jsp"></forward>
			<forward name="error" path="/login_error.jsp"></forward>
		</action>
	</action-mappings>
  
</struts-config>
ActionServlet通過比較用戶請求地址和配置文件中的<action>中的path屬性。調用相應的Action。因爲在配置文件<action-mapping>中配置好了path和Action的對應。有了用戶的請求地址,就能找到要調用的Action。


public class LoginAction extends Action {

	@Override
	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws Exception {
		
		LoginActionForm laf = (LoginActionForm)form;
		String username = laf.getUsername();
		String password = laf.getPassword();
		
		UserManager userManager = new UserManager();
		try{
			//調用相應的業務邏輯處理類
			userManager.login(username, password);
			
			//跳轉到登錄成功頁面
			return mapping.findForward("success");
			
			//用自己封裝的異常類捕獲異常——用戶不能找到
		}catch(UserNotFoundException e){
			e.printStackTrace();
			//將錯誤信息存放到request中
			request.setAttribute("msg", "用戶不能找到,用戶名稱=【" + username +"】");
			
			//用自己封裝的異常類捕獲異常——密碼錯誤
		}catch(PasswordErrorException e){
			//將錯誤信息放到request中
			request.setAttribute("msg", "密碼錯誤!");
		}
		
		//跳轉到錯誤頁面
		return mapping.findForward("error");
	}

}
Action中調用Model,進行業務處理,操作數據庫,得到操作結果。以及返回要訪問的JSP頁面。在配置文件中,通過<forward>標籤頁定義了要跳轉的JSP頁面。


對比Model2,Struts1裏邊,沒有了If。。else。。判斷語句,配置文件解決了這個問題,通過配置文件,將請求地址和要調用的Action匹配好了。通過這樣的綁定,有了請求地址,就找到了要訪問的Action。(其實是ActionServlet操作了這個跳轉的過程ActionServlet讀取配置文件,將<action-mapping>中的信息放到map中,以鍵值對的形式存在。ActionServlet分析截取用戶的請求地址,得到key,通過這個key從map中拿到value.即要跳轉到的action)。


再看剛纔Model2中分析的兩個缺點,f。。else。。判斷語句的問題就這樣被解決掉了。那第二個問題,分支判斷中都是用的固定的字符串比較的。這個在struts1中是通過模糊匹配的方式解決的。可以參看http://blog.csdn.net/xujiaolf/article/details/43968399。這篇博客了說明了Struts1中的模糊匹配。


以上就是Model1,Model2和Struts1的對比,每一次的演變都帶來巨大的便利。都是智慧的結晶啊,前人怎麼就這麼聰明呢?!


發佈了106 篇原創文章 · 獲贊 78 · 訪問量 29萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章