天天看點

Springmvc通過@ResponseBody标簽傳回JSON資料的方法都報406 (Not Acceptable)錯

引言: 

前幾天同學使用SpringMVC,在前端頁面使用AJAX請求後端資料的時候報了406 Not Acceptable的問題,當時也去度娘找解決方法,無奈找了好久沒找到。是以寫下來,免得以後遇到這個問題,自己想不起來!

1、先來看看代碼吧(看了部分代碼,估計已經有人看出來大概是什麼錯了)

1.1、背景主要代碼

@Controller
public class FooController {
   /**
     * 傳回一串測試的json資料
     * 
     * @return {"name":"LinHenk"}
     */
    @RequestMapping(value = "foo/getJson", method = RequestMethod.GET)
    @ResponseBody
    public Map<String,String> getJson() {
        Map<String,String> map = new HashMap<String, String>();
        map.put("name","linhenk" );
        return map;
    }
    //其他方法省略
}
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

1.2、前台代碼主要代碼(點選button,然後ajax向背景請求資料)

<script type="text/javascript">
    $(function(){
        $("#btn").click(function(){
            $.ajax({
                //foo/getJson後端方法的請求路徑
                url : "foo/getJson.html",
                type : "get",
                dataType : "json",
                success : function(data){
                    alert(data.name);
                }
            });
        })
    }) 
</script>
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

1.3、web.xml中SpringMVC的DispatcherServlet的配置(這裡看出存在某種問題或陰謀基本就不用看下面了)

<!-- 配置SpringMVC架構入口 -->
    <servlet>
        <servlet-name>springmvc-406</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/SpringMVC.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>springmvc-406</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

2、在浏覽器進行對頁面通路,并且點選按鍵,使其向背景系統請求資料

那麼來看看報的是什麼錯: 

Springmvc通過@ResponseBody标簽傳回JSON資料的方法都報406 (Not Acceptable)錯
Request URL:http://localhost:8080/springmvc-406/foo/getJson.html
Request Method:GET
Status Code: Not Acceptable
Remote Address:[::]:
           
  • 1
  • 2
  • 3
  • 4

3、度娘上找到的解決方法

大部分的答案都是,因為程式中使用到了@ResponseBody該注解,該注解可以将對象轉成json格式,但是@ResponseBody這個注解需要依賴jackson的相關jar包。 

ps:如果同樣遇到406問題的朋友,請先看看是否缺少jackson相關的jar包,如果是缺少相關jar可以使用如下方法解決: 

3.1、maven工程(添加以下依賴既可解決,注意jackson的版本是否和您目前SpringMVC的版本沖突):

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.4.2</version>
</dependency>
           
  • 1
  • 2
  • 3
  • 4
  • 5

3.2、非maven工程,通過以下連結點選下載下傳jackson-2.4.2,進行下載下傳,将下載下傳好的jar包,加入到工程中

4、工程中已存在jackson的相關jar包

Springmvc通過@ResponseBody标簽傳回JSON資料的方法都報406 (Not Acceptable)錯

看看日志檔案:

-- ::, [http-bio--exec-] [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] DispatcherServlet with name 'springmvc-406' processing GET request for [/springmvc-/foo/getJson.html]
-- ::, [http-bio--exec-] [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Looking up handler method for path /foo/getJson.html
2017-01-19 09::, [http-bio--exec-] [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping]-[DEBUG] Returning handler method [public java.util.Map<java.lang.String, java.lang.String> com.henk.springmvc.error406.controller.FooController.getJson()]
2017-01-19 09::, [http-bio--exec-] [org.springframework.beans.factory.support.DefaultListableBeanFactory]-[DEBUG] Returning cached instance of singleton bean 'fooController'
-- ::, [http-bio--exec-] [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Last-Modified value for [/springmvc-/foo/getJson.html] is: -
-- ::, [http-bio--exec-] [org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver]-[DEBUG] Resolving exception from handler [public java.util.Map<java.lang.String, java.lang.String> com.henk.springmvc.error406.controller.FooController.getJson()]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
-- ::, [http-bio--exec-] [org.springframework.web.servlet.mvc.annotation.ResponseStatusExceptionResolver]-[DEBUG] Resolving exception from handler [public java.util.Map<java.lang.String, java.lang.String> com.henk.springmvc.error406.controller.FooController.getJson()]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
-- ::, [http-bio--exec-] [org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver]-[DEBUG] Resolving exception from handler [public java.util.Map<java.lang.String, java.lang.String> com.henk.springmvc.error406.controller.FooController.getJson()]: org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation
-- ::, [http-bio--exec-] [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Null ModelAndView returned to DispatcherServlet with name 'springmvc-406': assuming HandlerAdapter completed request handling
-- ::, [http-bio--exec-] [org.springframework.web.servlet.DispatcherServlet]-[DEBUG] Successfully completed request
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

由以上日志可以看出,請求已經執行,但是在springmvc在進行響應的時候,産生了406

5、解決方法

前面有一個很重要的xml代碼,就是配置SpringMVC的DispatcherServlet的代碼

<servlet-mapping>
        <servlet-name>springmvc-406</servlet-name>
        <url-pattern>*.html</url-pattern>
</servlet-mapping>
           
  • 1
  • 2
  • 3
  • 4

就是這段配置的問題,url-pattern為*.html,在SpringMVC中如果請求以html結尾,那麼就不會傳回JSON資料,這是SpringMVC所規定的

怎麼解決? 

我們将url-pattern配置為

*.html

,是想使用僞靜态,來提高網站的SEO,是以直接将url-pattern改成

*.xxx

 是不太合适的。不過我們可以提供多路路徑進入SpringMVC。 

代碼如下:

<!-- 配置SpringMVC架構入口 -->
    <servlet>
        <servlet-name>springmvc-406</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/SpringMVC.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <!-- 通過html結尾進入SpringMVC -->
    <servlet-mapping>
        <servlet-name>springmvc-406</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    <!-- 通過/service/* 進入SpringMVC-->
    <servlet-mapping>
        <servlet-name>springmvc-406</servlet-name>
        <url-pattern>/service/*</url-pattern>
    </servlet-mapping>
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

是以前端代碼可以修改為以下形式即可解決406錯誤:

<script type="text/javascript">
    $(function(){
            $("#btn").click(function(){
                $.ajax({
                    url : "service/foo/getJson",
                    type : "get",
                    dataType : "json",
                    success : function(data){
                        alert(data.name);
                    }
                });
            })
        }) 
</script>
           
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

解決後的效果:

Springmvc通過@ResponseBody标簽傳回JSON資料的方法都報406 (Not Acceptable)錯

6、小結

以上就是整個的406報錯的解決過程,寫得可能不是很清晰,但是隻要注意以下幾點就可以避免文中的出現兩個SpringMVC的錯誤: 

1. 導入Jackson所依賴的相關JAR 

2.盡量避免向以html結尾的路徑請求JSON資料,如果實在不能避免,配置多路徑進入SpringMVC

繼續閱讀