Spring架构设计-增强MultiActionController
2010-11-15 16:28
281 查看
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;
}
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;
}
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;
}
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;
}
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{ // 用户信息列表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; } 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; } 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; } 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;} 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)。可以自定义command的名称。虽然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的构想,有三点需要实现。现在来讨论实现它们。
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");
}
}
public Properties getUrlMethodmappings() {
return urlMethodmappings;
}
public void setUrlMethodmappings(Properties urlMethodmappings) {
this.urlMethodmappings = urlMethodmappings;
}
}
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"); } } public Properties getUrlMethodmappings() { return urlMethodmappings; } 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方法就可以自
http://blog.sina.com.cn/s/blog_5cf5d2690100bce4.html
在使用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;
}
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;
}
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;
}
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;
}
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{ // 用户信息列表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; } 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; } 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; } 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;} 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)。可以自定义command的名称。虽然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的构想,有三点需要实现。现在来讨论实现它们。
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");
}
}
public Properties getUrlMethodmappings() {
return urlMethodmappings;
}
public void setUrlMethodmappings(Properties urlMethodmappings) {
this.urlMethodmappings = urlMethodmappings;
}
}
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"); } } public Properties getUrlMethodmappings() { return urlMethodmappings; } 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方法就可以自
http://blog.sina.com.cn/s/blog_5cf5d2690100bce4.html
相关文章推荐
- Spring架构设计-增强MultiActionController
- Spring架构设计-增强MultiActionController
- Spring架构设计-增强MultiActionController
- Spring架构增强MultiActionController
- Spring架构增强MultiActionController(二)
- Spring架构增强MultiActionController(上)
- Spring架构增强MultiActionController(下)
- Spring架构增强MultiActionController(1)
- Spring架构增强MultiActionController(2)
- Spring架构增强MultiActionController(3)
- Spring架构增强MultiActionController(一)
- Spring架构增强MultiActionController
- Spring架构增强MultiActionController(4)
- spring mvc MultiActionController !!!
- Spring的MultiActionController
- spring MultiActionController 简单配置
- springMVC3学习(五)--MultiActionController
- SpringMVC—MultiActionController控制器
- springmvc MultiActionController配置
- Spring MVC MultiActionController example