Spring addFormatters 未调用 WebMvcConfigurerAdapter

问题描述 投票:0回答:5

我正在尝试在

Spring
启动应用程序中实现转换器,但由于某种原因,我对
addFormatters(FormatterRegistry formatterRegistry)
的覆盖从未被调用。令人困惑的是,调用了其他重写的方法,
addInterceptors
工作得很好。此应用程序已启用安全性。

@EnableWebMvc
@Configuration
@ComponentScan(basePackages = {"com.company.web"})
public class WebMvcConfig extends WebMvcConfigurerAdapter {

  private final Logger logger = LoggerFactory.getLogger(this.getClass());

  @Autowired
  private RequestMappingHandlerAdapter requestMappingHandlerAdapter;

  @Inject
  private TenantIdentifierInterceptorAdapter multiTenancyInterceptor;

  @Override
  public void addInterceptors(InterceptorRegistry registry) {
    logger.info("adding interceptor");
    registry.addInterceptor(multiTenancyInterceptor);
  }

  //THIS IS NOT CALLED
  @Override
  public void addFormatters(FormatterRegistry formatterRegistry) {
    logger.info("adding converters"); 
    formatterRegistry.addConverter(new StringToPersonConverter());
  }

  private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {"classpath:/META-INF/resources/",
      "classpath:/resources/", "classpath:/static/", "classpath:/public/"};

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/**").addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS)
        .setCachePeriod(3600).resourceChain(true).addResolver(new PathResourceResolver());
  }

  @PostConstruct
  public void init() {
    requestMappingHandlerAdapter.setIgnoreDefaultModelOnRedirect(true);
  }

}

出于某种原因,如果我将此代码添加到文件中,则会命中格式化程序代码,但我收到错误“需要 ServletContext 来配置默认 servlet 处理”,并且应用程序将无法编译。

@Bean
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new       ResourceBundleMessageSource();
messageSource.setBasename("messages");
return messageSource;
}
java spring spring-mvc spring-boot converters
5个回答
1
投票

您是否使用超类 WebMvcConfigurationSupport 配置了 bean?
如果您这样做,它将禁用 WebMvcAutoConfiguration Bootstrap。
检查此代码:

@Configuration
@ConditionalOnWebApplication(
    type = Type.SERVLET
)
@ConditionalOnClass({Servlet.class, DispatcherServlet.class, WebMvcConfigurer.class})
@ConditionalOnMissingBean({WebMvcConfigurationSupport.class})
@AutoConfigureOrder(-2147483638)
@AutoConfigureAfter({DispatcherServletAutoConfiguration.class, ValidationAutoConfiguration.class})
public class WebMvcAutoConfiguration {

0
投票

我不是 100% 确定,但您是否尝试从类中删除

@EnableWebMvc
注释?因为根据文档它不应该在那里:

如果您想保留 Spring Boot MVC 功能,并且只想添加额外的 MVC 配置(拦截器、格式化程序、视图控制器等),您可以添加自己的 WebMvcConfigurerAdapter 类型的 @Configuration 类,但不使用 @EnableWebMvc。


0
投票

M。 Deinum 的评论就是答案。我删除了

@EnableWebMvc
并删除了方法
addFormatters
,然后添加了:

@Bean
StringToPersonConverter stringToPersonConverter() {
  return new StringToPersonConverter();
}

0
投票

我遇到了同样的问题(

addFormatters()
没有被调用),最终通过自动装配
FormatterRegistry
并从
ApplicationContextAware.setApplicationContext()
添加我的转换器来解决它。

Spring Boot 2.7.0

public class WebConfig implements WebMvcConfigurer, ApplicationContextAware 
{
    @Autowired
    FormatterRegistry registry;
    @Override
    public void setApplicationContext(ApplicationContext ctx) {
        registry.addConverter(new CardTypeConverter());
    }
}

-1
投票

我已经解决了类似的错误

启用WebMvc

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(DelegatingWebMvcConfiguration.class)
public @interface EnableWebMvc {
}

委托WebMvc配置

@Configuration
public class DelegatingWebMvcConfiguration extends WebMvcConfigurationSupport {
    private final WebMvcConfigurerComposite configurers = new WebMvcConfigurerComposite();

    @Autowired(required = false)
    public void setConfigurers(List<WebMvcConfigurer> configurers) {
        if (!CollectionUtils.isEmpty(configurers)) {
            this.configurers.addWebMvcConfigurers(configurers);
        }
    }

    //...

    @Override
    protected void addFormatters(FormatterRegistry registry) {
        this.configurers.addFormatters(registry);
    }

    //...

}

WebMvc配置支持

public class WebMvcConfigurationSupport implements ApplicationContextAware, ServletContextAware {

    //...

    @Bean
    public FormattingConversionService mvcConversionService() {
        FormattingConversionService conversionService = new DefaultFormattingConversionService();
        addFormatters(conversionService);
        return conversionService;
    }

    /**
     * Override this method to add custom {@link Converter}s and {@link Formatter}s.
     */
    protected void addFormatters(FormatterRegistry registry) {
    }

    //...

}

我的自定义配置具有多个 WebMvcConfigurerAdapter 实现 WebMvcConfigurer

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter
{
    @Autowired
    private ConversionService conversionService;

    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers)
    {
        argumentResolvers.add(new RequestTenantResolverComposite(conversionService));
    }
}

如果 FormattingConversionService 实现了在注入 WebMvcConfigurer 之前创建的 ConversionService bean,则不会调用该方法。

我使用 spring 版本 4.3.6 的 ConversionService 的 Lazy 注释解决了我的问题。

© www.soinside.com 2019 - 2024. All rights reserved.