代码之家  ›  专栏  ›  技术社区  ›  J E Carter II

将ViewResolverRegistry添加到SpringWebConfig后,MappingJackson2JsonView Bean中断

  •  0
  • J E Carter II  · 技术社区  · 6 年前

    已解决 -请参阅答案。

    我已经研究了许多类似的问题,没有立即看到类似的案例。当然,这不是一个独特的情况,我只是错过了它?

    使现代化 A Spring example I found shows a priority property 这在这里可能会有所帮助,但我只找到了XML示例。问题展开如下。

    问题摘要

    在我的SpringWebMVC应用程序中,两个视图解析器似乎存在冲突。

    问题详细信息

    我正在开发一个使用Spring 4.0.3-RELEASE的web应用程序,最近添加了Jackson以支持从调用返回Json到特定控制器。在我为configureViewResolvers的SpringWebConfig添加了一个@覆盖之前,这一直有效。现在,我对提供Json的控制器的调用只返回应该调用Jackson映射器bean的模板名称。

    最大的问题

    我怎样才能使这两者共存?我发现我可以打电话:

    registry.order(int)
    

    并将其设置为9以确保它是最后一个,但它仍然截获了来自控制器的jsonTemplate响应。我看不到为MappingJackson2JsonView bean设置顺序的方法@例如,Bean(order=0)无效。

    尝试过的事情

    在尝试获取映射的jsp视图时,按预期编辑ViewResolverRegistry会产生错误。

    javax.servlet.ServletException: Could not resolve view with name 'someView' in servlet with name 'spring-mvc-dispatcher'
    

    正如上面的问题陈述所指出的,我已经尝试在注册表上为ViewResolverRegistry设置顺序,但这没有帮助。

    我还尝试将以下内容添加到MappingJackson2JsonView实例view中:

    Properties props = new Properties();
    props.put("order", 1);
    view.setAttributes(props);
    

    但与之前一样,这并不能阻止ViewResolverRegistry在Jackson映射器处理“jsonTemplate”之前拦截它。

    我还更改了AppInitializer中配置的加载顺序,下面的代码已经更新以反映新的加载顺序,但这也没有帮助。

    再仔细阅读一下Spring文档,我似乎需要添加一个ContentNegotiationConfigurer来解决这个问题,目前我正在研究如何以一种保留模型返回到jsonTemplate视图的自动映射的方式来实现这一点。到目前为止,我看到的Exapmles使用jsp作为具有特定属性的视图,这违背了使用Json映射器的目的。

    配置

    我在包com中定义了多个配置类。我的测试。配置。

    AppInitializer。JAVA 处理将*配置类添加到上下文的操作。 程序包com。我的测试。配置;

    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRegistration;
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.web.WebApplicationInitializer;
    import org.springframework.web.context.ContextLoaderListener;
    import org.springframework.web.context.request.RequestContextListener;
    import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
    import org.springframework.web.servlet.DispatcherServlet;
    
    public class AppInitializer implements WebApplicationInitializer {
    
    private Logger logger = LoggerFactory.getLogger(AppInitializer.class);
    
    @Override
    public void onStartup(ServletContext container) throws ServletException {
    
        try {
    AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
            ctx.register(JSONConfiguration.class);
            ctx.register(SpringWebConfig.class);
    
    
            ctx.setServletContext(container);
            container.addListener(new ContextLoaderListener(ctx));
            container.addListener(new RequestContextListener());
    
            logger.info("Created AnnotationConfigWebApplicationContext");
    
            ServletRegistration.Dynamic dispatcher = container.addServlet("spring-mvc-dispatcher", new DispatcherServlet(ctx));
            dispatcher.setLoadOnStartup(1);
            dispatcher.addMapping("/");
    
            logger.info("DispatcherServlet added to AnnotationConfigWebApplicationContext");
    
    } catch (Exception e) {
                logger.error(e.getLocalizedMessage(), e);
            }
    
        }
    
    }
    

    SpringWebConfig。JAVA 是我注册大多数bean的地方。

    package com.mytest.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.PropertySource;
    import org.springframework.core.env.Environment;
    
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages={"com.mytest.controller","com.mytest.bean","com.mytest.model"})
    
    @PropertySource(value={"classpath:application.properties"})
    public class SpringWebConfig extends WebMvcConfigurerAdapter {
    
    @Autowired
    private Environment env;
    
    private Logger logger = LoggerFactory.getLogger(SpringWebConfig.class);
    
        // bunches of beans such as JdbcTemplate, DataSource... omitted for simplicity
    
    
        @Override // apparent problem location -- needed for jsp resolving
        public void configureViewResolvers(final ViewResolverRegistry registry) {       
            registry.jsp("/WEB-INF/views/html/",".jsp");
        }
    
    
        @Override 
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            configurer.enable();
            logger.info("DefaultServletHandlerConfigurer enabled");
        }
    
        @Override
        public void addInterceptors(InterceptorRegistry registry){      
            registry.addInterceptor(new com.honda.hrao.rid.config.RequestInterceptor());
            logger.info("RequestInterceptor added to InterceptorRegistry");
        }
    }
    

    JSON配置。JAVA 是我为JSON设置的控制器。

    package com.mytest.config;
    
    import java.util.Properties;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    
    import org.springframework.web.servlet.View;
    import org.springframework.web.servlet.ViewResolver;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.view.BeanNameViewResolver;
    import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
    
    @Configuration
    @ComponentScan(basePackages = {"com.mytest.controller"})
    @EnableWebMvc
    
    public class JSONConfiguration {
    
        private Logger logger = LoggerFactory.getLogger(JSONConfiguration.class);
    
          @Bean  // needed for JSON conversion of bean responses
            public View jsonTemplate() {
              logger.info("Registered MappingJackson2JsonView");
                MappingJackson2JsonView view = new MappingJackson2JsonView();
                Properties props = new Properties();
                props.put("order", 1);
                view.setAttributes(props);
                view.setPrettyPrint(true);
                return view;
            }
    
            @Bean
            public ViewResolver viewResolver() {
                logger.info("Starting ViewResolver bean");
                return new BeanNameViewResolver();
            }
    
    }
    

    实施

    在我的控制器中,以下方法应返回JSON。

    @Autowired
    AppConstants appConstants;
    
    @RequestMapping(method = RequestMethod.GET, value = "getAppConstants")
        public String getAppConstants(Model model) {
            model.addAttribute("AppConstants",appConstants);
            if(appConstants==null) {
                Logger.error("appConstants not autowired!!!");
                return null;
            }
            return "jsonTemplate";
        }
    

    正如前面在Things Treaded中所提到的,如果我从SpringWebConfig中删除ViewResolverRegistry bean,并且如果我将该bean保留在原位,则上述控制器方法将返回

    404, /WEB-INF/views/html/jsonTemplate.jsp 
    The requested resource is not available.
    

    --我理解。这就是视图解析器应该做的。如何使JSON调用绕过此问题?

    1 回复  |  直到 6 年前
        1
  •  0
  •   J E Carter II    6 年前

    结果发现只少了几样东西。第一个是为映射器的bean声明添加以下注释:

    @Primary
    

    现在,bean设置如下所示。

      @Bean  // needed for JSON conversion of bean responses
      @Primary
        public View jsonTemplate() {
          logger.info("Registered MappingJackson2JsonView");
            MappingJackson2JsonView view = new MappingJackson2JsonView();
            Properties props = new Properties();
            props.put("order", 1);
            view.setAttributes(props);
            view.setPrettyPrint(true);          
            return view;
        }
    

    第二种是使用ContentNegotiationConfigurer。在我的SpringWebConfig中,我添加了以下内容:

    public void configurationContentNegotiation(ContentNegotiationConfigurer configurer) {
            configurer
                .ignoreUnknownPathExtensions(false)
            .defaultContentType(MediaType.TEXT_HTML);
        }
    

    并将我的configureViewResolvers函数更改如下:

    @Override // needed for jsp resolving
        public void configureViewResolvers(final ViewResolverRegistry registry) {    
            MappingJackson2JsonView view = new MappingJackson2JsonView();
            view.setPrettyPrint(true);      
            registry.enableContentNegotiation(view);        
            registry.jsp("/WEB-INF/views/html/",".jsp");
        }
    

    发现一条线索 this example .其余部分来自Spring文档。