2013-05-02 79 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,則代碼現在無法編譯。