1. 程式人生 > >SpringBoot get請求返回 錯誤碼 406 Not Acceptable

SpringBoot get請求返回 錯誤碼 406 Not Acceptable

場景描述

今天需要寫查詢伺服器上某一個檔案是否存在,整個Controller註解為@RestController
程式碼大致如下

@ApiOperation(value = "查詢檔案是否存在")
    @RequestMapping(value = "/query/{filename:.+}", method = RequestMethod.GET)
    public JSONData query(@PathVariable String filename){
        String filePath= appProperties.getFilePath() + filename;
        boolean exist = false;
        File file = new File(filePath);
        if(file.exists()){
        	exist = true;
		}
		Map data = Maps.newHashMap();
		data.put("exist",exist);
        return JSONData.builder().msg(EnumResponseMsg.RESP_SUCCESS_0000.getMsg()).
              code(EnumResponseMsg.RESP_SUCCESS_0000.getCode()).data(data).success(true).build();
    }

PathVariable 填abcd.txt, URI為 /query/abcd.txt
利用swagger-ui 跑介面返回程式碼 406。

報錯分析

註解@RestController意味著要把物件轉換成json格式返回給請求端,有可能是缺少jackson相關的jar(例如jackson-core-asl-x.x.x.jar,jackson-mapper-asl-x.x.x.jar),springboot 的pom.xml應該是引用過這些jar的。況且其他的get也有返回內容,並沒有出現406,問題應該不在這。
後面查到資料springmvc 以.html結尾的請求是不會返回JSON資料,很有可能以 .txt 結尾也是這個原因。
後查詢資料證實:Spring Boot的MVC預設配置中使用的 ViewResolver 為 ContentNegotiatingViewResolver,該檢視解析器的功能是根據要請求的文件型別,來查詢不同的檢視以返回對應格式的文件。請求的文件型別要可以從請求頭中的Accept中獲取,也可以通過URI字尾名得到,如/login.html即為請求HTML格式的文件,這兩種方式分別對應著兩種不同的Strategy(策略),預設為根據URI字尾名。

解決方法

初步定位是上述原因,那麼怎麼解決呢?
方法一、避免以.txt結尾的URL去訪問,改變我們的@RequestMapping的value。我這邊的情況不太適用。
方法二、繼承WebMvcConfigurerAdapter 重寫configureContentNegotiation方法禁用字尾方式進行內容協商

@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
	@Override
	public void configureContentNegotiation(ContentNegotiationConfigurer configurer) {
		configurer.favorPathExtension(false);
	}
}

這種方式更適合我這邊的場景,前後端分離,不需要字尾方式,乾脆禁用掉。