[英]Spring MVC @RequestMapping Inheritance
来自Struts2我习惯在超类(或者package-info.java
)上声明@Namespace
注释,继承类随后将获取其祖先的@Namespace
注释中的值,并将其添加到请求路径中行动。 我现在尝试使用@RequestMapping
注释在Spring MVC中执行类似的操作,如下所示(为简洁起见,代码已修剪):
package au.test
@RequestMapping(value = "/")
public abstract class AbstractController {
...
}
au.test.user
@RequestMapping(value = "/user")
public abstract class AbstractUserController extends AbstractController {
@RequestMapping(value = "/dashboard")
public String dashboard() {
....
}
}
au.test.user.twitter
@RequestMapping(value = "/twitter")
public abstract class AbstractTwitterController extends AbstractUserController {
...
}
public abstract class TwitterController extends AbstractTwitterController {
@RequestMapping(value = "/updateStatus")
public String updateStatus() {
....
}
}
/
按预期工作 /user/dashboard
按预期工作 /user/twitter/updateStatus
工作时它没有并检查日志我可以看到一个类似于的日志条目: org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping - 映射的URL路径[/ tweeter / updateStatus]到处理程序'twitterController'上
是否有一个我可以启用的设置,它将扫描超类的@RequestMapping
注释并构造正确的路径?
另外我认为在package-info.java
中定义@RequestMapping
包是非法的吗?
以下基本上成为/tweeter/updateStatus
而不是/user/tweeter/updateStatus
public abstract class TwitterController extends AbstractTwitterController {
@RequestMapping(value = "/updateStatus")
public String updateStatus() {
....
}
}
这是预期的行为,因为您已经覆盖了您在AbstractController
和AbstractUserController
声明的原始@RequestMapping
。
实际上,当您声明AbstractUserController
时,它还会覆盖AbstractController
的@RequestMapping
。 它只是给你一个幻觉,即来自AbstractController
的/已被继承。
“我是否可以启用一个设置来扫描超类以获取@RequestMapping
注释并构建正确的路径?” 从来没听说过。
根据在启动时修改@RequestMappings中解释的技术,是的,可以以您想要的方式从超类构造URL模式。
实质上,您必须继承RequestMappingHandlerMapping (很可能,它将是您的HandlerMapping实现,但请先检查)并覆盖受保护的getMappingForMethod
方法。 一旦这变得可行,您就可以完全控制URL模式生成。
从您给出的示例中可以看出确切的合并策略并不完全清楚,例如,如果超类AbstractTwitterController
还使用自己的@RequestMapping
实现updateStatus()
方法,您希望获得什么路径,或者您希望如何连接URL模式层次结构,自上而下或自下而上,(我假设前者在下面),但是,希望以下代码片段能给你一些想法:
private static class PathTweakingRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestMappingInfo getMappingForMethod(Method method, Class<?> handlerType) {
RequestMappingInfo methodMapping = super.getMappingForMethod(method, handlerType);
if (methodMapping == null)
return null;
List<String> superclassUrlPatterns = new ArrayList<String>();
boolean springPath = false;
for (Class<?> clazz = handlerType; clazz != Object.class; clazz = clazz.getSuperclass())
if (clazz.isAnnotationPresent(RequestMapping.class))
if (springPath)
superclassUrlPatterns.add(clazz.getAnnotation(RequestMapping.class).value()[0]);// TODO handle other elements in the array if necessary
else
springPath = true;
if (!superclassUrlPatterns.isEmpty()) {
RequestMappingInfo superclassRequestMappingInfo = new RequestMappingInfo("",
new PatternsRequestCondition(String.join("", superclassUrlPatterns)), null, null, null, null, null, null);// TODO implement specific method, consumes, produces, etc depending on your merging policies
return superclassRequestMappingInfo.combine(methodMapping);
} else
return methodMapping;
}
}
另一个好问题是如何拦截RequestMappingHandlerMapping
的实例化。 在因特网中,存在许多用于各种配置策略的各种示例。 但是,使用JavaConfig,请记住,如果在@Configuration
集中提供WebMvcConfigurationSupport
,那么@EnableWebMvc
(显式或隐式)将停止工作。 我最终得到了以下内容:
@Configuration
public class WebConfig extends DelegatingWebMvcConfiguration{
@Configuration
public static class UnconditionalWebMvcAutoConfiguration extends WebMvcAutoConfiguration {//forces @EnableWebMvc
}
@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
return new PathTweakingRequestMappingHandlerMapping();
}
@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return super.requestMappingHandlerMapping();
}
}
但是想了解更好的方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.