2013-05-02 103 views
48

我试图生成一个简单的JSON响应工作。现在我得到406不可接受的错误。 Tomcat说:“这个请求标识的资源只能根据请求”接受“头文件生成不可接受的特征的响应。”即使我Accept头是Spring MVC + JSON = 406不可接受

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 

到Tomcat/lib中我都Tomcat的罐子,罐子春季和Jackson-ALL-1.9.0.jar。我在Tomcat 7上使用Spring 3.2.2。

我知道这个问题已经讨论过很多次,但没有一个解决方案适用于我。

的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> 

调度-servlet.xml中或改变jakcson,所有杰克逊ASLjackson-core-asl但输出是一样的。

+1

这可以帮助:http://stackoverflow.com/questions/2828968/mapping-restful-ajax-requests-to-spring? – NINCOMPOOP 2013-05-02 10:27:36

+0

做了什么之后,我不再得到406错误,但我也没有得到JSON响应。事实上,我没有得到任何回应。服务器返回200状态的空文档。 – Mateusz 2013-05-02 11:30:10

回答

16

接受:text/html的,应用/ XHTML + xml的,应用/ XML; Q = 0.9,/; Q = 0.8

这应该是问题。 JSON的服务为application/json。如果你相应地设置了Accept头,你应该得到正确的回应。 (有浏览器插件,让你设置头,我喜欢“海报”为Firefox最好)

+2

它不会改变任何东西,我仍然得到406错误。 – Mateusz 2013-05-02 12:35:13

+8

@Mateusz你还必须像alain.janinm写的那样正确设置spring mvc。最简单的方法是通过''或'@ EnableWebMvc'。看到[这是我以前的答案](http://stackoverflow.com/questions/5908466/jquery-spring-mvc-requestbody-and-json-making-it-work-together/5908632#5908632)为一个完整的工作示例 – 2013-05-02 14:45:32

+1

非常感谢你,你的先前发帖我终于设法让它工作。 – Mateusz 2013-05-02 15:58:58

4

您必须先注册注释在Spring-MVC-config.xml中为杰克逊的结合,例如:

<!-- 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 
37

如果您正在使用Maven和最新Jackson code那么你可以从你的Spring配置XML文件中删除所有的具体杰克逊配置(您仍然需要注释驱动标签< 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 version 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>... 
    
+0

嗨我仍然面临一些不同的对象 – Dharmesh 2015-03-24 07:30:10

+0

@Dharmesh - 我需要更多的信息,而不是你在评论中给我的信息来帮助你。也许你可以提出一个完整的细节问题,然后在你的下一个评论中指出我的问题。祝你好运! – KSev 2015-03-24 16:20:50

+2

我解决了这个问题。在我的情况下,它的一个小错误,我没有为我的Object类中的1字段提供getter和setter,因为当它尝试使用@ResponseBody注释转换JSON响应正文中的对象时,它给了我406错误。 – Dharmesh 2015-03-25 06:31:11

18

另一种方式是创建一个类,没有公共成员。在这种情况下,不可接受的是一个相当无用的错误消息。

+0

这正是我所面临的。非常混乱的错误信息。 – 2016-01-28 03:20:44

+0

Hooray无用的错误响应消息。这有很大帮助。 – 2016-02-02 15:31:04

+0

是的,这是我的情况下的问题,公开设置吸气剂属性 – anshulkatta 2016-05-30 10:09:17

4

我想,这个问题是在的* .htm扩展在RequestMapping(foobar.htm)使用。尝试将其更改为footer.json或其他内容。

链接到正确答案:https://stackoverflow.com/a/21236862/537246

附:

Spring的方式默认情况下,开发人员知道Spring的整个API从A到Z.然后只是“406不可接受”,没有任何细节,Tomcat的日志是空的!

0

它看起来像你试图产生/接收JSON输出。 我发现你的方法有两个问题。 1)您没有在您的Accept标头中指定应用程序/ json 2)您需要在@RequestMapping中指定produce =“application/json”

0

还有另一种情况,将返回此状态:if杰克逊映射器无法弄清楚如何序列化你的bean。例如,如果对于相同的布尔属性isFoo()getFoo()有两个访问器方法。

删除getFoo()并把isFoo()。它为我工作。

+0

是的。这个为我工作。 @RequestMapping(method = RequestMethod.GET,headers = {“Accept = text/xml,application/json”}) – sats 2016-03-28 19:38:19

1

尝试getShopInJSON()添加

@RequestMapping(method = RequestMethod.GET,headers = {"Accept=text/xml, application/json"}) 

它为我工作。

8

使用Spring 4只添加@EnableWebMvc,例如:

@Controller 
@EnableWebMvc 
@RequestMapping(value = "/articles/action", headers="Accept=*/*", produces="application/json") 
public class ArticlesController { 

} 
0

我无法看到了在这里的答案,所以我想我会提到,我收到使用弹簧4.2这个错误时,我不小心删除I类的getter/setter期待以Json的身份返回。

+1

是的。这个为我工作。谢谢Shubham @RequestMapping(method = RequestMethod.GET,headers = {“Accept = text/xml,application/json”}) – sats 2016-03-28 19:39:39

6

使用下面的依赖在你的POM

<dependency> 
    <groupId>com.fasterxml.jackson.core</groupId> 
    <artifactId>jackson-databind</artifactId> 
    <version>2.5.3</version> 
</dependency> 
1

也许你的POJO的各个领域需要getter和setter。

我根据这个问题修复了它。 参考:Spring MVC - HttpMediaTypeNotAcceptableException

而406不是一个有用的消息来解决该错误。您应该调试代码并查看异常情况。

2

看到问题是与扩展名。根据扩展名的不同,Spring可能会计算出内容类型。如果您的网址以.com结尾,那么它会发送文本/ html作为内容类型标题。如果你想改变弹簧的这种行为,请使用下面的代码:

@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,缺省内容类型为application/JSON。 注意: HibernateConfig类包含所有的bean。

7

没有其他答案帮助我。

我看了几十#1的回答了关于406不能接受的,HttpMediaTypeNotAcceptableException,多文件,ResponseBody,设置接受头,生产,消耗等

我们有春天4.2.4 SpringBoot和杰克逊的build.gradle配置:

compile "com.fasterxml.jackson.core:jackson-core:2.6.7" 
compile "com.fasterxml.jackson.core:jackson-databind:2.6.7" 

所有航线我们其他控制器工作得很好,我们可以使用GET,POST,PUT和DELETE。然后我开始添加多部分文件上传功能并创建一个新的控制器。 GET路径工作正常,但我们的POST和DELETE没有。无论我如何从这里尝试不同的解决方案,我只是不断接受406不可接受。

于是最后我碰到这个偶然SO回答: Spring throwing HttpMediaTypeNotAcceptableException: Could not find acceptable representation due to dot in url path

阅读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对我们来说是不可接受的。

这是我从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开始使用content-type“application/octet-stream”而不是“image/svg + xml”将SVG文件发送回UI。我们通过发送fileName作为查询参数来解决此问题,如:

@RequestMapping(value = "/audio", method = RequestMethod.DELETE) 
public Boolean deleteAudio(@RequestParam String fileName) { 

    return audioService.remove(fileName); 
} 

我们还删除了configurer.favorPathExtension(false)。另一种方法可能是在路径中对fileName进行编码,但我们选择了查询参数方法以避免进一步的副作用。

1

这是因为对象是不是在JSP接受的......用他的

添加这种依赖关系或其他任何发送转换JSON字符串把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 
+0

为gson添加依赖有助于解决我的问题。 – David 2016-08-30 10:04:10

0

RequestMapping值与的.html这应该是不同的结局。

我试着将它改为.json它对我很有用。

0

我已经用下面的代码

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. 
2

今天我也通过同样的问题,得到了类似的问题和解决。就我而言,在web.xml

<servlet-mapping> 
     <servlet-name>spring</servlet-name> 
     <url-pattern>*.html</url-pattern> 
    </servlet-mapping> 

我的网址是有.html扩展。例如:.../getUsers.html。但我在控制器中返回JSON数据。 .html扩展名默认将接受类型设置为html。

所以我更改为以下:

web.xml中:

<servlet-mapping> 
    <servlet-name>spring</servlet-name> 
    <url-pattern>*.html</url-pattern> 
    <url-pattern>*.json</url-pattern> 
</servlet-mapping> 

网址:现在

.../getUsers.json

一切工作正常。希望能帮助到你。

0

我的课程使用了JsonSerialize注解,并且include参数设置为JsonSerialize.Inclusion.NON_DEFAULT。这导致杰克逊确定每个bean属性的默认值。我有一个返回int的bean属性。在我的情况下,问题是bean getter调用了一个推断返回类型的方法(即:一个通用方法)。由于一些奇怪的原因,这些代码编译;它不应该编译,因为你不能使用int作为推断的返回类型。我将该'int'更改为该bean属性的'Integer',并且我不再获得406.奇怪的是,如果将Integer更改为int,则代码现在无法编译。