我们正在将一个struts应用程序迁移到Spring MVC并利用@Controller注释将页面定向到各种方法调用.
我在确定一个好的重用策略时遇到了麻烦.
我们在许多页面中基本上都做同样的事情:
prepareView(..., ...); //Various params -- could likely be standardized
if (!allowedToView()) {
mav.setViewName(injectedErrorPage);
}
performBusinessLogic(..., ...); //Various params -- not seeing how to standardize
persistEntities();
finalizeView(..., ...); // Various params -- could likely be standardized
Run Code Online (Sandbox Code Playgroud)
有哪些策略用于创建最终方法,允许开发人员"忘记"这些流程?我考虑过制作一个抽象类,但由于每种方法的不同,我真的没有办法"标准化".
例如,我们有以下内容:
@RequestMapping("params="assign", method=RequestMethod.Post)
public ModelAndView assign(@SessionAttribute(value="sessionAttr") Pojo pojo,
@ModelAttribute("command") CommandPojo commandPojo,
BindingResult result) {
//Follows pattern above
}
@RequestMapping()
public ModelAndView filterResults(@SessionAttribute(value="sessionAttr") Pojo pojo,
@RequestAttribute("requestAttr") String requestAttr,
@ModelAttribute("command") CommandPojo2 commandPojo2,
BindingResult result) {
//Follows pattern above
}
Run Code Online (Sandbox Code Playgroud)
拥有最终方法需要将其分解为两个POJO(然后将调用描述性函数).我直接关注的是如何处理最终方法中的不同参数?我认为没有办法处理这种情况.
如果我们仍然可以使用受保护函数的"最终"方法,我们可以在需要时覆盖它.
我和你有同样的问题.我还没有一个干净的解决方案,但我相信我取得了一些进展,所以我想我会分享到目前为止我找到的内容.
我探讨了three_cups_of_java建议的拦截器的使用,但我遇到了各种问题(如下所述).目前我正在尝试使用自定义AnnotationMethodHandlerAdapter,但我还没有完成这项工作.
拦截器
由于拦截器无法访问它们拦截的控制器对象(更正:它们可以访问它,但对执行流程的控制有限),控制器和拦截器必须通过会话中的对象进行通信.
这是我的意思的一个简化示例:
在我们的旧架构中,我们有自己的基本控制器,每个人都可以扩展.它本身扩展了MultiActionController,并添加了一些自定义行为 - 比如在您的示例中,在调用处理程序方法之前更新发布请求之后的服务器端视图.这是有效的,因为所有控制器都提供模板方法的实现(例如getViewKeyInSession()).
因此,基本控制器中的自定义代码看起来大致如下:
// inside handleRequestInternal method
if (request.getMethod().equals("POST") {
updateViewAfterPost (session.get(getViewKeyInSession());
}
return super.handleRequestInternal();
Run Code Online (Sandbox Code Playgroud)
现在,当我们将此代码移动到拦截器时,我们遇到了几个问题:
updateModelAfterPost.这通常不是必需的,但不幸的是,有些控制器是必要的.使用Custom AnnotationMethodHandlerAdapter
目前我正在寻找DefaultAnnotationHandlerMapping直接在我的xml(而不是mvc:annotation-driven)中指定,然后为其提供自定义AnnotationMethodHandlerAdapter.
正如我先前所说,我没有取得足够的进展来呈现完整的结果,但我的目标是:
我认为AnnotationMethodHandlerAdapter是一个Spring提供的MultiActionController,但是对于pojo控制器.例如,我已经知道如何插入我自己的方法解析器(请参阅此问题)和其他Spring好东西.
此适配器有几种方法可以覆盖,例如
invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler),
也可以
handle(HttpServletRequest request, HttpServletResponse response, Object handler)
.
在自定义代码中,您可以检查处理程序类,然后相应地执行操作.要继续前面的示例,如果处理程序类有一个方法updateViewAfterPost或者它实现了某个接口,那么你可以调用该方法,然后调用super让spring继续进行常规调用.因此,代码看起来大致如下:
public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// inspect handler object, look for marker interface, methods and/or annotations
// perform pre-processing on the handler object
// e.g. handler.updateViewAfterPost(request, response)
ModelAndView mav = super.handle (request, response, handler);
// post-processing on the handler object
return mav;
}
Run Code Online (Sandbox Code Playgroud)
(当然,这只是一个玩具示例.在实际代码中,您需要更好的异常处理)
更新:
我用自定义尝试了上述策略,AnnotationMethodHandlerAdapter确实有效.我在我的pojo控制器上使用了一个标记接口,并且只引入了一个命名updateModelAfterPost为生命周期的新方法,并且它按预期工作.
我遇到了几个小警告,主要是因为我在同一个mvc环境中将旧方法与新方法结合起来.下面你可以看到我对xml上下文所做的更改,然后是我认为值得强调的问题列表.
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="2" />
</bean>
<bean class="com.sample.MyAnnotationMethodHandlerAdapter">
<property name="order" value="2" />
</bean>
<bean class="com.sample.MySimpleControllerHandlerAdapter" >
<property name="order" value="1" />
</bean>
<bean class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="order" value="1" />
<property name="mappings">
<props>
...
</props>
</property>
</bean>
Run Code Online (Sandbox Code Playgroud)
AnnotationMethodHandlerAdapter不能很好地处理,因此我设置了元素的顺序,使得遗留处理程序映射和处理程序适配器首先起作用,而基于注释的处理程序映射和处理程序适配器起作用.SimpleControllerHandlerAdapter,但我还必须使用自己的类扩展它,因为它没有实现Ordered接口.最后,这是相关类的代码:
package com.sample;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter;
public class MyAnnotationMethodHandlerAdapter extends AnnotationMethodHandlerAdapter {
protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof MyMarkerInterface) {
MyMarkerInterface handler2 = (MyMarkerInterface) handler;
handler2.updateModelAfterPost(request);
}
return super.invokeHandlerMethod(request, response, handler);
}
}
package com.sample;
import org.springframework.core.Ordered;
import org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter;
public class MySimpleControllerHandlerAdapter extends SimpleControllerHandlerAdapter implements Ordered {
private int order = 0;
public int getOrder() {
return order;
}
public void setOrder(int order) {
this.order = order;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4848 次 |
| 最近记录: |