已解决 - 请参阅答案。
我查看了许多类似的问题,并没有立即看到类似的情况。当然,这不是一个独特的情况,我只是错过了它?
更新 A Spring example I found shows a priority property这可能有所帮助,但我只找到了XML示例。问题扩展如下。
问题摘要
两个视图解析器在我的SpringWebMVC应用程序中似乎存在冲突。
问题详情
我使用Spring 4.0.3-RELEASE在Web应用程序上工作,并且最近添加了Jackson以支持将Json从调用返回到特定控制器。这是有效的,直到我为我的SpringWebConfig添加了一个@Override for configureViewResolvers。现在我给我的控制器调用Json只返回模板名称,该名称应调用Jackson映射器bean。
最大的问题
我怎样才能使这两者共存?我发现我可以打电话:
registry.order(int)
并将其设置为9只是为了确保它是最后一个,但它仍然拦截了来自控制器的jsonTemplate响应。我没有看到为MappingJackson2JsonView bean设置订单的方法。例如,@ Bean(order = 0)无效。
尝试的事情
按预期方式重写ViewResolverRegistry会在尝试获取映射的jsp视图时产生错误。
javax.servlet.ServletException: Could not resolve view with name 'someView' in servlet with name 'spring-mvc-dispatcher'
正如上面的问题陈述中所述,我已尝试在ViewResolverRegistry的注册表上设置订单,但这没有帮助。
我也尝试将以下内容添加到MappingJackson2JsonView实例中,查看:
Properties props = new Properties();
props.put("order", 1);
view.setAttributes(props);
但和以前一样,这并不能阻止ViewResolverRegistry拦截" jsonTemplate"杰克逊映射器可以处理之前。
我也更改了AppInitializer中配置的加载顺序,下面的代码已更新以反映新的加载顺序,但这也没有帮助。
通过阅读Spring文档,似乎添加ContentNegotiationConfigurer将是我需要解决的问题,而我目前正在研究如何以保留自动映射的方式使其工作模型返回到jsonTemplate视图。到目前为止,我已经看到过使用jsp作为具有特定属性的视图,这违背了使用Json Mapper的目的。
配置
我的com.mytest.config包中定义了多个配置类。
AppInitializer.java 处理将* config类添加到上下文中。 包com.mytest.config;
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");
}
}
JSONConfiguration.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();
}
}
实施
在我的Controller中,以下方法应该返回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";
}
如上所述,在Try Tried中,如果我从SpringWebConfig中删除ViewResolverRegistry bean并且如果我将bean保留在原位,则上述控制器方法将返回
404, /WEB-INF/views/html/jsonTemplate.jsp
The requested resource is not available.
- 我明白了。这是视图解析器应该做的事情。如何让我的JSON调用绕过这个?
答案 0 :(得分:0)
事实证明只有少数事情缺失。第一个是将以下注释添加到映射器的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文档。