You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring ExceptionHandler问题:Accept为XML时406响应无返回体

解决Spring WebFlux中406响应无法返回指定JSON格式的问题

问题描述

作为API消费者,当请求头设置Accept: application/xml时,期望收到如下格式的406响应:

{
    "status": ${responseCode},
    "Message": ${whyHasItHappened}
}

但使用ExceptionHandler处理时,返回Error对象会抛出org.springframework.web.HttpMediaTypeNotAcceptableException: No acceptable representation异常,Postman中无法获取响应体;之前用ObjectMapper转成String返回被要求作为最后手段,需要找到更合适的解决方式。

解决方案

核心问题在于:客户端请求的Accept头是application/xml,但我们需要返回JSON格式的错误响应,Spring默认会根据请求的Accept头匹配对应的消息转换器,若没有配置XML转换器(或不想用XML返回错误),就会抛出异常。以下是两种可行的解决方式:

方式一:在ExceptionHandler上指定返回的媒体类型

修改异常处理器,添加@Produces(MediaType.APPLICATION_JSON_VALUE)注解,强制Spring使用JSON转换器序列化错误对象,同时指定响应状态码为406:

@RestController
@RequestMapping("/api/v1")
public class RepoController {

    private final RepoServiceImpl repoService;

    public RepoController(RepoServiceImpl repoService) {
        this.repoService = repoService;
    }

    @GetMapping("/{username}")
    @ResponseStatus(HttpStatus.OK)
    public Flux<ResponseRepo> getReposByUsername(@PathVariable("username") String username) {
        return repoService.getReposInfo(username);
    }

    @ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
    @ResponseStatus(HttpStatus.NOT_ACCEPTABLE)
    @Produces(MediaType.APPLICATION_JSON_VALUE)
    public Error handleInvalidAcceptHeader(HttpMediaTypeNotAcceptableException e) {
        return new Error(HttpStatus.NOT_ACCEPTABLE.value(), "Type not acceptable");
    }

}

方式二:用ResponseEntity构建响应(更直观)

通过ResponseEntity明确设置响应的状态码和Content-Type,确保返回JSON格式:

@RestController
@RequestMapping("/api/v1")
public class RepoController {

    private final RepoServiceImpl repoService;

    public RepoController(RepoServiceImpl repoService) {
        this.repoService = repoService;
    }

    @GetMapping("/{username}")
    @ResponseStatus(HttpStatus.OK)
    public Flux<ResponseRepo> getReposByUsername(@PathVariable("username") String username) {
        return repoService.getReposInfo(username);
    }

    @ExceptionHandler(HttpMediaTypeNotAcceptableException.class)
    public ResponseEntity<Error> handleInvalidAcceptHeader(HttpMediaTypeNotAcceptableException e) {
        Error error = new Error(HttpStatus.NOT_ACCEPTABLE.value(), "Type not acceptable");
        return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE)
                .contentType(MediaType.APPLICATION_JSON)
                .body(error);
    }

}

注意事项

  1. 确保Error类的字段与期望的JSON格式匹配,字段名大小写要一致(比如示例中的Message首字母大写),且提供对应的getter/setter方法:
public class Error {
    private int status;
    private String Message;

    public Error(int status, String message) {
        this.status = status;
        this.Message = message;
    }

    // getter和setter
    public int getStatus() {
        return status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    public String getMessage() {
        return Message;
    }

    public void setMessage(String message) {
        Message = message;
    }
}
  1. 如果项目中使用了Lombok,可以用@Data注解简化getter/setter的编写,但要注意字段名的正确性。

内容的提问来源于stack exchange,提问作者robertos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 19:40:34