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

基于Spring的RestControllerAdvice按sourceid头路由至对应异常处理器

问题

我们开发了一个服务于不同部门的API,但4xx或5xx错误响应体格式需遵循各部门要求,无法自主决定。所幸不同部门的请求带有不同的sourceid HTTP请求头。请问基于Spring的ExceptionHandler和RestControllerAdvice机制,能否根据请求中的sourceid头将异常路由至对应的ExceptionHandler,以返回符合预期格式的响应?

回答

完全可以实现,基于Spring的RestControllerAdvice和ExceptionHandler机制,有两种常用的实现思路:

方案一:多ExceptionHandler方法匹配特定sourceid

通过在ExceptionHandler方法中绑定sourceid请求头,让Spring自动匹配符合条件的处理方法。如果请求头不匹配,Spring会自动尝试其他兼容的ExceptionHandler方法。

示例代码:

@RestControllerAdvice
public class GlobalExceptionHandler {

    // 处理sourceid为deptA的请求异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<DeptAErrorResponse> handleDeptAException(Exception e, @RequestHeader("sourceid") String sourceid) {
        if (!"deptA".equals(sourceid)) {
            throw new IllegalStateException("不匹配的sourceid");
        }
        // 构造符合deptA格式的错误响应
        DeptAErrorResponse response = new DeptAErrorResponse();
        response.setCode("A-500");
        response.setMsg(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    // 处理sourceid为deptB的请求异常
    @ExceptionHandler(Exception.class)
    public ResponseEntity<DeptBErrorResponse> handleDeptBException(Exception e, @RequestHeader("sourceid") String sourceid) {
        if (!"deptB".equals(sourceid)) {
            throw new IllegalStateException("不匹配的sourceid");
        }
        // 构造符合deptB格式的错误响应
        DeptBErrorResponse response = new DeptBErrorResponse();
        response.setErrorId(UUID.randomUUID().toString());
        response.setErrorMessage(e.getMessage());
        response.setTimestamp(System.currentTimeMillis());
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    // 默认处理逻辑(当sourceid不存在或不匹配时)
    @ExceptionHandler(Exception.class)
    public ResponseEntity<DefaultErrorResponse> handleDefaultException(Exception e) {
        DefaultErrorResponse response = new DefaultErrorResponse();
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setMessage(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

方案二:单一ExceptionHandler分支处理

在全局异常处理类中注入HttpServletRequest,获取sourceid后通过分支逻辑调用对应部门的错误响应构造方法。这种方式更适合部门较多的场景,便于统一维护路由规则。

示例代码:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private HttpServletRequest request;

    @ExceptionHandler(Exception.class)
    public ResponseEntity<?> handleException(Exception e) {
        String sourceid = request.getHeader("sourceid");
        switch (sourceid) {
            case "deptA":
                return buildDeptAResponse(e);
            case "deptB":
                return buildDeptBResponse(e);
            // 可扩展更多部门分支
            default:
                return buildDefaultResponse(e);
        }
    }

    private ResponseEntity<DeptAErrorResponse> buildDeptAResponse(Exception e) {
        DeptAErrorResponse response = new DeptAErrorResponse();
        response.setCode("A-" + HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setMessage(e.getMessage());
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    private ResponseEntity<DeptBErrorResponse> buildDeptBResponse(Exception e) {
        DeptBErrorResponse response = new DeptBErrorResponse();
        response.setErrorDetails(e.getMessage());
        response.setErrorCode(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setRequestId(request.getHeader("requestId"));
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }

    private ResponseEntity<DefaultErrorResponse> buildDefaultResponse(Exception e) {
        DefaultErrorResponse response = new DefaultErrorResponse();
        response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        response.setMessage("服务器内部错误");
        return new ResponseEntity<>(response, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

两种方案都能满足根据sourceid路由异常处理逻辑的需求,你可以根据部门数量和维护成本选择合适的实现方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 04:23:09