76. Spring Boot完美解決(406)Could not find acceptable representation原因及解決方法


 

【原創文章】

       使用Spring Boot的Web項目,處理/login請求的控制器方法(該方法會返回JSON格式的數據)。此時如果訪問localhost:8080/login.html,用戶期望返回jsons數據,但框架卻報錯:

 

There was an unexpected error (type=Not Acceptable, status=406).

Could not find acceptable representation

 

 

或者這樣的異常信息:

org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation

    at org.springframework.web.servlet.mvc.method.RequestMappingInfoHandlerMapping.handleNoMatch(RequestMappingInfoHandlerMapping.java:235) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]

    at org.springframework.web.servlet.handler.AbstractHandlerMethodMapping.lookupHandlerMethod(AbstractHandlerMethodMapping.java:382) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]

 

 

錯誤原因:

       Spring Boot的MVC默認配置中使用的 ViewResolver 為 ContentNegotiatingViewResolver,該視圖解析器的功能是根據要請求的文檔類型,來查找不同的視圖以返回對應格式的文檔。請求的文檔類型要可以從請求頭中的Accept中獲取,也可以通過URI后綴名得到,如/login.html即為請求HTML格式的文檔,這兩種方式分別對應着兩種不同的Strategy(策略),默認為根據URI后綴名。

 

ContentNegotiatingViewResolver中有說明:

The ContentNegotiatingViewResolver does not resolve views itself but rather delegates to other view resolvers, selecting the view that resembles the representation requested by the client. Two strategies exist for a client to request a representation from the server: 
• Use a distinct URI for each resource, typically by using a different file extension in the URI. For example, the URIhttp://www.example.com/users/fred.pdf requests a PDF representation of the user fred, and http://www.example.com/users/fred.xmlrequests an XML representation. 
• Use the same URI for the client to locate the resource, but set the Accept HTTP request header to list the media types that it understands. For example, an HTTP request for http:// www.example.com/users/fred with an Accept header set to application/pdf requests a PDF representation of the user fred, while http://www.example.com/users/fred with an Accept header set to text/xml requests an XML representation. This strategy is known as content negotiation.

      

        因此,當用戶請求 /login.html 時,spring會查找/login對應的控制器,並得到其返回的文檔類型為application/json, 然后判斷它與后綴名.html文檔類型是否匹配,如果不匹配,就報HttpMediaTypeNotAcceptableException了。

       其實它的初衷是好的,它是想實現訪問/user.json時返回JSON數據,訪問/user.html返回HTML, 訪問/user.xml則返回XML的功能。但是在這里我們只用Spring Boot提供RESTful接口,因此該功能就無用武之地了。

 

解決方案

       我們剛才在上面說了Spring 會通過URI后綴獲取請求格式,當訪問/login.html的時候,那么根據當前的URI獲取到后綴.html,那么判斷與.html文檔類型是否匹配,匹配的話執行相應的解析器。那么我們就會想,我們能夠關閉這種默認的后綴匹配規則呢,既然本文章說是完美解決答案就是肯定的。解決步驟就兩步驟:

(1)在啟動類App.java類中繼承:WebMvcConfigurerAdapter

(2)覆蓋方法:configureContentNegotiation

具體代碼如下:

package com.kfit;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;

import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

 

/**

 *

 * @author Angel --守護天使

 * @version v.0.1

 * @date 2016年7月29日下午7:06:11

 */

@SpringBootApplication

public class ApiCoreApp extends WebMvcConfigurerAdapter {

   

    /**

     (1)在啟動類App.java類中繼承:WebMvcConfigurerAdapter

    (2)覆蓋方法:configureContentNegotiation

   

    favorPathExtension表示支持后綴匹配,

    屬性ignoreAcceptHeader默認為fasle,表示accept-header匹配,defaultContentType開啟默認匹配。

       例如:請求aaa.xx,若設置<entry key="xx" value="application/xml"/> 也能匹配以xml返回。

根據以上條件進行一一匹配最終,得到相關並符合的策略初始化ContentNegotiationManager  

     */

    @Override

   public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {

        configurer.favorPathExtension(false);

    }

    public static void main(String[] args) {

       SpringApplication.run(ApiCoreApp.class, args);

    }

}

       這里說下核心代碼:

configurer.favorPathExtension(false);

   favorPathExtension表示支持后綴匹配,

   屬性ignoreAcceptHeader默認為fasle,表示accept-header匹配,defaultContentType開啟默認匹配。

      例如:請求aaa.xx,若設置<entry key="xx" value="application/xml"/> 也能匹配以xml返回。

 

根據以上條件進行一一匹配最終,得到相關並符合的策略初始化ContentNegotiationManager


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM