
在spring restful api开发中,http 406 not acceptable 错误是一个常见的挑战,尤其是在处理客户端与服务器之间的内容协商时。当客户端发送一个请求,并在其accept请求头中声明了它能够处理的媒体类型(例如application/json或application/xml),而服务器端却无法生成任何符合这些媒体类型的响应时,就会返回406状态码。
错误堆栈信息通常会显示org.springframework.web.HttpMediaTypeNotAcceptableException: Could not find acceptable representation,这明确指出Spring MVC的消息转换器无法找到一个可以将控制器方法返回值转换为客户端可接受格式的处理器。即使项目中引入了Jackson等JSON处理库的依赖,如果Spring无法正确识别或应用这些转换器,问题依然会存在。
Spring MVC通过HttpMessageConverter接口处理HTTP请求和响应体的序列化与反序列化。当一个控制器方法返回一个Java对象时,Spring会尝试使用注册的HttpMessageConverter将其转换为HTTP响应体。这个过程需要考虑以下几个关键因素:
当上述任一环节不匹配时,例如客户端期望JSON,但服务器只声明能生产XML,或者虽然有JSON转换器但控制器方法没有明确声明produces JSON,Spring就可能抛出406错误。在提供的案例中,虽然添加了Jackson相关的依赖,但如果客户端期望JSON而Spring默认或尝试生成XML(可能是因为某种配置或依赖冲突导致XML转换器优先级更高),或者控制器方法没有明确指定produces = MediaType.APPLICATION_JSON_VALUE,那么问题依然会存在。
解决406错误的核心在于明确告诉Spring控制器方法能够produces(生产)哪种媒体类型的响应,以及能够consumes(消费)哪种媒体类型的请求。这可以通过在@RequestMapping及其派生注解(如@GetMapping, @PostMapping)上使用produces和consumes属性来实现。
对于返回响应体的GET请求,我们需要使用produces属性来指定控制器方法能够生成的媒体类型。例如,如果期望返回JSON格式的响应,应将produces设置为MediaType.APPLICATION_JSON_VALUE。
示例代码:
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
@RestController
@EnableWebMvc
@RequestMapping("/api")
@Log4j2
public class UsersController {
@Autowired
UsersService service;
@ResponseBody
@GetMapping(value = "/users",
produces = MediaType.APPLICATION_JSON_VALUE) // 明确指定生成JSON
public ResponseEntity<UsersGetByIdResponseBody> findUById(@RequestParam Long userID) {
// ... 业务逻辑 ...
return service.getUsersInfoById(userID);
}
// ... 其他方法 ...
}通过添加produces = MediaType.APPLICATION_JSON_VALUE,我们明确告诉Spring,findUById方法将生成JSON格式的响应。当客户端发送带有Accept: application/json头的请求时,Spring就能够找到MappingJackson2HttpMessageConverter来处理响应。
对于POST请求,通常涉及到接收请求体并返回响应体。因此,除了produces,我们还需要考虑consumes属性,它指定了控制器方法能够接受的请求体媒体类型。如果客户端发送的Content-Type头与consumes不匹配,可能会导致415 Unsupported Media Type 错误。
示例代码:
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
@RestController
@EnableWebMvc
@RequestMapping("/api")
@Log4j2
public class UsersController {
@Autowired
UsersService service;
@PostMapping(value = "/users",
consumes = MediaType.APPLICATION_JSON_VALUE, // 明确指定消费JSON请求体
produces = MediaType.APPLICATION_JSON_VALUE) // 明确指定生成JSON响应体
public Users createU(@RequestBody UsersPostRequestBody ubody) {
// ... 业务逻辑 ...
return service.save(ubody);
}
// ... 其他方法 ...
}在这里,consumes = MediaType.APPLICATION_JSON_VALUE确保控制器方法只接受JSON格式的请求体,而produces = MediaType.APPLICATION_JSON_VALUE则确保响应也是JSON格式。
虽然明确指定produces和consumes是解决406错误的关键,但正确的依赖管理也是必不可少的。为了支持JSON处理,jackson-databind是核心依赖:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version> <!-- 使用合适的版本 -->
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.annotations</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>而jackson-dataformat-xml只有在需要处理XML时才应添加。在尝试获取JSON响应时,如果添加了XML相关的Jackson依赖,可能会导致Spring默认尝试使用XML转换器,从而使问题变得复杂。因此,仅在需要时引入相关依赖,并始终通过produces和consumes明确声明意图,是最佳实践。
HTTP 406 Not Acceptable 错误在Spring REST API中通常是内容协商失败的信号。解决此问题的关键在于:
通过遵循这些实践,开发者可以构建更加健壮和可预测的Spring RESTful API,有效避免内容协商相关的错误,确保API能够按照预期提供和消费数据。
以上就是Spring REST API 406 错误:内容协商与解决方案的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号