国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

詳解Java的Struts框架以及相關的MVC設計理念

2019-11-26 14:45:56
字體:
來源:轉載
供稿:網友

struts簡介
Struts是Apache軟件基金會(ASF)贊助的一個開源項目。它最初是jakarta項目中的一個子項目,并在2004年3月成為ASF的頂級項目。它通過采用JavaServlet/JSP技術,實現了基于JavaEEWeb應用的MVC設計模式的應用框架,是MVC經典設計模式中的一個經典產品。
Struts發展歷史
Struts是作為ApacheJakarta項目的組成部分,項目的創立者希望通過對該項目的研究,改進和提高JavaServerPages、servlet、標簽庫以及面向對象的技術水準。
Struts這個名字的來源于在建筑和舊式飛機中使用的支持金屬架。之所以這個框架叫做“struts”,是為了提醒我們記住那些支撐我們房屋,建筑,橋梁,甚至我們踩高蹺的基礎支撐。這也是解釋struts在開發web應用程序中所扮演的角色的精彩描述。
Struts的含義是”支柱,枝干”,它的目的是為了減少程序開發的時間,項目的創建者認為JSP,servlet的存在雖然可以幫助用戶解決大部分問題,但是由于它們的編碼對項目的開發帶來了許多的不方便,可重用性也差,所以struts應運而生,幫助用戶在最短的時間內解決這些問題。Struts框架提供如下服務:
(1)作為控制器的Servlet。
(2)提供大量的標簽庫。
(3)提供了用于國際化的框架,利用不同的配置文件,可以幫助用戶選擇合適自己的語言。
(4)提供了JDBC的實現,來定義數據源和數據庫連接池。
(5)XML語法分析工具。
(6)文件下載機制。
 
Struts原理
Struts是對JSPModel2設計標準的一種實現,下面分別從模型(Model)、視圖(view)和控制器3個部分介紹Struts的體系結構和工作原理。調用流程如下所示。

20151211171400989.jpg (632×435)

(1)視圖(view)
在Struts中,視圖層包含兩個部分,JSP頁面和ActionForm。
ActionForm封裝了用戶提交的表單信息,其實ActonForm本質上就是JavaBean,這些JavaBean中沒有業務邏輯,只提供了所有屬性的getter和setter方法,這些屬性和用戶表單中的輸入項是一一對應的。在Struts中就是通過ActionForm把用戶表單信息提交給控制器。
JSP頁面是經典MVC中主要的視圖組件,主要是信息顯示和控制器處理結果顯示的功能。
除了以上,struts還提供了一個強大的struts標簽庫,來幫助用戶解決顯示邏輯,并且利用ActonForm組件將信息傳遞到控制層。
(2)控制器(Controller)
在控制層,struts提供了一個控制器組件ActionServlet,它繼承自HttpServlet,并重載了HttpServlet的doGet(),doPost()方法,可以接受HTTP的響應,并進行轉發,同時還提供了使用XML進行轉發Mapping(映射)的功能。
(3)模型(Model)
模型表示狀態和業務邏輯的處理,在一般的web應用程序中,用JavaBean或者EJB來實現系統的業務邏輯。在Struts中,struts提供Action對象,來管理業務邏輯的調用,幫助用戶分離業務邏輯,也就是說struts本身不實現業務邏輯,但可以調用已完成的業務邏輯。


Struts工作流程
Struts工作流程如下所示。

20151211171418507.jpg (1071×696)

ActionServlet是struts中核心的控制器,所有的用戶請求都必須通過ActionServlet的處理,而struts-config.xml是struts中核心的配置文件,在這個文件中配置了用戶請求URL和控制器Action的映射關系,ActionServlet通過這個配置文件把用戶的請求發送到對應的控制器中。
在struts web應用程序中,當web應用程序啟動的時候,就會初始化ActionServlet在初始化ActionServlet的時候會加載struts-config.xml配置文件,在加載成功后會把這些URL和控制器映射關系存放在ActionMapping對象或者其他對象中。當ActionServlet接收到用戶請求的時候,就會按照下面的流程對用戶請求進行處理。
(1)ActionServlet接收到用戶的請求后,會根據請求URL尋找匹配的ActionMapping對象,如果匹配失敗,說明用戶請求的URL路徑信息有誤,所以返回請求路徑無效的信息,當找到匹配的ActionMapping的時候,進入到下一步。
(2)當ActionServlet找到匹配的ActionMapping對象的時候,會根據ActionMapping中的映射信息判斷對應的ActionForm對象是否存在,如果不存在對應的ActionForm對象就創建一個新的ActionForm對應,并把用戶提交的表單信息保存到這個ActionForm對象中。
(3)在struts-config.xml中這個配置文件,可以配置表單是否需要驗證,如果需要驗證,就調用ActionForm中的validate()方法對用戶輸入的表單進行驗證。
(4)如果ActionForm的validate()方法返回了ActionErrors對象,則表明驗證失敗,ActionServlet把這個頁面返回到用戶輸入的界面,提示用戶重新輸入。如果方法的返回值為null,就表明驗證已經通過,可以進入下一步處理。
(5)ActionServlet可以根據ActionMapping對象查找用戶請求轉發給哪個控制器Action,如果對應的Action對象不存在,就創建這個對象,并調用這個Action的excute()方法。
(6)業務邏輯控制器Action的execute()方法就會返回一個ActionForward對象,ActionServlet把控制器處理的結果轉發到ActionForward對象指定的JSP頁面。
(7)ActionForward對象指定的JSP頁面根據返回的處理結果,用合適形式把服務器處理的結果展示給用戶,到這里為止,一個客戶請求的整個過程完畢。

以上初步struts框架進行了介紹,和對原理進行了簡單的分析。至于struts是如何實現MVC的,ActionServlet屬于Controller部分,Action和ActionForm屬于Model層,還是Action屬于Controller層,不同的人對struts有不同的理解。接下來真正的運用到實踐中,在實踐中深刻去體會,原理固然重要,重要的是運用,是能駕馭和使用這個框架。就像學習開車一樣,不是一蹴而就的。

 

MVC向struts MVC框架演變過程
版本一 基本的MVC
首先是創建一個jsp索引頁面index.jsp,index.jsp創建一個表單。
如果我們完成添加用戶的模塊,我們提交表單的時候要把這個表單提交給一個servlet,于是我們在src自己的包中建立自己的servlet繼承HttpServlet,TestServlet同時覆蓋父類的doGet和doPost方法。
提交的的表單信息,我們可以在TestServlet中通過request.getParameter(“username”);取出來。之后把從表單中的數據提交到數據庫,我們的servlet作為控制器沒有添加到數據庫的職責,于是我們把訪問數據庫的業務邏輯放到UserManager.java類中。在這個類中實現添加用戶的任務。

package com.bjpowernode.servlet;   public class UserManager {                                        public void add(String username)                {                System.out.println("UserManager.add()-->>"+ username);                } } 


在TestServlet中調用UserManager中的方法。同時讓頁面轉向到添加成功的頁面add_success.jsp。
TestServlet代碼以及在web.xml中配置TestServlet.
 

<servlet>           <servlet-name>TestServlet</servlet-name>           <servlet-class>com.bjpowernode.servlet.TestServlet</servlet-class>  </servlet>      <servlet-mapping>           <servlet-name>TestServlet</servlet-name>             <url-pattern>/servlet/TestServlet</url-pattern>  </servlet-mapping> 

Testservlet代碼如下所示:

package com.bjpowernode.servlet;   import java.io.IOException; import java.util.List;   import javax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse;   public class TestServlet extendsHttpServlet {                   @Override                 protected void doGet(HttpServletRequest request, HttpServletResponse response)                 throws ServletException, IOException {                    String username = request.getParameter(“username”);                    UserManager userManager = new UserManager();                    userManager.add(username);                    request.getRequestDispatcher(“/add_success.jsp”).forward(request,response); }                     @Override                 protected void doPost(HttpServletRequest request, HttpServletResponse response)                 throws ServletException, IOException {                                            doGet(request,response);                         } } 


索引頁面index.jsp代碼,通過servlet/TestServlet來轉到TestServlet。

<form action="servlet/queryUser.action" method="post">       姓名:<input type="text" name="username"><br>       <input type="submit" value="提交"><br>    </form> 

這樣采用MVC完成了用戶的添加任務。
版本二 通過判斷標識變量
當我們不僅要完成用戶的添加而是要完成用戶的增刪改查的時候我們可以在servlet中進行判斷,是添加還是刪除等。并且在傳遞字符串的時候要加上一個標識表示相應的操作。這樣在servlet中會有很多的if和else語句。
版本三 servlet模式匹配 截取字符串判斷
我們可以在配置servlet的時候配置成為匹配模式<url-pattern>*.action</url-pattern>任何的*.action的都會轉到到TestServlet,這樣我們可以截取URL來判斷轉到哪個頁面。但在TestServlet中仍然有很多的ifelse語句進行判斷。這樣我們的TestServlet代碼如下所示。

import java.io.IOException; import java.util.List;   importjavax.servlet.ServletException; importjavax.servlet.http.HttpServlet; importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse;   public class TestServlet extendsHttpServlet {                           @Override                         protected void doGet(HttpServletRequest request, HttpServletResponse response)                             throws ServletException, IOException {                          //截取url.                          String requestURI = request.getRequestURI();                          //System.out.println("requestURI="+ requestURI);                                                   //截取http://localhost:8080/test_servlet/servlet/addUser.action test_servlet后面的東西。                          String path = requestURI.substring(requestURI.indexOf("/", 1),requestURI.indexOf("."));                          //截取得到虛目錄。/servlet/addUser                          System.out.println("path="+ path);                                                                                                     String username = request.getParameter("username");                          UserManager userManager = new UserManager();                                                   String forward = "";                          //判斷截取的path和哪個要加載的頁面相等.                          if("/servlet/delUser".equals(path))                          {                             userManager.del(username);                             forward = "del_success.jsp";                             //request.getRequestDispatcher("/del_success.jsp").forward(request,response);                          }else if("/servlet/addUser".equals(path))                          {                             userManager.add(username);                             forward= "add_success.jsp";                             //request.getRequestDispatcher("/add_success.jsp").forward(request,response);                          }else if("/servlet/modifyUser".equals(path))                          {                             userManager.modify(username);                             forward= "modify_success.jsp";                                                 //request.getRequestDispatcher("/modify_success.jsp").forward(request,response);                                                       }else if("/servlet/queryUser".equals(path))                          {                             List userList = userManager.query(username);                             request.setAttribute("userList",userList);                                                          forward= "query_success.jsp";                                                                              //request.getRequestDispatcher("/query_success.jsp").forward(request,response);                          }else                          {                             throw new RuntimeException("請求失敗!");                          }                                                   request.getRequestDispatcher(forward).forward(request,response);                                                   }                         @Override                         protected void doPost(HttpServletRequest request, HttpServletResponse response)                             throwsServletException, IOException {                                                   doGet(request,response);                         }   } 


 
UserManager代碼如下所示:

package com.bjpowernode.servlet;   import java.util.ArrayList; import java.util.List;   public class UserManager {                                                 public void add(String username)                         {                          System.out.println("UserManager.add()-->>"+ username);                         }                                                 public void del(String username)                         {                          System.out.println("UserManager.del()-->>"+ username);                         }                                                                         public void modify(String username)                         {                          System.out.println("UserManager.modify()-->>"+ username);                         }                                                 public List query(String username)                         {                          System.out.println("UserManager.query()-->>"+ username);                            List userList = new ArrayList();                          userList.add("a");                          userList.add("b");                          userList.add("c");                                                   return userList;                         }   } 


 
同時建立查詢成功,刪除成功,修改成功jsp頁面。
這樣在index.jsp頁面中通過表單的action屬性來轉到相應的頁面。

<body>                                                 <form action="servlet/queryUser.action" method="post">                          姓名:<input type="text" name="username"><br>                          <input type="submit" value="提交"><br>                         </form> </body> 


 
版本三的缺點是if太多,不穩定,當我們添加或者刪除一個if的時候還需要重新編譯源程序。這樣無法適應變化的需求。所以我們在此基礎上進行改進就需要去掉if語句,可以把改變的部分分離出來,變成可配置的,這樣就變得靈活的,需要改動jsp的文件名,在配置文件中配置一下就可以了。
版本四 if else抽象出接口和類+配置文件
首先我們把轉到的地址字符串放到一個字符串變量中,這樣TestServlet中的doGet方法,代碼如下。

String username = request.getParameter("username");                        UserManager userManager = new UserManager();                                               String forward = "";                        //判斷截取的path和哪個要加載的頁面相等.                        if("/servlet/delUser".equals(path))                        {                           userManager.del(username);                           forward= "del_success.jsp";                        }else if("/servlet/addUser".equals(path))                        {                           userManager.add(username);                           forward= "add_success.jsp";                               }elseif("/servlet/modifyUser".equals(path))                        {                           userManager.modify(username);                           forward= "modify_success.jsp";                                                                              }else if("/servlet/queryUser".equals(path))                        {                           List userList = userManager.query(username);                           request.setAttribute("userList",userList);                                                      forward= "query_success.jsp";                                                   }else                        {                           thrownew RuntimeException("請求失敗!");                        }                       request.getRequestDispatcher(forward).forward(request,response); 

統一完成了轉向。當if語句是滿足某種條件,條件不同的時候轉到不同的頁面,添加有添加的邏輯,修改有修改的邏輯,這樣我們可以抽象出接口。對添加的action操作添加,對刪除的action做出刪除任務,對修改的action做出修改。把每一個if語句中的變成為類去實現,抽象出一個Action接口,接口中方法execute()方法,返回轉向路徑字符串。類圖如下所示。

20151211171733626.jpg (928×332)

共同的Action接口,不同的實現。
Action接口代碼。

package com.bjpowernode.servlet;   importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse;   public interface Action {                                                 public String execute(HttpServletRequest request, HttpServletResponse response) throws Exception;                         } 

AddUserAction代碼。
package com.bjpowernode.servlet;   importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse;   public class AddUserActionimplements Action {                           @Override                         public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception {                          String username = request.getParameter("username");                          //Stringsex = request.getParameter("sex");                          //...........                          //調用業務邏輯.                                                   UserManager userManager = new UserManager();                          userManager.add(username);                                                   return"/add_success.jsp";                                                                           }   } 
  


DelUserAction代碼。

package com.bjpowernode.servlet;   importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse;   public class DelUserActionimplements Action {                           @Override                         public String execute(HttpServletRequest request,HttpServletResponse response) throws Exception {                          String username = request.getParameter("username");                          //String sex = request.getParameter("sex");                          //...........                          //調用業務邏輯.                          UserManager userManager = new UserManager();                          try                          {                             userManager.del(username);                          }catch(Exceptione)                          {                             return"del_error.jsp";                          }                                                                                                     return"/del_success.jsp";                                                                           }   } 

  


ModifyUserAction代碼。

package com.bjpowernode.servlet;   importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse;   public class ModifyUserActionimplements Action {                           @Override                         public String execute(HttpServletRequest request,HttpServletResponse response) throwsException {                          String username = request.getParameter("username");                          //String sex = request.getParameter("userId");                          //...........等其他...                                                   //調用業務邏輯.                                                   UserManager userManager = new UserManager();                          userManager.modify(username);                                                   return"/modify_success.jsp";                                                                           }   }   


QueryUserAction代碼。

package com.bjpowernode.servlet;   import java.util.List;   importjavax.servlet.http.HttpServletRequest; importjavax.servlet.http.HttpServletResponse;   public class QueryUserActionimplements Action {                           @Override                         public String execute(HttpServletRequest request,HttpServletResponse response) throwsException {                          String username = request.getParameter("username");                          //Stringsex = request.getParameter("userId");                          //其他查詢條件.                          //...........等其他...                                                   //調用業務邏輯.                                                   UserManager userManager = new UserManager();                          List userList = userManager.query(username);                          request.setAttribute("userList",userList);                                                   return"/query_success.jsp";//轉向路徑都可以通過配置文件讀取。                                                                                  }   } 


 
這樣使用多態方式調用不同的Action,轉向代碼如下所示。

//用多態的方式.                          Action action = null;                          if("/servlet/delUser".equals(path))                          {                             action= new DelUserAction();                          }else if("/servlet/addUser".equals(path))                          {                             action= new AddUserAction();                          }else if("/servlet/modifyUser".equals(path))                          {                             action= new ModifyUserAction();                                                       }else if("/servlet/queryUser".equals(path))                          {                             action= new QueryUserAction();                                                          }else                          {                             throw new RuntimeException("請求失敗!");                          }                          //取得action后傳遞過去。動態調用ACtion中的execute方法。                           String forward = null;                          try{                             forward= action.execute(request,response);                          }catch (Exception e) {                             e.printStackTrace();                          }                                                     //根據路徑完成轉向。                          request.getRequestDispatcher(forward).forward(request, response); 

            


上述調用不同的action,我們可以把不同的請求和對應的action配置到自己的xml文件中。配置哪個請求對應哪個Action。

<action-config>       <action path="/servlet/delUser" type="com.bjpowernode.servlet.DelUserAction">          <forward name="success">/del_success.jsp</forward>          <forward name="error">/del_error.jsp</forward>       </action>    <action path="/servlet/addUser" type="com.bjpowernode.servlet.AddUserAction">          <forward name="success">/add_success.jsp</forward>          <forward name="error">/add_error.jsp</forward>       </action>    <action path="/servlet/modifyUser" type="com.bjpowernode.servlet.ModifyUserAction">          <forward name="success">/modify_success.jsp</forward>          <forward name="error">/modify_error.jsp</forward>       </action>    <action path="/servlet/queryUser" type="com.bjpowernode.servlet.QueryUserAction">          <forward name="success">/query_success.jsp</forward>          <forward name="error">/query_error.jsp</forward>       </action>  </action-config> 


這樣我們就可以讀取配置文件來進行相應的操作。每個action對應著一些信息,它的class,執行成功以及執行失敗的配置。我們在讀取配置文件的時候可以把這些放到Map對象中。代碼如下所示。

ActionMapping                           {                                private String path;                                private String type;                                Map forwardMap;                           }                                                     forwardMap                           {                                key="success";                                value="/del_success.jsp"                                key="error";                                value="/del_error.jsp";                           }                                                     Map map = new HashMap();                           map.put("/servlet/delUser",);                           map.put("/servlet/addUser",);                           map.put("/servlet/modifyUser",);                           map.put("/servlet/queryUser",);                                                                                 //如果是刪除的ActionMapping存儲如下:                           actionMapping                           {                                path="/servlet/delUser";                                type="com.bjpowernode.servlet.DelUserAction";                                forwardMap                                {                                   key="success",value="/del_success.jsp";                                   key="error",value="/del_error.jsp";                                }                          }                           String path ="/servlet/delUser";                                                                                 //根據截取的URL請求,到Map中取得本次請求對應的Action。                           ActionMapping actionMapping =(ActionMappint)map.get(path);                                                     // 取得本次請求對應的Action類的完成路徑。                           String type =actionMappint.getType();//com.bjpowernode.servlet.DelUserAction                                                     //通過反射動態實例化Action                           Aciton action =(Action)class.forName(type).newInstance();                                                                                 //取得action后傳遞過去。動態調用ACtion中的execute方法。                           String forward =action.execute(request,response);                                                      //根據路徑完成轉向。                           request.getRequestDispatcher(forward).forward(request,response); 


我們用時序圖來描述上述調用過程(如圖)。 

20151211172040393.jpg (881×565)

Struts就是采用上述思路。Struts框架是把上圖中前端控制器servlet進行了封裝,我們只要繼承struts的Action去調用業務邏輯和轉向。讀取配置文件的工作也是封裝到了struts框架中。前篇講解了struts框架的應用實例,我們可以進行對比。    

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 布拖县| 宝应县| 辛集市| 广州市| 山东省| 呈贡县| 景德镇市| 石阡县| 子洲县| 永胜县| 彭水| 图们市| 德阳市| 泗洪县| 巨鹿县| 保靖县| 垦利县| 平阳县| 墨江| 平原县| 马鞍山市| 莱阳市| 铜川市| 定陶县| 农安县| 浏阳市| 中西区| 威信县| 西丰县| 通城县| 达州市| 九龙县| 黄冈市| 京山县| 自贡市| 正镶白旗| 喀什市| 东山县| 乡城县| 图木舒克市| 会泽县|