我通过向其添加一些功能来扩展RequestMappingHandlerMapping类
当我添加如下配置时:
@Configuration
public class MyConfig extends DelegatingWebMvcConfiguration {
@Override
@Bean
@Primary
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
return super.requestMappingHandlerMapping();
}
@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
//Here I create my new version RequestMappingHandlerMapping
return new MyNewVersionRequestMappingHandlerMapping();
}
}
public class MyNewVersionRequestMappingHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected RequestCondition<?> getCustomTypeCondition(final Class<?> handlerType) {
// instead of null return my new Condition
return new SomeCustomTypeCondition(handlerType);
}
@Override
protected RequestCondition<?> getCustomMethodCondition(final Method method) {
// instead of null return my new Condition
return new SomeCustomTypeCondition(handlerType);
}
}
然后启动应用程序,它显示:
The bean 'requestMappingHandlerMapping', defined in class path resource [com/test/MyConfig.class],
could not be registered. A bean with that name has already been defined in class path resource
[org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]
and overriding is disabled.
WebMvcAutoConfiguration.EnableWebMvcConfiguration具有@Configuration批注,并从DelegatingWebMvcConfiguration扩展而来:
public class WebMvcAutoConfiguration {
...
@Configuration
public static class EnableWebMvcConfiguration extends DelegatingWebMvcConfiguration implements ResourceLoaderAware {
...
@Bean
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping() {
// I want return my version of RequestMappingHandlerMapping, but how?
return super.requestMappingHandlerMapping();
}
...
spring-boot-autoconfigure-2.1.9.RELEASE.jar中的使用链为:
-> META-INF\spring.factories
-> WebMvcAutoConfiguration
-> EnableWebMvcConfiguration
-> DelegatingWebMvcConfiguration.
因此,当使用Spring Boot自动配置时,它被编码为使用DelegatingWebMvcConfiguration
,我可以用我自己的版本替换这个默认值吗?
有时候我可以将选项添加到application.yml
main:
allow-bean-definition-overriding: true
有效。但我想避免这样做,因为此选项将隐藏Bean复制警告。
问题是:如何在不添加此类选项的情况下进行修复?
答案 0 :(得分:1)
我可以使其与以下代码一起使用。希望问题能为您解决。
package com.jjs.in.config;
@Configuration
public class WebConfigMapping extends DelegatingWebMvcConfiguration{
// @Configuration
// public static class UnconditionalWebMvcAutoConfiguration implements WebMvcConfigurer { // extends WebMvcAutoConfiguration {//forces @EnableWebMvc
// }
@Override
protected RequestMappingHandlerMapping createRequestMappingHandlerMapping() {
return new MyWebConfig.InternalPathRequestMappingHandlerMapping();
}
@Bean//("CASPER_REQUESTING_MAPPING")
@Primary
@Override
public RequestMappingHandlerMapping requestMappingHandlerMapping(
@Qualifier("mvcContentNegotiationManager") ContentNegotiationManager contentNegotiationManager,
@Qualifier("mvcConversionService") FormattingConversionService conversionService,
@Qualifier("mvcResourceUrlProvider") ResourceUrlProvider resourceUrlProvider) {
return super.requestMappingHandlerMapping(contentNegotiationManager, conversionService,resourceUrlProvider);
}
}
@Slf4j
@Configuration
public class MyWebConfig {
public static class InternalPathRequestMappingHandlerMapping 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<>();
for (Class<?> clazz = handlerType; clazz != Object.class; clazz = clazz.getSuperclass()) {
if (clazz.isAnnotationPresent(InternalRequest.class))
superclassUrlPatterns.add((String)methodMapping.getPatternsCondition().getPatterns().toArray()[0]);
}
if (method.isAnnotationPresent(InternalRequest.class) && superclassUrlPatterns.isEmpty()){
superclassUrlPatterns.add((String)methodMapping.getPatternsCondition().getPatterns().toArray()[0]);
}
if (!superclassUrlPatterns.isEmpty()) {
String newUrl = "MY_PREFIX"+ superclassUrlPatterns.get(0);
RequestMappingInfo superclassRequestMappingInfo = new RequestMappingInfo(methodMapping.getName(),
new PatternsRequestCondition(newUrl), methodMapping.getMethodsCondition()
, methodMapping.getParamsCondition()
, methodMapping.getHeadersCondition()
, methodMapping.getConsumesCondition()
, methodMapping.getProducesCondition()
, methodMapping.getCustomCondition());
return superclassRequestMappingInfo;
} else {
return methodMapping;
}
}
}
}