feat: 全局异常

This commit is contained in:
xuliangchao 2026-04-29 15:27:33 +08:00
parent 56b643e1ce
commit 8cef660ac9
5 changed files with 98 additions and 2 deletions

View File

@ -36,6 +36,12 @@
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<!-- Bean Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Spring Data JPA --> <!-- Spring Data JPA -->
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>

View File

@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List; import java.util.List;
@RestController @RestController
@ -28,12 +29,12 @@ public class UserController {
} }
@PostMapping @PostMapping
public User create(@RequestBody User user) { public User create(@Valid @RequestBody User user) {
return userService.save(user); return userService.save(user);
} }
@PutMapping("/{id}") @PutMapping("/{id}")
public ResponseEntity<User> update(@PathVariable Long id, @RequestBody User user) { public ResponseEntity<User> update(@PathVariable Long id, @Valid @RequestBody User user) {
return userService.findById(id) return userService.findById(id)
.map(existing -> { .map(existing -> {
existing.setName(user.getName()); existing.setName(user.getName());

View File

@ -1,6 +1,9 @@
package com.example.demo.entity; package com.example.demo.entity;
import javax.persistence.*; import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;
@Entity @Entity
@Table(name = "t_user") @Table(name = "t_user")
@ -10,12 +13,16 @@ public class User {
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id; private Long id;
@NotBlank(message = "姓名不能为空")
@Column(nullable = false) @Column(nullable = false)
private String name; private String name;
@NotBlank(message = "邮箱不能为空")
@Email(message = "邮箱格式不正确")
@Column(nullable = false) @Column(nullable = false)
private String email; private String email;
@Min(value = 0, message = "年龄不能小于0")
private Integer age; private Integer age;
public User() { public User() {

View File

@ -0,0 +1,22 @@
package com.example.demo.exception;
/**
* 业务异常
*/
public class BusinessException extends RuntimeException {
private final int code;
public BusinessException(int code, String message) {
super(message);
this.code = code;
}
public BusinessException(String message) {
this(400, message);
}
public int getCode() {
return code;
}
}

View File

@ -0,0 +1,60 @@
package com.example.demo.exception;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
/**
* 处理参数校验失败
*/
@ExceptionHandler(MethodArgumentNotValidException.class)
public ResponseEntity<Map<String, Object>> handleValidation(MethodArgumentNotValidException ex) {
String message = ex.getBindingResult().getFieldErrors().stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining("; "));
return buildResponse(HttpStatus.BAD_REQUEST, message);
}
/**
* 处理业务异常
*/
@ExceptionHandler(BusinessException.class)
public ResponseEntity<Map<String, Object>> handleBusiness(BusinessException ex) {
log.warn("业务异常: code={}, message={}", ex.getCode(), ex.getMessage());
return buildResponse(HttpStatus.valueOf(ex.getCode()), ex.getMessage());
}
/**
* 处理其他未捕获异常
*/
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleException(Exception ex, HttpServletRequest request) {
log.error("请求 {} {} 发生异常", request.getMethod(), request.getRequestURI(), ex);
return buildResponse(HttpStatus.INTERNAL_SERVER_ERROR, "服务器内部错误");
}
private ResponseEntity<Map<String, Object>> buildResponse(HttpStatus status, String message) {
Map<String, Object> body = new LinkedHashMap<>();
body.put("timestamp", LocalDateTime.now().toString());
body.put("status", status.value());
body.put("error", status.getReasonPhrase());
body.put("message", message);
return ResponseEntity.status(status).body(body);
}
}