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

WebApplicationException无法返回JSON错误体的问题排查

解决JAX-RS(Jetty)错误状态码响应体为空的问题

我之前也遇到过一模一样的情况!尤其是在Jetty容器下返回4xx/5xx状态码时,明明设置了entity但响应体就是空的,而3xx状态却正常。结合你的测试和代码,咱们一步步解决:

1. 先搞定直接返回Response时的实体丢失问题

Jetty(以及不少Servlet容器)默认会用内置错误页面接管4xx/5xx这类错误状态码的响应,这就导致你手动设置的entity被覆盖了。解决这个的关键是让JAX-RS使用setStatus()而非sendError()来设置状态码——后者会触发容器的错误页面机制。

你只需要在你的JAX-RS Application类里添加一个配置属性:

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;
import javax.ws.rs.core.ServerProperties;
import java.util.HashMap;
import java.util.Map;

@ApplicationPath("/your-api-path")
public class YourApplication extends Application {
    @Override
    public Map<String, Object> getProperties() {
        Map<String, Object> props = new HashMap<>();
        // 核心配置:禁用容器自动接管错误响应
        props.put(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
        return props;
    }
}

添加这个配置后,再测试你那片返回401的代码,Postman应该就能看到"Some message here"的响应体了。

2. 让你的ExceptionMapper生效

你的UnexpectedExceptionMapper代码本身没问题,但大概率是没被JAX-RS正确注册。要确保它被框架扫描到,有两种方式:

方式一:手动注册到Application类

如果你的项目是通过继承Application来配置JAX-RS,直接把Mapper加入到getClasses()里:

@Override
public Set<Class<?>> getClasses() {
    Set<Class<?>> classes = new HashSet<>();
    // 注册自定义异常映射器
    classes.add(UnexpectedExceptionMapper.class);
    // 别忘了添加你的其他资源类(比如那个getActionIdForPlaceAssetOrder所在的类)
    classes.add(YourResourceClass.class);
    return classes;
}

方式二:确保自动扫描覆盖Mapper所在包

如果你的项目用的是自动扫描(比如Jersey的@Packages或者web.xml里的配置),要确认UnexpectedExceptionMapper所在的包被包含在扫描路径中。

另外补充个小细节:如果你的代码里抛出的是WebApplicationException,通用的ExceptionMapper<Exception>可能不会优先触发——因为JAX-RS会优先匹配最具体的异常类型。如果需要专门处理WebApplicationException,可以单独写一个映射器:

@Provider
public class WebAppExceptionMapper implements ExceptionMapper<WebApplicationException> {
    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    public Response toResponse(WebApplicationException e) {
        ErrorInfo errorInfo = new ErrorInfo(e.getMessage(), e.getCause() != null ? e.getCause().getMessage() : e.getMessage());
        try {
            return Response.status(e.getResponse().getStatus())
                    .entity(MAPPER.writeValueAsString(errorInfo))
                    .type(MediaType.APPLICATION_JSON)
                    .build();
        } catch (JsonProcessingException ex) {
            return Response.status(e.getResponse().getStatus())
                    .entity("{\"message\":\"An error occurred\"}")
                    .type(MediaType.APPLICATION_JSON)
                    .build();
        }
    }
}

3. 最后验证

先测试直接返回带实体的错误Response,确认响应体正常显示;再测试throw new Exception("test"),看看你的UnexpectedExceptionMapper是否能正确返回JSON格式的错误信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:51:36