在使用Spring提供的控制器時,AbstractController和SimpleFormController是應用得最多的。AbstractController是最基本的Controller,可以給予用戶最大的靈活性。SimpleFormController則用于典型的表單編輯和提交。在一個需要增,刪,改,查的需求中,增加和修改擴展SimpleFormController完成,刪除和查詢則擴展AbstractController完成。
??? 但是像上面那樣完成某一業務對象的增,刪,改,查,都屬于一類相關的業務。把一類相關的操作分布到不同的類去完成,違返“高內聚”的設計原則。這樣四個業務操作需要四個類來完成,造成太多的類文件,難以維護和配置。
??? 所以Spring借鑒Struts的DispatchAction提供了類似功能的MultiActionController??梢詫崿F不同的請求路徑對應MultiActionController中的不同方法,這樣就可以把相關的操作都在一個類的相關方法中完成。這樣使得這個類具有“高內聚”,也利于系統的維護,還避免了重復代碼。增加和修改操作的數據驗證邏輯是很相似的,使用MultiActionController后就可以讓增加和修改操作共用一段數據驗證邏輯代碼。
??? 1. 使用MultiActionController
??? MultiActionController會使不同的請求映射為不同方法,這里是一個實現用戶信息增刪改查的例子:
??? 1.1 SampleMultiMethodController實現
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;
}
}
1.2 web-context配置
<!--
把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應該配置簡單明了,并且無需要在多個地方進行配置。 應該支持對綁定對象自定義名稱。
<
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接口
public
class
MultiMethodController extends MultiActionController implements
InitializingBean
{
private
Properties urlMethodmappings;
public
void
afterPropertiesSet() throws Exception
{
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
