“告别手动设置响应码!用注解魔法精准控制每个HTTP响应的状态信息”

一、@ResponseStatus定位图解 🗺️

框架地位:Spring MVC异常处理体系的"状态码转换器"

二、核心功能对比表 📊

方式 代码示例 灵活性 适用场景
原生ServletResponse response.setStatus(404) 需要动态判断
@ResponseStatus @ResponseStatus(404) 静态状态码定义
ResponseEntity return new ResponseEntity<>(status) 极高 需要精细控制响应

三、注解使用三叉戟 ⚔️

1. 标注异常类(最常用)

@ResponseStatus(code = HttpStatus.NOT_FOUND, reason = "用户不存在")
public class UserNotFoundException extends RuntimeException {
    // 触发时自动返回404状态
}

2. 标注控制器方法

@GetMapping("/old-api")
@ResponseStatus(code = HttpStatus.GONE, reason = "API已迁移")
public void deprecatedMethod() {
    // 方法体执行后自动返回410状态
}

3. 自定义错误消息(Spring 5+)

@ResponseStatus(value = HttpStatus.BAD_REQUEST)
public class CustomException extends RuntimeException {
    public CustomException(String message) {
        super(message); // 消息会作为响应体
    }
}

四、工作原理揭秘 🔧

五、进阶使用技巧 🚀

1. 结合@ExceptionHandler

@RestControllerAdvice
public class GlobalExceptionHandler {
    
    @ExceptionHandler(ValidationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidationError(ValidationException ex) {
        return new ErrorResponse(ex.getErrors());
    }
}

2. 动态状态码(条件判断)

@GetMapping("/resource/{id}")
public Resource getResource(@PathVariable String id) {
    return resourceRepo.findById(id)
            .orElseThrow(() -> {
                if(id.startsWith("temp_")) {
                    return new ResponseStatusException(HttpStatus.GONE);
                }
                return new ResponseStatusException(HttpStatus.NOT_FOUND);
            });
}

3. 自定义状态描述(国际化)

# messages.properties
resource.notfound=请求的资源不存在 ID: {0}
@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String id) {
        super(MessageFormat.format(
            ResourceBundle.getBundle("messages")
                .getString("resource.notfound"), id));
    }
}

六、状态码选型指南 🏷️

场景 推荐状态码 配合注解示例
资源不存在 404 NOT_FOUND @ResponseStatus(HttpStatus.NOT_FOUND)
参数校验失败 400 BAD_REQUEST @ResponseStatus(HttpStatus.BAD_REQUEST)
权限不足 403 FORBIDDEN @ResponseStatus(HttpStatus.FORBIDDEN)
业务逻辑冲突 409 CONFLICT @ResponseStatus(HttpStatus.CONFLICT)

七、常见问题解答 ❓

Q1:和ResponseEntity有什么区别?
A:@ResponseStatus更声明式,ResponseEntity更灵活可控

Q2:能覆盖@ExceptionHandler的响应码吗?
A:可以,但建议统一使用一种方式保持代码一致性

Q3:如何返回自定义错误JSON?

@ResponseStatus(code = HttpStatus.BAD_REQUEST)
public class ApiException extends RuntimeException {
    private final String errorCode;
    // getter构造器等...
}

// 客户端收到:
// HTTP/1.1 400
// {"errorCode":"INVALID_INPUT","message":"参数无效"}

八、性能优化建议 ⚡

  1. 避免过度使用:简单场景直接用ResponseEntity
  2. 预定义异常类:减少运行时注解解析开销
  3. 状态码缓存:常用异常类可缓存HTTP状态码

九、版本演进对比 🔄

Spring版本 特性增强
3.0 基础注解支持
4.0 支持reason占位符解析
5.0 异常消息自动作为响应体
6.0 更好的RFC 7807问题详情支持

十、最佳实践总结 🏆

  1. 业务异常:用@ResponseStatus定义语义化状态
  2. REST API:结合@RestControllerAdvice统一处理
  3. Web应用:配合错误页面更友好
  4. 微服务:保持各服务状态码规范一致

思考题:在微服务架构中,如何保证跨服务的HTTP状态码一致性?欢迎分享你的设计方案! 💭

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐