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>
</dependency>
<!-- Bean Validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<!-- Spring Data JPA -->
<dependency>
<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.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RestController
@ -28,12 +29,12 @@ public class UserController {
}
@PostMapping
public User create(@RequestBody User user) {
public User create(@Valid @RequestBody User user) {
return userService.save(user);
}
@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)
.map(existing -> {
existing.setName(user.getName());

View File

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