Spring MVC + JSON = 406不可接受
我试图生成一个简单的JSON响应工作。 现在我得到406不可接受的错误。 Tomcat说:“这个请求标识的资源只能根据请求的”接受“头文件生成不可接受的特征的响应。 即使我的Accept
头是
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
在Tomcat / lib中,我有所有的Tomcatjar子,Springjar子和jackson-all-1.9.0.jar。 我在Tomcat 7中使用Spring 3.2.2。
我知道这个问题已经讨论过很多次了,但是没有任何一个解决scheme为我工作。
web.xml中
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"> <display-name>Spring Web MVC Application</display-name> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class> org.springframework.web.servlet.DispatcherServlet </servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>*.htm</url-pattern> </servlet-mapping> </web-app>
调度员servlet.xml中
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd"> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver" > <property name="prefix"> <value>/WEB-INF/pages/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean> <context:component-scan base-package="com.smiechmateusz.controller" /> <context:annotation-config /> <mvc:annotation-driven /> </beans>
HelloWorldController.java
package com.smiechmateusz.controller; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; import com.smiechmateusz.dao.Foo; @Controller @RequestMapping("/") public class HelloWorldController extends AbstractController{ @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { ModelAndView model = new ModelAndView("HelloWorldPage"); return model; } @RequestMapping(value="foobar.htm", method = RequestMethod.GET) public @ResponseBody Foo getShopInJSON() { Foo f = new Foo(); f.setX(1); f.setY(2); f.setDescription("desc"); return f; } }
Foo.java
package com.smiechmateusz.dao; import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="foobaz") public class Foo implements Serializable { private int x, y; String description; int id; @Column(name = "x") public int getX() { return x; } public void setX(int x) { this.x = x; } @Column(name = "y") public int getY() { return y; } public void setY(int y) { this.y = y; } @Column(name = "description") public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } @Id @GeneratedValue @Column(name = "id") public int getId() { return id; } public void setId(int id) { this.id = id; } }
我已经尝试添加
<bean id="jsonConverter" class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"></bean> <bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"> <property name="messageConverters"> <list> <ref bean="jsonConverter"/> </list> </property> </bean>
到我的dispatcher-servlet.xml或更改jakcson-全部为jackson-asl和jackson-core-asl,但输出是相同的。
接受:text / html,application / xhtml + xml,application / xml; q = 0.9, / ; q = 0.8
这应该是问题。 JSON作为application/json
。 如果你相应地设置Accept头,你应该得到正确的回应。 (有浏览器插件,可以让你设置标题,我喜欢Firefox的“海报”最好)
如果您使用的是Maven和最新的Jackson代码,那么您可以从SpringconfigurationXML文件中删除所有Jackson特有的configuration(您仍然需要一个注释驱动标签<mvc:annotation-driven />),然后添加一些jackson依赖你的pom.xml文件。 请参阅下面的依赖关系的示例。 这工作对我来说,我正在使用:
- Apache Maven 3.0.4(r1232337; 2012-01-17 01:44:56-0700)
- org.springframework version 3.1.2.RELEASE
-
spring-security版本3.1.0.RELEASE。
...<dependencies> ... <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.2.3</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.2.3</version> </dependency> ... </dependencies>...
你可以得到这个错误的另一种方法是创build一个没有公共成员的类。 在这种情况下406不可接受是一个相当无用的错误消息。
在Spring 4中,只能添加@EnableWebMvc
,例如:
@Controller @EnableWebMvc @RequestMapping(value = "/articles/action", headers="Accept=*/*", produces="application/json") public class ArticlesController { }
没有其他的答案帮助我。
我读了几十个关于406不可接受,HttpMediaTypeNotAcceptableException,多部分文件,ResponseBody,设置接受标题,产生,消耗等的Stackoverflow答案
我们用SpringBoot和Jackson在build.gradle中configuration了Spring 4.2.4:
compile "com.fasterxml.jackson.core:jackson-core:2.6.7" compile "com.fasterxml.jackson.core:jackson-databind:2.6.7"
所有的路由在我们的其他控制器中工作正常,我们可以使用GET,POST,PUT和DELETE。 然后,我开始添加多部分file uploadfunction,并创build了一个新的控制器。 GETpath工作正常,但我们的POST和DELETE没有。 无论我如何从这里尝试不同的解决scheme,我只是不断得到406不能接受。
然后最后我偶然发现这个答案: spring抛出HttpMediaTypeNotAcceptableException:无法find可接受的表示forms,由于urlpath中的点
阅读Raniz的回答和所有评论。
这一切都归结于我们的@RequestMapping值:
@RequestMapping(value = "/audio/{fileName:.+}", method = RequestMethod.POST, consumes="multipart/*") public AudioFileDto insertAudio(@PathVariable String fileName, @RequestParam("audiofile") MultipartFile audiofile) { return audioService.insert(fileName, audiofile); } @RequestMapping(value = "/audio/{fileName:.+}", method = RequestMethod.DELETE) public Boolean deleteAudio(@PathVariable String fileName) { return audioService.remove(fileName); }
在我的情况下,@RequestMapping值中的{fileName:.+}
部分导致了406 Not Acceptable。
这里是我从Raniz的答案中添加的代码:
@Configuration public class ContentNegotiationConfig extends WebMvcConfigurerAdapter { @Override void configureContentNegotiation(final ContentNegotiationConfigurer configurer) { // Turn off suffix-based content negotiation configurer.favorPathExtension(false); } }
编辑2016年8月29日:
我们遇到了麻烦使用configurer.favorPathExtension(false)
:静态SVG图像停止加载。 经过分析,我们发现Spring开始发送SVG文件到内容types为“application / octet-stream”而不是“image / svg + xml”的UI。 我们通过发送fileName作为查询参数解决了这个问题,如:
@RequestMapping(value = "/audio", method = RequestMethod.DELETE) public Boolean deleteAudio(@RequestParam String fileName) { return audioService.remove(fileName); }
我们也删除了configurer.favorPathExtension(false)
。 另一种方法可能是在path中编码fileName,但我们select查询参数方法来避免进一步的副作用。
在你的pom中使用下面的依赖关系
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.5.3</version> </dependency>
您必须在spring-mvc-config.xml中注册Jackson的注释绑定,例如:
<!-- activates annotation driven binding --> <mvc:annotation-driven ignoreDefaultModelOnRedirect="true" validator="validator"> <mvc:message-converters> <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/> <bean class="org.springframework.http.converter.xml.Jaxb2RootElementHttpMessageConverter"/> <bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/> </mvc:message-converters> </mvc:annotation-driven>
然后在你的控制器中,你可以使用:
@RequestMapping(value = "/your_url", method = RequestMethod.GET, produces = "application/json") @ResponseBody
我想,问题是在RequestMapping( foobar.htm )中使用* .htm扩展。 尝试将其更改为footer.json或其他东西。
链接到正确的答案: https : //stackoverflow.com/a/21236862/537246
PS
默认情况下,Spring的方式是,开发人员知道Spring的整个API从A到Z,然后就是“406不能接受”,而Tomcat的日志是空的!
看到问题是与扩展。 根据扩展名,弹簧可以计算出内容types。 如果您的url以.com结尾,那么它将发送text / html作为内容types标题。 如果你想改变这个Spring的行为,请使用下面的代码:
@Configuration @Import(HibernateConfig.class) @EnableWebMvc // @EnableAsync() // @EnableAspectJAutoProxy @ComponentScan(basePackages = "com.azim.web.service.*", basePackageClasses = { WebSecurityConfig.class }, excludeFilters = { @ComponentScan.Filter(Configuration.class) }) public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureContentNegotiation(ContentNegotiationConfigurer configurer) { configurer.favorPathExtension(false).favorParameter(true).parameterName("mediaType").ignoreAcceptHeader(true).useJaf(false) .defaultContentType(MediaType.APPLICATION_JSON).mediaType("xml", MediaType.APPLICATION_XML).mediaType("json", MediaType.APPLICATION_JSON); } @Bean(name = "validator") public Validator validator() { return new LocalValidatorFactoryBean(); } }
在这里,我们将favorPathExtension设置为false,将Default Content-type设置为Application / json。 注意: HibernateConfig类包含所有的bean。
尝试添加
@RequestMapping(method = RequestMethod.GET,headers = {"Accept=text/xml, application/json"})
在getShopInJSON()
。
它为我工作。
也许POJO的所有领域都需要Getter和Setter。
我根据这个问题修好了。 参考: Spring MVC – HttpMediaTypeNotAcceptableException
而406是不是一个有用的信息来解决这个错误。 你应该debugging代码,看看exception是在地球上。
这是因为jsp的对象是不能接受的…用他的
添加这个依赖或任何其他发送转换jsonstring到jsp …
例如在pom中添加这个
<dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.6.2</version> </dependency>
并使用这样的代码:
@RequestMapping(value="foobar.htm", method = RequestMethod.GET) public @ResponseBody String getShopInJSON() { Foo f = new Foo(); f.setX(1); f.setY(2); f.setDescription("desc"); return new Gson().toJson(f); //converted object into json string }//return converted json string
今天我也经历了同样的问题。 在我的情况下,在web.xml
我有
<servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.html</url-pattern> </servlet-mapping>
我的url是.html
扩展名。 例如: .../getUsers.html
。 但是我在控制器中返回JSON数据。 .html扩展名默认将接受types设置为html。
所以我改成了以下内容:
web.xml中:
<servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.html</url-pattern> <url-pattern>*.json</url-pattern> </servlet-mapping>
url:
.../getUsers.json
现在一切正常。 希望它有帮助。
它看起来像你正试图产生/接收JSON输出。 我看到你的方法有两个问题。 1)您没有在Accept头中指定application / json 2)您需要在@RequestMapping中指定produce =“application / json”
还有另外一种情况是返回这个状态:如果jackson映射器无法弄清楚如何序列化你的bean。 例如,如果对同一个boolean属性isFoo()和getFoo()有两个访问方法。
删除getFoo()并把isFoo()。 它为我工作。
我不能在这里看到它作为答案,所以我想我会提到,我收到这个错误使用spring4.2时,我不小心删除了类的getter / setter我期待被返回为Json。
我的RequestMapping
值以.html结尾,应该是不同的。
我试图改变它.JSON和它为我工作。
我有类似的问题,并通过使用下面的代码解决
public class ProductList { private List<Product> productList = new ArrayList<Product>(); @JsonProperty("data") @JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT) public List<Product> getProductList() { return productList; } public void setProductList(List<Product> productList) { this.productList = productList; } I am setting ProductList object in ResponseEntity object and returning from controller.
我的类用JsonSerialize注释,并且include参数被设置为JsonSerialize.Inclusion.NON_DEFAULT
。 这导致了jackson确定每个bean属性的默认值。 我有一个返回int的bean属性。 在我的情况下,问题是bean getter调用了一个推断返回types的方法(即:一个通用的方法)。 由于一些奇怪的原因,这个代码编译; 它不应该编译,因为你不能使用int作为推断的返回types。 我把那个“int”改成了这个bean属性的一个“Integer”,我不再拥有一个406.奇怪的是,如果我将Integer改回到int,代码现在无法编译。