日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring架构设计-增强MultiActionController

發布時間:2024/4/17 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring架构设计-增强MultiActionController 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?http://www.iteye.com/topic/72814

Spring架構設計-增強MultiActionController
在使用Spring提供的控制器時,AbstractController和SimpleFormController是應用得最多的。AbstractController是最基本的Controller,可以給予用戶最大的靈活性。SimpleFormController則用于典型的表單編輯和提交。在一個需要增,刪,改,查的需求中,增加和修改擴展SimpleFormController完成,刪除和查詢則擴展AbstractController完成。
但是像上面那樣完成某一業務對象的增,刪,改,查,都屬于一類相關的業務。把一類相關的操作分布到不同的類去完成,違返“高內聚”的設計原則。這樣四個業務操作需要四個類來完成,造成太多的類文件,難以維護和配置。
所以Spring借鑒Struts的DispatchAction提供了類似功能的MultiActionController。可以實現不同的請求路徑對應MultiActionController中的不同方法,這樣就可以把相關的操作都在一個類的相關方法中完成。這樣使得這個類具有“高內聚”,也利于系統的維護,還避免了重復代碼。增加和修改操作的數據驗證邏輯是很相似的,使用MultiActionController后就可以讓增加和修改操作共用一段數據驗證邏輯代碼。
1. 使用MultiActionController
MultiActionController會使不同的請求映射為不同方法,這里是一個實現用戶信息增刪改查的例子:

1.1 SampleMultiMethodController實現

Java代碼 ?
  • public?class?SampleMultiMethodController?extends?MultiActionController{ ??
  • ??//?用戶信息列表view ??
  • ??private?static?final?String?userInfoListView?=?"ehld.sample.getuserinfolist"; ??
  • ??//用戶信息編輯view ??
  • ??private?static?final?String?userFormView?=?"ehld.sample.userForm"; ??
  • ??//提交成功后顯示的view ??
  • ??private?static?final?String?userSuccessView?="redirect:ehld.sample.getuserinfolist.do"; ??
  • ??//?用戶信息列表key值 ??
  • ??private?static?final?String?userInfoListKey?=?"userInfoList"; ??
  • ??//?userid ??
  • ??private?final?String?userIdParam?=?"id"; ??
  • ??//?定義業務對象 ??
  • ??private?SampleAction?sampleAction; ??
  • ??public?SampleAction?getSampleAction()?{ ??
  • ????????return?sampleAction; ??
  • ??} ??
  • ??public?void?setSampleAction(SampleAction?sampleAction)?{ ??
  • ????this.sampleAction?=?sampleAction; ??
  • ??} ??
  • ??
  • ??/** ?
  • ???*?功能:獲得所有的用戶信息<br> ?
  • ??*/??
  • ??public?ModelAndView?listUser(HttpServletRequest?request, ??
  • ????????????HttpServletResponse?response)?throws?Exception?{ ??
  • ?????List?userInfoList?=?this.sampleAction.getUserInfoList(); ??
  • ?????ModelAndView?mav?=?new?ModelAndView(userInfoListView); ??
  • ?????mav.addObject(this.userInfoListKey,userInfoList); ??
  • ?????return?mav; ??
  • ??} ??
  • ??
  • ??/** ?
  • ???*?功能:編輯用戶信息<br> ?
  • ??*/??
  • ??public?ModelAndView?edtiUser(HttpServletRequest?request, ??
  • ????????????HttpServletResponse?response)?throws?Exception?{?? ??
  • ?????String?uid?=?RequestUtils.getStringParameter(request,?userIdParam); ??
  • ?????UserInfoDTO?userInfo?=?null; ??
  • ?????if?(!"".equals(uid))?{ ??
  • ????userInfo?=?this.sampleAction.getUserInfo(uid); ??
  • ?????} ??
  • ?????if?(userInfo?==?null)?{ ??
  • ????userInfo?=?new?UserInfoDTO(); ??
  • ?????} ??
  • ?????ModelAndView?mav?=?new?ModelAndView(this.userFormView,?this??
  • ????????????????.getCommandName(null),?userInfo); ??
  • ?????return?mav;?? ??
  • ??} ??
  • ??/** ?
  • ???*?功能:保存修改或新增的用戶信息<br> ?
  • ???*檢查從頁面bind的對象,如果userId或userName為空則返回原來的form頁面;否則進行保存用戶信息操作,返回?? ?
  • ?*成功頁面 ?
  • ??*/??
  • public?ModelAndView?saveUser(HttpServletRequest?request, ??
  • ????????????HttpServletResponse?response,?UserInfoDTO?command)?throws?Exception?{ ??
  • ????UserInfoDTO?user?=?(UserInfoDTO)?command; ??
  • ????ServletRequestDataBinder?binder?=?new?ServletRequestDataBinder(command, ??
  • ????????????????getCommandName(command)); ??
  • ????BindException?errors?=?binder.getErrors(); ??
  • ????ModelAndView?mav?=?null; ??
  • ????if?(user.getUserID()?==?null?||?"".equals(user.getUserID()))?{ ??
  • ????????errors.rejectValue("userID",?"userIdNull",?"用戶id不能為空"); ??
  • ????} ??
  • ??
  • ????if?(user.getUserName()?==?null?||?"".equals(user.getUserName()))?{ ??
  • ????????errors.reject("userNameNull",?"用戶名不能為空"); ??
  • ????} ??
  • ????if?(errors.hasErrors())?{ ??
  • ???????mav?=?new?ModelAndView(this.userFormView,?errors.getModel()); ??
  • ????}?else?{ ??
  • ??
  • ???????this.sampleAction.saveUserInfo(user);//?保存用戶信息 ??
  • ???????mav?=?new?ModelAndView(this.userSuccessView); ??
  • ????} ??
  • ????????return?mav; ??
  • } ??
  • ??/** ?
  • ???*?功能:刪除用戶信息<br> ?
  • ??*/??
  • public?ModelAndView?deleteUser(HttpServletRequest?request, ??
  • ????????????HttpServletResponse?response)?throws?Exception?{ ??
  • ??????String?uid?=?RequestUtils.getStringParameter(request,?userIdParam); ??
  • ??????UserInfoDTO?user?=?new?UserInfoDTO(); ??
  • ??????user.setUserID(uid); ??
  • ??????this.sampleAction.deleteUserInfo(user); ??
  • ??????ModelAndView?mav?=?new?ModelAndView(this.userSuccessView); ??
  • ??????return?mav; ??
  • } ??
  • }??
  • public class SampleMultiMethodController extends MultiActionController{// 用戶信息列表viewprivate static final String userInfoListView = "ehld.sample.getuserinfolist";//用戶信息編輯viewprivate static final String userFormView = "ehld.sample.userForm";//提交成功后顯示的viewprivate static final String userSuccessView ="redirect:ehld.sample.getuserinfolist.do";// 用戶信息列表key值private static final String userInfoListKey = "userInfoList";// useridprivate final String userIdParam = "id";// 定義業務對象private SampleAction sampleAction;public SampleAction getSampleAction() {return sampleAction;}public void setSampleAction(SampleAction sampleAction) {this.sampleAction = sampleAction;}/*** 功能:獲得所有的用戶信息<br>*/public ModelAndView listUser(HttpServletRequest request,HttpServletResponse response) throws Exception {List userInfoList = this.sampleAction.getUserInfoList();ModelAndView mav = new ModelAndView(userInfoListView);mav.addObject(this.userInfoListKey,userInfoList);return mav;}/*** 功能:編輯用戶信息<br>*/public ModelAndView edtiUser(HttpServletRequest request,HttpServletResponse response) throws Exception { String uid = RequestUtils.getStringParameter(request, userIdParam);UserInfoDTO userInfo = null;if (!"".equals(uid)) {userInfo = this.sampleAction.getUserInfo(uid);}if (userInfo == null) {userInfo = new UserInfoDTO();}ModelAndView mav = new ModelAndView(this.userFormView, this.getCommandName(null), userInfo);return mav; }/*** 功能:保存修改或新增的用戶信息<br>*檢查從頁面bind的對象,如果userId或userName為空則返回原來的form頁面;否則進行保存用戶信息操作,返回 *成功頁面*/ public ModelAndView saveUser(HttpServletRequest request,HttpServletResponse response, UserInfoDTO command) throws Exception {UserInfoDTO user = (UserInfoDTO) command;ServletRequestDataBinder binder = new ServletRequestDataBinder(command,getCommandName(command));BindException errors = binder.getErrors();ModelAndView mav = null;if (user.getUserID() == null || "".equals(user.getUserID())) {errors.rejectValue("userID", "userIdNull", "用戶id不能為空");}if (user.getUserName() == null || "".equals(user.getUserName())) {errors.reject("userNameNull", "用戶名不能為空");}if (errors.hasErrors()) {mav = new ModelAndView(this.userFormView, errors.getModel());} else {this.sampleAction.saveUserInfo(user);// 保存用戶信息mav = new ModelAndView(this.userSuccessView);}return mav; }/*** 功能:刪除用戶信息<br>*/ public ModelAndView deleteUser(HttpServletRequest request,HttpServletResponse response) throws Exception {String uid = RequestUtils.getStringParameter(request, userIdParam);UserInfoDTO user = new UserInfoDTO();user.setUserID(uid);this.sampleAction.deleteUserInfo(user);ModelAndView mav = new ModelAndView(this.userSuccessView);return mav; } }


    1.2 web-context配置

    Java代碼 ?
  • ????<!--?把sampleMultiMethodController所有的請求映射到SimpleUrlHandlerMapping?--> ??
  • ????<bean?id="handlerMapping"? ??
  • class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> ??
  • ????????<property?name="defaultHandler"?ref="?sampleMultiMethodController?"/> ??
  • ????</bean> ??
  • ??
  • ????<!--?集增,刪,改,查操作到一個類的controller?--> ??
  • ????<bean?id="sampleMultiMethodController"??
  • ??class="com.prs.application.ehld.sample.web.controller.SampleMultiMethodController"> ??
  • ????????<property?name="methodNameResolver"> ??
  • ????????????<bean? ??
  • class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver"> ??
  • ????????????????<property?name="mappings"> ??
  • ????????????????????<props> ??
  • ????????????????????????<prop?key="/ehld.sample.getuserinfolist.do">listUser</prop> ??
  • ????????????????????????<prop?key="/ehld.sample.edituserinfo.do">edtiUser</prop> ??
  • ????????????????????????<prop?key="/ehld.sample.saveuserinfo.do">saveUser</prop> ??
  • ????????????????????</props> ??
  • ????????????????</property> ??
  • ????????????</bean> ??
  • ????????</property> ??
  • ????????<property?name="sampleAction"??
  • ?ref="com.prs.application.ehld.sample.biz.action.sampleAction"></property> ??
  • ????</bean>??
  • <!-- 把sampleMultiMethodController所有的請求映射到SimpleUrlHandlerMapping --><bean id="handlerMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"><property name="defaultHandler" ref=" sampleMultiMethodController "/></bean><!-- 集增,刪,改,查操作到一個類的controller --><bean id="sampleMultiMethodController"class="com.prs.application.ehld.sample.web.controller.SampleMultiMethodController"><property name="methodNameResolver"><bean class="org.springframework.web.servlet.mvc.multiaction.PropertiesMethodNameResolver"><property name="mappings"><props><prop key="/ehld.sample.getuserinfolist.do">listUser</prop><prop key="/ehld.sample.edituserinfo.do">edtiUser</prop><prop key="/ehld.sample.saveuserinfo.do">saveUser</prop></props></property></bean></property><property name="sampleAction"ref="com.prs.application.ehld.sample.biz.action.sampleAction"></property></bean>


    2. MultiActionController的缺點
    MultiActionController把相關的業務方法集中在一個類中進行處理,減少控制類的數量。方便于系統的維護,可以重用相關的邏輯代碼,提高代碼的重用,同時也減少bean的配置。有太多的bean配置可以說是Spring 的一個暇疵。Spring提供IOC,讓我們靈活的控制bean的依賴。同時我們需要去維護太多的bean配置,Spring項目中很大程度上都在爛用xml 配置文件,這很不利于團隊開發和系統的后期維護。MultiActionController也不例外。
    1. multiActionController的配置相對復雜。MultiActionController需要注入一個MethodNameResolver對象,再通過MethodNameResolver的mappings屬性來提供請求與方法之間的映射。這樣的配置是復雜的和難以理解的。使用Spring框架的確很靈活,但是有時這種過分的靈活反而增加了系統的復雜度。
    2. multiActionController配置涉及的bean過多。除了自身的bean定義外,還需要把所有的映射配置到一個UrlHandlerMapping中去。這樣除了維護multiActionController的自身的bean定義外,還需要維護UrlHandlerMapping的定義。

    筆者十分反對這種具有連帶性的配置,一個bean的屬性改變會造成對別一個bean屬性的改變。這樣增加了系統的復雜度,和維護成本。所以必須提供一種默認的實現,讓bean之間的依賴,不要造成bean屬性之間的依賴。MultiActionController在這方面表示得十分不好。

    3. 數據綁定支持不好。SimpleFormController專門用來支持編輯和表單提效的,它支持數據綁定,在這方面做得很好。可以把jsp頁面的字段值綁定為某一對象(Command)??梢宰远xcommand的名稱。雖然MultiActionController也支持數據綁定,但是它并不支持自定義command的名稱。它默認的comamnd名稱為”command”。這也是不便于維護的,對象應該有一個代表自身含義的名字。如果所有頁面的綁定對象都以”command”作為名字,那將難以理解。MultiActionController支持數據綁定的方法參見上面例子的saveUser方法。
    3. 理想的MultiActionController構想
    一個理想的MultActionController應該配置簡單明了,并且無需要在多個地方進行配置。 應該支持對綁定對象自定義名稱。

    Java代碼 ?
  • <bean???name="sampleMultiMethodController"? ??
  • class="com.prs.application.ehld.sample.web.controller.SampleMultiMethodController"> ??
  • ????????????<property?name="commandName"?value="userInfoDTO"/> ??
  • ????????????<property?name="formView"?value="ehld.sample.userForm"/> ??
  • ????????????<property?name="successView"?value="redirect:ehld.sample.getuserinfolist.do"/>???????? ??
  • ????????????<property?name="urlMethodmappings"> ??
  • ????????????????<props> ??
  • ????????????????????<!--顯示用戶信息列表?--> ??
  • ????????????????????<prop?key="/ehld.sample.getuserinfolist.do">listUser</prop> ??
  • ????????????????????<!--?編輯用戶信息?-->??? ??
  • ????????????????????<prop?key="/ehld.sample.edituserinfo.do">edtiUser</prop> ??
  • ????????????????????<!--?保存用戶信息--> ??
  • ????????????????????<prop?key="/ehld.sample.saveuserinfo.do">saveUser</prop>???????????? ??
  • ????????????????</props> ??
  • ????????????</property> ??
  • ????????????<property?name="sampleAction"? ??
  • ref="com.prs.application.ehld.sample.biz.action.sampleAction"></property> ??
  • </bean>??
  • <bean name="sampleMultiMethodController" class="com.prs.application.ehld.sample.web.controller.SampleMultiMethodController"><property name="commandName" value="userInfoDTO"/><property name="formView" value="ehld.sample.userForm"/><property name="successView" value="redirect:ehld.sample.getuserinfolist.do"/> <property name="urlMethodmappings"><props><!--顯示用戶信息列表 --><prop key="/ehld.sample.getuserinfolist.do">listUser</prop><!-- 編輯用戶信息 --> <prop key="/ehld.sample.edituserinfo.do">edtiUser</prop><!-- 保存用戶信息--><prop key="/ehld.sample.saveuserinfo.do">saveUser</prop> </props></property><property name="sampleAction" ref="com.prs.application.ehld.sample.biz.action.sampleAction"></property> </bean>


    上面是一個更讓人能夠理解的配置。
    1.把請求與具體方法之間的映射作為MultiActionController自身的一個屬性“urlMethodmappings”。
    2.通過一個commandName屬性,可以讓用戶自由決定綁定對象的名稱。
    3.簡化UrlHandlerMapping的關聯配置。對MutilActionController的bean配置進行改動時,無再需要去關心 SimpleUrlHandlerMapping的bean配置

    4. 增強的MultiActionController實現
    上面提到理想MultiActionController的構想,有三點需要實現?,F在來討論實現它們。
    1. 把請求與具體方法之間的映射作為MultActionController自身的一個屬性。也就是說MultiActionController提供一個“urlMethodMapping”的屬性來保存請求路徑與對應方法之間的映射關系。

    我們知道MultiActionController有一個methodNameResolver的屬性,而請求路徑與方法之間的對應映射關系是由一個MethodNameResolver 的bean來保存的。我們一般可以配置一個PropertiesMethodNameResolver來作默認實現。把請求路徑與方法之間的映射關系保存在PropertiesMethodNameResolver中的“mapping”屬性中。

    我們可以在MultiActionController中定義一個PropertiesMethodNameResolver類型的成員變量“propertiesMethodNameResoler”。和定義一個Properties類型的成員變量“urlMethodmappings”
    在MultiActionController的bean進行配置的時候把urlMethodmappings的值作為propertiesMethodNameResoler的mapping的值。然后再調用MultiActionController的setMethodNameResolver()方法,把propertiesMethodNameResoler設置為MultiActionController的methodNameResolver的屬性值。要做到這一些還應該實現InitializingBean接口

    Java代碼 ?
  • public?class?MultiMethodController?extends?MultiActionController?implements??
  • ????????InitializingBean?{ ??
  • ??
  • ????private?Properties?urlMethodmappings; ??
  • ????????public?void?afterPropertiesSet()?throws?Exception?{ ??
  • ????????if?(urlMethodmappings?!=?null?&&?!urlMethodmappings.isEmpty())?{ ??
  • ???????? ??
  • ????????????PropertiesMethodNameResolver?propertiesMethodNameResolver? ??
  • =?new?PropertiesMethodNameResolver(); ??
  • ????????????propertiesMethodNameResolver.setMappings(urlMethodmappings); ??
  • ????????????this.setMethodNameResolver(propertiesMethodNameResolver); ??
  • ????????????if?(this.logger.isInfoEnabled())?{ ??
  • ????????????????this.logger.info("binding?success......?"); ??
  • ????????????} ??
  • ????????}?else?{ ??
  • ????????????logger.info("no?'urlMethodmappings'?set?on?MultiMethodController"); ??
  • ????????} ??
  • ????} ??
  • ????/** ?
  • ?????*?@return?Returns?the?urlMethodmappings. ?
  • ?????*/??
  • ????public?Properties?getUrlMethodmappings()?{ ??
  • ????????return?urlMethodmappings; ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@param?urlMethodmappings ?
  • ?????*????????????The?urlMethodmappings?to?set. ?
  • ?????*/??
  • ????public?void?setUrlMethodmappings(Properties?urlMethodmappings)?{ ??
  • ????????this.urlMethodmappings?=?urlMethodmappings; ??
  • ????} ??
  • }??
  • public class MultiMethodController extends MultiActionController implementsInitializingBean {private Properties urlMethodmappings;public void afterPropertiesSet() throws Exception {if (urlMethodmappings != null && !urlMethodmappings.isEmpty()) {PropertiesMethodNameResolver propertiesMethodNameResolver = new PropertiesMethodNameResolver();propertiesMethodNameResolver.setMappings(urlMethodmappings);this.setMethodNameResolver(propertiesMethodNameResolver);if (this.logger.isInfoEnabled()) {this.logger.info("binding success...... ");}} else {logger.info("no 'urlMethodmappings' set on MultiMethodController");}}/*** @return Returns the urlMethodmappings.*/public Properties getUrlMethodmappings() {return urlMethodmappings;}/*** @param urlMethodmappings* The urlMethodmappings to set.*/public void setUrlMethodmappings(Properties urlMethodmappings) {this.urlMethodmappings = urlMethodmappings;} }


    ?

    Java代碼 ?
  • 在afterPropertiesSet中, ??
  • PropertiesMethodNameResolver??propertiesMethodNameResolver? ??
  • =?new?PropertiesMethodNameResolver();? ??
  • ????????????創建一個默認的PropertiesMethodNameResolver的實例 ??
  • ????????????propertiesMethodNameResolver.setMappings(urlMethodmappings); ??
  • ????????????把urlMethodmappings作為propertiesMethodNameResolver的mapping屬性值 ??
  • ????????????this.setMethodNameResolver(propertiesMethodNameResolver); ??
  • ????????????調用父類方法,把propertiesMethodNameResolver注入MethodNameResolver屬性中??
  • 在afterPropertiesSet中, PropertiesMethodNameResolver propertiesMethodNameResolver = new PropertiesMethodNameResolver(); 創建一個默認的PropertiesMethodNameResolver的實例propertiesMethodNameResolver.setMappings(urlMethodmappings);把urlMethodmappings作為propertiesMethodNameResolver的mapping屬性值this.setMethodNameResolver(propertiesMethodNameResolver);調用父類方法,把propertiesMethodNameResolver注入MethodNameResolver屬性中


    2. 通過一個commandName屬性,可以讓用戶自由決定綁定對象的名稱
    MultiActionController的

    Java代碼 ?
  • getCommandName如下 ??
  • ????????????public?static?final?String?DEFAULT_COMMAND_NAME?=?"command"; ??
  • protected?String?getCommandName(Object?command)?{ ??
  • ???????????????return?DEFAULT_COMMAND_NAME; ??
  • ????????????}??
  • getCommandName如下public static final String DEFAULT_COMMAND_NAME = "command"; protected String getCommandName(Object command) {return DEFAULT_COMMAND_NAME;}

    MultiActionController并沒有一個setCommandName的方法,所以我們需要一個setCommandName的方法,然后重寫getCommandName(Object command)方法

    Java代碼 ?
  • private?String?commandName?=DEFAULT_COMMAND_NAME; ??
  • ????public?String?getCommandName()?{ ??
  • ????????return?commandName; ??
  • ????} ??
  • ????public?void?setCommandName(String?commandName)?{ ??
  • ????????this.commandName?=?commandName; ??
  • ????} ??
  • ????protected?String?getCommandName(Object?object)?{ ??
  • ????????return?this.getCommandName(); ??
  • ????}??
  • private String commandName =DEFAULT_COMMAND_NAME;public String getCommandName() {return commandName;}public void setCommandName(String commandName) {this.commandName = commandName;}protected String getCommandName(Object object) {return this.getCommandName();}


    如果沒有設置commandName屬性,默認值為“command”,通過setCommandName方法就可以自由的去決定comamnd對象的名稱了。
    這樣我們基本上已經簡化了MultiActionController的自身的配置,但是它仍然需要與一個UrlHandlerMapping聯系,也就是增加或刪除一個MutilActionController的bean。都需要修改某一個UrlHandlerMapping的bean的配置。這也就是我們上面說的理想MultiActionController的第3點。


    3. 簡化UrlHandlerMapping的關聯配置
    UrlHandlerMapping是請求路徑與Controller之間的對應映射。UrlHandlerMapping有一個最簡單的實現就是SimpleUrlHandlerMapping.

    Java代碼 ?
  • <bean?id="simpleUrlMapping"????????????????????????class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> ??
  • ?????<property?name="mappings"> ??
  • ??????<props> ??
  • ??????<prop?key="/welcom.do">oneController</prop> ??
  • ??????</props> ??
  • ???</property>???????? ??
  • </bean>??
  • <bean id="simpleUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"><property name="mappings"><props><prop key="/welcom.do">oneController</prop></props></property> </bean>


    “/welcom.do”這個請求路徑對應bean 名稱為oneController的Controller實例。所以應將MultiActionController中的所有請求路徑都保存在一個UrlHandlerMapping的mappings屬性中,作為key值,把MutilActionController 的bean實例作為value作。
    DispatcherServlet在初始化時會在Context中查找所有類型為HandlerMapping的bean,將所有的HandlerMapping實例保存在handlerMappings屬性List中。當一個請求進入時,DispatcherServlet會依次查找handlerMappings List中的HandlerMapping實例是否匹配當前請求路徑,如果匹配當前請求路徑,就獲取請求路徑對應的Controller實例;如果Controller實例是MultiActionController類型時,MultiActionController就會會根據當前請求路徑去調用MultiActionController相應的方法。這就是一個MultiActionController的執行過程。
    根據這樣的原理,能夠有一個類似SimpleUrlHandlerMapping的HandlerMapping能夠在初始化的時候自動在當前WebApplicationContext中查找所有MultiActionController類型的bean。然后依次生成一個以MultiActionController的urlMethodmappings Map的所有key值作為key值,以MultiActionController實例為value值的一個Map,并把這個Map所有元素都添加到SimpleUrlHandlerMapping的mappings屬性中。這樣就達到了我們自動化配置的效果。
    我們把這個HandlerMapping 稱為MultiMethodControllerUrlHandlerMapping,下面我們講怎么具體去實現它。
    5.實現MultiMethodControllerUrlHandlerMapping
    我們在上面討論過了怎么實現MultiMethodControllerUrlHandlerMapping,要實現為具體的代碼,我們可以通過擴展org.springframework.web.servlet.handler.AbstractUrlHandlerMapping。AbstractUrlHandlerMapping擴展了org.springframework.web.context.support.WebApplicationObjectSupport。WebApplicationObjectSupport可以獲得當前WebApplicationContext。
    1. 重寫initApplicationContext方法,在context中查找所有MultiActionController類型的bean,把MultiActionController的urlMethodmappings屬性的key值為key值,MultiActionController實例為鍵值的鍵值對添加到一個urlMap中。

    Java代碼 ?
  • public?class?MultiMethodControllerUrlHandlerMapping?extends?AbstractUrlHandlerMapping{ ??
  • ????private??Map?urlMap?=?new?HashMap(); ??
  • ????public?void?initApplicationContext()?throws?BeansException?{ ??
  • ????????initialUrlMap(); ??
  • ????} ??
  • ????protected?void?initialUrlMap()throws?BeansException{ ??
  • ????????//找查所有MultiMethodController類型和子類型的bean到一個map中,bean?Name為key值?,bean實例為value值 ??
  • ????????Map?matchingBeans?=?BeanFactoryUtils.beansOfTypeIncludingAncestors( ??
  • ????????????????getWebApplicationContext(), ??
  • ????????????????MultiMethodController.class,?true,?false); ??
  • ????????List?controllers?=?null; ??
  • ????????if(!matchingBeans.isEmpty()){ ??
  • ????????????controllers?=?new?ArrayList(matchingBeans.values()); ??
  • ????????????for(int?i?=?0;?controllers?!=?null?&&?i?<?controllers.size();i++){ ??
  • ????????????????MultiMethodController?controller?=?(MultiMethodController)controllers.get(i); ??
  • ????????????????Properties?urlPros?=?controller.getUrlMethodmappings();????? ??
  • ????????????????Iterator?itr?=?urlPros.keySet().iterator(); ??
  • ????????????????for(;itr.hasNext();){ ??
  • ????????????????????String?url?=?(String)itr.next(); ??
  • ????????????????????urlMap.put(url,controller); ??
  • ????????????????} ??
  • ????????????} ??
  • ????????} ??
  • }??
  • public class MultiMethodControllerUrlHandlerMapping extends AbstractUrlHandlerMapping{private Map urlMap = new HashMap();public void initApplicationContext() throws BeansException {initialUrlMap();}protected void initialUrlMap()throws BeansException{//找查所有MultiMethodController類型和子類型的bean到一個map中,bean Name為key值 ,bean實例為value值Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(getWebApplicationContext(),MultiMethodController.class, true, false);List controllers = null;if(!matchingBeans.isEmpty()){controllers = new ArrayList(matchingBeans.values());for(int i = 0; controllers != null && i < controllers.size();i++){MultiMethodController controller = (MultiMethodController)controllers.get(i);Properties urlPros = controller.getUrlMethodmappings(); Iterator itr = urlPros.keySet().iterator();for(;itr.hasNext();){String url = (String)itr.next();urlMap.put(url,controller);}}} }

    2. 遍歷urlMap,調用AbstractUrlHandlerMapping的registerHandler(String urlPath, Object handler)方法,依次將url與對應的handler注冊到AbstractUrlHandlerMapping的handlerMap中。

    Java代碼 ?
  • protected?void?registerUrlMap()throws?BeansException{ ??
  • ????????if?(this.urlMap.isEmpty())?{ ??
  • ????????????logger.info("Neither?'urlMap'?nor?'mappings'?set?on?MultiMethodControllerUrlHandlerMapping"); ??
  • ????????} ??
  • ????????else?{ ??
  • ????????????Iterator?itr?=?this.urlMap.keySet().iterator(); ??
  • ????????????while?(itr.hasNext())?{ ??
  • ????????????????String?url?=?(String)?itr.next(); ??
  • ????????????????Object?handler?=?this.urlMap.get(url); ??
  • ????????????????//?prepend?with?slash?if?it's?not?present ??
  • ????????????????if?(!url.startsWith("/"))?{ ??
  • ????????????????????url?=?"/"?+?url; ??
  • ????????????????} ??
  • ????????????????//父類方法 ??
  • ????????????????registerHandler(url,?handler); ??
  • ????????????} ??
  • ????????}??????? ??
  • ???????? ??
  • ????}??
  • protected void registerUrlMap()throws BeansException{if (this.urlMap.isEmpty()) {logger.info("Neither 'urlMap' nor 'mappings' set on MultiMethodControllerUrlHandlerMapping");}else {Iterator itr = this.urlMap.keySet().iterator();while (itr.hasNext()) {String url = (String) itr.next();Object handler = this.urlMap.get(url);// prepend with slash if it's not presentif (!url.startsWith("/")) {url = "/" + url;}//父類方法registerHandler(url, handler);}} }


    然后在initApplicationContext方法中調用registerUrlMap方法

    Java代碼 ?
  • public?void?initApplicationContext()?throws?BeansException?{ ??
  • ????????initialUrlMap(); ??
  • ????????registerUrlMap(); ??
  • ????}??
  • public void initApplicationContext() throws BeansException {initialUrlMap();registerUrlMap();}


    3. 使用MultiMethodControllerUrlHandlerMapping
    使用MultiMethodControllerUrlHandlerMapping,只需要在ApplicationContext中,定義成一個bean就可以了。

    Java代碼 ?
  • id="multiMethodControllerUrlHandlerMapping"??
  • ??class="com.prs.application.ehld.web.handler.MultiMethodControllerUrlHandlerMapping"> ??
  • ??<property?name="order"> ??
  • ?????<value>3</value> ??
  • ??</property> ??
  • </bean>??
  • id="multiMethodControllerUrlHandlerMapping"class="com.prs.application.ehld.web.handler.MultiMethodControllerUrlHandlerMapping"><property name="order"><value>3</value></property> </bean>


    注意:在一個context如果定義多個HandlerMapping,需要為每一個HandlerMapping指定order屬性。

    你只需要在在context 中定義MultiMethodControllerUrlHandlerMapping,在使用MultiActionController時,只需要配置urlMethodmappings屬性就可以了。當刪除或增加一個MultiActionController的bean時,無需要連帶配置任何HandlerMapping. 簡化了bean的配置。使得MultiActionControler的bean配置只關心自身的屬性配置,而無需要去關心看起來與自身無關的HandlerMapping的配置。使得整個配置更合乎人們正常的思維邏輯,減少配置的復雜性。
    6.設計討論
    在這里我們將對以Spring為基礎進行項目架構設計進行一些討論.
    1. MultiActionController還是AbstractController與SimpleFormController組合
    在使用Spring MVC時,SimpleFormController用于表單編輯和提交;而復雜的功能則通過擴展AbstractcController完成。這就是所謂的AbstractController與SimpleFormController組合。以AbstractController與SimpleFormController的結合來完成表示層邏輯。
    Spring MVC雖然也提供了MultiActionController,但是它似乎天生就有點蹩腳。對數據綁定支持不是很好,在用于表單編輯和提交時不像SimpleFormController那么強大。其實通過對MultiActionController的擴展和增強,完成可以實現與SimpleFormController同樣的功能,比如數據校驗等,并且還比SimpleFormController具有更多的靈活性。
    在OO技術中,有一個重要的原則:低耦合,高內聚;我們應該按職責來設計對象。按對象應該具有的職責來給對象設計相應的方法。如果把一個對象本來該具有的職責分散到不同類中去完成,那么這個些類是違反“低耦合,高內聚”原則的。一個類不是高內聚的,就不便于維護和擴展,造成大量重復代碼的產生。同樣把一組相關的功能分散到多個Controller去實現,是違反“低耦合,高內聚”原則的,可以就會產生大量的重復代碼。比如參數獲取,數據校驗等。如果使用MultiActionController,把相關的功能由一個Controller的不同方法實現,集中在一個Controller類中處理,就使得這個Controller類是具有“高內聚”性的。所以,在項目應用中,相關的功能應該由一個MultiActionController的不同方法去實現。這樣就便于代碼的維護,提高代碼的重用,減少bean配置,降低項目的復雜度。
    2. 靈活性與簡易化
    Spring作為一個輕量級的j2ee基礎框架,使用是非常靈活的。特別是可以通過xml文件來靈活的配置對象之間的依賴。但是,以Spring作為框架的項目,bean的配置太多,反而增加了項目的復雜度。在開發過程中,應該把主要精力花在關注業務邏輯的實現上面,而不應該花在配置上面。靈活度越大也就導致了復雜度越高。當然,Spring是一個通用框架,應該具有這樣的靈活性,才便于擴展,以滿足各種應用需要。
    在具體的項目中,就應該使架構使用起來簡單,易用。特別是以Spring作為基礎的架構中,應該通過設計降低配置的復雜度,盡可能的減少bean的配置和使配置簡單化。
    一個bean屬性發生變化,不應該產生連帶關系,使得其它bean也需要修改配置。這是不利于團隊開發的。在團隊開發中,開發人員應該只關心業務對象的bean配置。
    像HandlerMapping這些屬于框架基礎bean配置一旦定義后就應該具有穩定性。不要因為業務對象bean的改變而需要開發人員隨之進行修改。
    3. 增強的MultiActionController與MultiMethodControllerUrlHandlerMapping
    通過擴展MultiActionController,使得它得到增強,能夠實現SimpleFormController的功能,同時使得配置更加直觀和簡易。
    只需要定義一個MultiMethodControllerUrlHandlerMapping,使得開發人員只需要關注相關MultiActionController的配置,而無需去再關注和修改HandlerMapping的配置。
    通過MultiMethodControllerUrlHandlerMapping 與增強的MultiActionController結合,更易于運用OO技術設計高內聚的Controller類,減化bean的配置。讓開發人員把精力花在系統的業務邏輯的實現上,而不會去過度關心bean的配置。
    7.完整的代碼實現
    這里把增強的MultiActionController稱為MultiMethodController
    1. MultiMethodController.java

    Java代碼 ?
  • public?class?MultiMethodController?extends?MultiActionController?implements??
  • ????????InitializingBean?{ ??
  • ??
  • ????private?Properties?urlMethodmappings; ??
  • ???? ??
  • ????private?String?commandName?=DEFAULT_COMMAND_NAME; ??
  • ???? ??
  • ????private?String?formView?; ??
  • ???? ??
  • ????private?String?successView; ??
  • ???? ??
  • ??
  • ????/** ?
  • ?????*?@return?Returns?the?formView. ?
  • ?????*/??
  • ????public?String?getFormView()?{ ??
  • ????????return?formView; ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@param?formView?The?formView?to?set. ?
  • ?????*/??
  • ????public?void?setFormView(String?formView)?{ ??
  • ????????this.formView?=?formView; ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@return?Returns?the?successView. ?
  • ?????*/??
  • ????public?String?getSuccessView()?{ ??
  • ????????return?successView; ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@param?successView?The?successView?to?set. ?
  • ?????*/??
  • ????public?void?setSuccessView(String?successView)?{ ??
  • ????????this.successView?=?successView; ??
  • ????} ??
  • ??
  • ????/*?(non-Javadoc) ?
  • ?????*?@see?org.springframework.web.servlet.mvc.multiaction.MultiActionController#getCommandName(java.lang.Object) ?
  • ?????*/??
  • ????protected?String?getCommandName(Object?object)?{ ??
  • ????????return?this.getCommandName(); ??
  • ????} ??
  • ??
  • ????/* ?
  • ?????*?(non-Javadoc) ?
  • ?????*? ?
  • ?????*?@see?org.springframework.beans.factory.InitializingBean#afterPropertiesSet() ?
  • ?????*/??
  • ????public?void?afterPropertiesSet()?throws?Exception?{ ??
  • ????????if?(urlMethodmappings?!=?null?&&?!urlMethodmappings.isEmpty())?{ ??
  • ???????? ??
  • ????????????PropertiesMethodNameResolver?propertiesMethodNameResolver?=?new?PropertiesMethodNameResolver(); ??
  • ????????????propertiesMethodNameResolver.setMappings(urlMethodmappings); ??
  • ????????????this.setMethodNameResolver(propertiesMethodNameResolver); ??
  • ????????????if?(this.logger.isInfoEnabled())?{ ??
  • ????????????????this.logger.info("binding?success......?"); ??
  • ????????????} ??
  • ????????}?else?{ ??
  • ????????????logger.info("no?'urlMethodmappings'?set?on?MultiMethodController"); ??
  • ????????} ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@return?Returns?the?urlMethodmappings. ?
  • ?????*/??
  • ????public?Properties?getUrlMethodmappings()?{ ??
  • ????????return?urlMethodmappings; ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@param?urlMethodmappings ?
  • ?????*????????????The?urlMethodmappings?to?set. ?
  • ?????*/??
  • ????public?void?setUrlMethodmappings(Properties?urlMethodmappings)?{ ??
  • ????????this.urlMethodmappings?=?urlMethodmappings; ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@return?Returns?the?commandName. ?
  • ?????*/??
  • ????public?String?getCommandName()?{ ??
  • ????????return?commandName; ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@param?commandName?The?commandName?to?set. ?
  • ?????*/??
  • ????public?void?setCommandName(String?commandName)?{ ??
  • ????????this.commandName?=?commandName; ??
  • ????} ??
  • ??
  • } ??
  • ??
  • 2.??MultiMethodControllerUrlHandlerMapping.java ??
  • public?class?MultiMethodControllerUrlHandlerMapping?extends?AbstractUrlHandlerMapping{ ??
  • ????private??Map?urlMap?=?new?HashMap(); ??
  • ????/** ?
  • ?????*映射URL?到?Controller?的bean?名稱 ?
  • ?????*這是一個配置HandMapping的典型的方式. ?
  • ?????*<p>支持直接URL匹配和"ant風格"模式的匹配 ?
  • ?????*詳細的語法,參見AntPathMatcher類 ?
  • ?????* ?
  • ?????*?@param?mappings?URL作為鍵,而bean?名稱作為鍵值的Properties ?
  • ?????*?@see?org.springframework.util.AntPathMatcher ?
  • ?????*/??
  • ????public?void?setMappings(Properties?mappings){ ??
  • ????????this.urlMap.putAll(mappings); ??
  • ????} ??
  • ??
  • ????/** ?
  • ?????*?@return?Returns?the?urlMap. ?
  • ?????*/??
  • ????public?Map?getUrlMap()?{ ??
  • ????????return?urlMap; ??
  • ????} ??
  • ??
  • ??
  • ????/** ?
  • ?????*?@param?urlMap?The?urlMap?to?set. ?
  • ?????*/??
  • ????public?void?setUrlMap(Map?urlMap)?{ ??
  • ????????this.urlMap?=?urlMap; ??
  • ????} ??
  • ???? ??
  • ???? ??
  • ????public?void?initApplicationContext()?throws?BeansException?{ ??
  • ????????initialUrlMap(); ??
  • ????????registerUrlMap(); ??
  • ????} ??
  • ???? ??
  • ????protected?void?registerUrlMap()throws?BeansException{ ??
  • ????????if?(this.urlMap.isEmpty())?{ ??
  • ????????????logger.info("Neither?'urlMap'?nor?'mappings'?set?on?MultiMethodControllerUrlHandlerMapping"); ??
  • ????????} ??
  • ????????else?{ ??
  • ????????????Iterator?itr?=?this.urlMap.keySet().iterator(); ??
  • ????????????while?(itr.hasNext())?{ ??
  • ????????????????String?url?=?(String)?itr.next(); ??
  • ????????????????Object?handler?=?this.urlMap.get(url); ??
  • ????????????????//?prepend?with?slash?if?it's?not?present ??
  • ????????????????if?(!url.startsWith("/"))?{ ??
  • ????????????????????url?=?"/"?+?url; ??
  • ????????????????} ??
  • ????????????????registerHandler(url,?handler); ??
  • ????????????} ??
  • ????????}??????? ??
  • ???????? ??
  • ????} ??
  • ???? ??
  • ????protected?void?initialUrlMap()throws?BeansException{ ??
  • ????????//找查所有MultiMethodController類型和子類型的bean到一個map中,bean?Name為key值?,bean實例為value值 ??
  • ????????Map?matchingBeans?=?BeanFactoryUtils.beansOfTypeIncludingAncestors( ??
  • ????????????????getWebApplicationContext(), ??
  • ????????????????MultiMethodController.class,?true,?false); ??
  • ????????List?controllers?=?null; ??
  • ????????if(!matchingBeans.isEmpty()){ ??
  • ????????????controllers?=?new?ArrayList(matchingBeans.values()); ??
  • ????????????Collections.sort(controllers,?new?OrderComparator()); ??
  • ????????????for(int?i?=?0;?controllers?!=?null?&&?i?<?controllers.size();i++){ ??
  • ????????????????MultiMethodController?controller?=?(MultiMethodController)controllers.get(i); ??
  • ????????????????Properties?urlPros?=?controller.getUrlMethodmappings();????? ??
  • ????????????????Iterator?itr?=?urlPros.keySet().iterator(); ??
  • ????????????????for(;itr.hasNext();){ ??
  • ????????????????????String?url?=?(String)itr.next(); ??
  • ????????????????????urlMap.put(url,controller); ??
  • ????????????????} ??
  • ????????????} ??
  • ????????} ??
  • ????} ??
  • }??
  • public class MultiMethodController extends MultiActionController implementsInitializingBean {private Properties urlMethodmappings;private String commandName =DEFAULT_COMMAND_NAME;private String formView ;private String successView;/*** @return Returns the formView.*/public String getFormView() {return formView;}/*** @param formView The formView to set.*/public void setFormView(String formView) {this.formView = formView;}/*** @return Returns the successView.*/public String getSuccessView() {return successView;}/*** @param successView The successView to set.*/public void setSuccessView(String successView) {this.successView = successView;}/* (non-Javadoc)* @see org.springframework.web.servlet.mvc.multiaction.MultiActionController#getCommandName(java.lang.Object)*/protected String getCommandName(Object object) {return this.getCommandName();}/** (non-Javadoc)* * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()*/public void afterPropertiesSet() throws Exception {if (urlMethodmappings != null && !urlMethodmappings.isEmpty()) {PropertiesMethodNameResolver propertiesMethodNameResolver = new PropertiesMethodNameResolver();propertiesMethodNameResolver.setMappings(urlMethodmappings);this.setMethodNameResolver(propertiesMethodNameResolver);if (this.logger.isInfoEnabled()) {this.logger.info("binding success...... ");}} else {logger.info("no 'urlMethodmappings' set on MultiMethodController");}}/*** @return Returns the urlMethodmappings.*/public Properties getUrlMethodmappings() {return urlMethodmappings;}/*** @param urlMethodmappings* The urlMethodmappings to set.*/public void setUrlMethodmappings(Properties urlMethodmappings) {this.urlMethodmappings = urlMethodmappings;}/*** @return Returns the commandName.*/public String getCommandName() {return commandName;}/*** @param commandName The commandName to set.*/public void setCommandName(String commandName) {this.commandName = commandName;}}2. MultiMethodControllerUrlHandlerMapping.java public class MultiMethodControllerUrlHandlerMapping extends AbstractUrlHandlerMapping{private Map urlMap = new HashMap();/***映射URL 到 Controller 的bean 名稱*這是一個配置HandMapping的典型的方式.*<p>支持直接URL匹配和"ant風格"模式的匹配*詳細的語法,參見AntPathMatcher類** @param mappings URL作為鍵,而bean 名稱作為鍵值的Properties* @see org.springframework.util.AntPathMatcher*/public void setMappings(Properties mappings){this.urlMap.putAll(mappings);}/*** @return Returns the urlMap.*/public Map getUrlMap() {return urlMap;}/*** @param urlMap The urlMap to set.*/public void setUrlMap(Map urlMap) {this.urlMap = urlMap;}public void initApplicationContext() throws BeansException {initialUrlMap();registerUrlMap();}protected void registerUrlMap()throws BeansException{if (this.urlMap.isEmpty()) {logger.info("Neither 'urlMap' nor 'mappings' set on MultiMethodControllerUrlHandlerMapping");}else {Iterator itr = this.urlMap.keySet().iterator();while (itr.hasNext()) {String url = (String) itr.next();Object handler = this.urlMap.get(url);// prepend with slash if it's not presentif (!url.startsWith("/")) {url = "/" + url;}registerHandler(url, handler);}} }protected void initialUrlMap()throws BeansException{//找查所有MultiMethodController類型和子類型的bean到一個map中,bean Name為key值 ,bean實例為value值Map matchingBeans = BeanFactoryUtils.beansOfTypeIncludingAncestors(getWebApplicationContext(),MultiMethodController.class, true, false);List controllers = null;if(!matchingBeans.isEmpty()){controllers = new ArrayList(matchingBeans.values());Collections.sort(controllers, new OrderComparator());for(int i = 0; controllers != null && i < controllers.size();i++){MultiMethodController controller = (MultiMethodController)controllers.get(i);Properties urlPros = controller.getUrlMethodmappings(); Iterator itr = urlPros.keySet().iterator();for(;itr.hasNext();){String url = (String)itr.next();urlMap.put(url,controller);}}}} }


    ?

    總結

    以上是生活随笔為你收集整理的Spring架构设计-增强MultiActionController的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。