@ResponseStatus 注解详解

@ResponseStatus 注解详解

📋 概述

@ResponseStatus 是 Spring 框架提供的一个核心注解,用于在处理 HTTP 请求时设置响应的状态码和原因短语。它可以应用于控制器方法或异常类上,让开发者能够更精确地控制 API 的响应状态。

🎯 主要特性

  • ✅ 支持在方法上直接设置响应状态码
  • ✅ 支持在异常类上定义默认状态码
  • ✅ 提供原因短语的自定义设置
  • ✅ 与全局异常处理器完美集成
  • ✅ 简化 RESTful API 的状态管理

🔧 注解属性

属性 类型 说明 必需
value / code HttpStatus HTTP 状态码枚举值
reason String 状态码的原因短语

💡 使用方式

1. 在控制器方法上使用

java 复制代码
@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping("/{id}")
    @ResponseStatus(HttpStatus.OK)
    public User getUser(@PathVariable Long id) {
        return userService.findById(id);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.deleteById(id);
    }
}

2. 在异常类上使用

java 复制代码
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "用户不存在")
public class UserNotFoundException extends RuntimeException {
    public UserNotFoundException(String message) {
        super(message);
    }
}

@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "请求参数无效")
public class InvalidRequestException extends RuntimeException {
    public InvalidRequestException(String message) {
        super(message);
    }
}

3. 在全局异常处理器中使用

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    public ErrorResponse handleDataIntegrityViolation(DataIntegrityViolationException ex) {
        return new ErrorResponse("CONFLICT", "数据完整性冲突", ex.getMessage());
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidationException(MethodArgumentNotValidException ex) {
        return new ErrorResponse("VALIDATION_ERROR", "参数验证失败", ex.getMessage());
    }
}

🚀 实际应用场景

场景 1:RESTful API 设计

java 复制代码
@RestController
@RequestMapping("/api/products")
public class ProductController {

    @GetMapping
    @ResponseStatus(HttpStatus.OK)
    public List<Product> getAllProducts() {
        return productService.findAll();
    }

    @GetMapping("/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Product getProduct(@PathVariable Long id) {
        Product product = productService.findById(id);
        if (product == null) {
            throw new ProductNotFoundException("产品不存在");
        }
        return product;
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public Product createProduct(@Valid @RequestBody Product product) {
        return productService.save(product);
    }

    @PutMapping("/{id}")
    @ResponseStatus(HttpStatus.OK)
    public Product updateProduct(@PathVariable Long id, @Valid @RequestBody Product product) {
        return productService.update(id, product);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteProduct(@PathVariable Long id) {
        productService.deleteById(id);
    }
}

场景 2:自定义业务异常

java 复制代码
// 业务异常定义
@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "订单不存在")
public class OrderNotFoundException extends RuntimeException {
    public OrderNotFoundException(String orderId) {
        super("订单 " + orderId + " 不存在");
    }
}

@ResponseStatus(value = HttpStatus.FORBIDDEN, reason = "权限不足")
public class InsufficientPermissionException extends RuntimeException {
    public InsufficientPermissionException(String message) {
        super(message);
    }
}

// 控制器使用
@RestController
@RequestMapping("/api/orders")
public class OrderController {

    @GetMapping("/{orderId}")
    public Order getOrder(@PathVariable String orderId, 
                         @RequestHeader("Authorization") String token) {
        // 权限检查
        if (!hasPermission(token)) {
            throw new InsufficientPermissionException("用户权限不足");
        }
        
        // 订单查找
        Order order = orderService.findByOrderId(orderId);
        if (order == null) {
            throw new OrderNotFoundException(orderId);
        }
        
        return order;
    }
}

⚠️ 注意事项

1. reason 属性的限制

java 复制代码
// ❌ 不推荐:使用 reason 属性会清空响应体
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "参数错误")
public class BadRequestException extends RuntimeException {
    // 这种方式会调用 response.sendError(),清空响应体
}

// ✅ 推荐:不使用 reason,在异常处理器中处理
@ResponseStatus(HttpStatus.BAD_REQUEST)
public class BadRequestException extends RuntimeException {
    public BadRequestException(String message) {
        super(message);
    }
}

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(BadRequestException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleBadRequest(BadRequestException ex) {
        return new ErrorResponse("BAD_REQUEST", "请求参数错误", ex.getMessage());
    }
}

2. 与 ResponseEntity 的区别

java 复制代码
// 使用 @ResponseStatus(简单场景)
@GetMapping("/simple")
@ResponseStatus(HttpStatus.OK)
public String getSimpleData() {
    return "简单数据";
}

// 使用 ResponseEntity(复杂场景)
@GetMapping("/complex")
public ResponseEntity<ApiResponse<String>> getComplexData() {
    ApiResponse<String> response = new ApiResponse<>();
    response.setData("复杂数据");
    response.setTimestamp(LocalDateTime.now());
    
    return ResponseEntity.ok()
            .header("Custom-Header", "value")
            .body(response);
}

3. 状态码优先级

java 复制代码
@RestController
public class PriorityController {

    @GetMapping("/priority")
    @ResponseStatus(HttpStatus.OK)  // 方法级别的状态码
    public ResponseEntity<String> getData() {
        // ResponseEntity 的状态码会覆盖 @ResponseStatus
        return ResponseEntity.status(HttpStatus.CREATED)
                .body("数据创建成功");
    }
}

🔍 最佳实践

1. 统一异常处理

java 复制代码
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ValidationException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public ErrorResponse handleValidation(ValidationException ex) {
        return ErrorResponse.builder()
                .code("VALIDATION_ERROR")
                .message("参数验证失败")
                .details(ex.getErrors())
                .timestamp(LocalDateTime.now())
                .build();
    }

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ErrorResponse handleNotFound(ResourceNotFoundException ex) {
        return ErrorResponse.builder()
                .code("RESOURCE_NOT_FOUND")
                .message("资源不存在")
                .details(ex.getMessage())
                .timestamp(LocalDateTime.now())
                .build();
    }
}

2. 状态码枚举使用

java 复制代码
public enum ApiStatus {
    SUCCESS(HttpStatus.OK, "操作成功"),
    CREATED(HttpStatus.CREATED, "创建成功"),
    NO_CONTENT(HttpStatus.NO_CONTENT, "删除成功"),
    BAD_REQUEST(HttpStatus.BAD_REQUEST, "请求参数错误"),
    UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "未授权"),
    FORBIDDEN(HttpStatus.FORBIDDEN, "权限不足"),
    NOT_FOUND(HttpStatus.NOT_FOUND, "资源不存在"),
    INTERNAL_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "服务器内部错误");

    private final HttpStatus httpStatus;
    private final String message;

    ApiStatus(HttpStatus httpStatus, String message) {
        this.httpStatus = httpStatus;
        this.message = message;
    }

    // getter 方法...
}

📊 总结

@ResponseStatus 注解是 Spring 框架中管理 HTTP 响应状态的重要工具:

  • 🎯 适用场景:简单的状态码设置、异常处理、RESTful API 设计
  • 优势:代码简洁、声明式配置、易于维护
  • ⚠️ 限制:reason 属性会清空响应体、灵活性不如 ResponseEntity
  • 🔧 建议:结合全局异常处理器使用,避免使用 reason 属性

通过合理使用 @ResponseStatus 注解,可以让你的 Spring Boot 应用具有更好的 API 设计和错误处理机制。


厦门工学院人工智能创作坊 -- 郑恩赐
2025 年 10 月 1 日

相关推荐
间彧4 小时前
Java枚举单例详解与项目实战指南
后端
wdfk_prog4 小时前
闹钟定时器(Alarm Timer)初始化:构建可挂起的定时器基础框架
java·linux·数据库
Arva .4 小时前
开发准备之日志 git
spring boot·git·后端
怎么没有名字注册了啊5 小时前
C++后台进程
java·c++·算法
z日火5 小时前
Java 泛型
java·开发语言
小宁爱Python5 小时前
从零搭建 RAG 智能问答系统1:基于 LlamaIndex 与 Chainlit实现最简单的聊天助手
人工智能·后端·python
简色5 小时前
题库批量(文件)导入的全链路优化实践
java·数据库·mysql·mybatis·java-rabbitmq
苏三说技术5 小时前
高性能场景为什么推荐使用PostgreSQL,而非MySQL?
后端