本文目录导读:

我来为你提供一个完整的Java全局校验封装方案,包括多种实现方式:
基于Spring框架的全局校验封装
1 自定义注解
import javax.validation.Constraint;
import javax.validation.Payload;
import java.lang.annotation.*;
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Constraint(validatedBy = PhoneValidator.class)
@Documented
public @interface ValidPhone {
String message() default "手机号格式不正确";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
2 自定义校验器
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Pattern;
public class PhoneValidator implements ConstraintValidator<ValidPhone, String> {
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
@Override
public boolean isValid(String phone, ConstraintValidatorContext context) {
if (phone == null || phone.isEmpty()) {
return true; // 交给@NotNull处理
}
return Pattern.matches(PHONE_REGEX, phone);
}
}
全局异常处理封装
1 通用响应类
import lombok.Data;
import java.io.Serializable;
@Data
public class ApiResponse<T> implements Serializable {
private Integer code;
private String message;
private T data;
private Long timestamp;
public ApiResponse() {
this.timestamp = System.currentTimeMillis();
}
public static <T> ApiResponse<T> success(T data) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(200);
response.setMessage("success");
response.setData(data);
return response;
}
public static <T> ApiResponse<T> error(Integer code, String message) {
ApiResponse<T> response = new ApiResponse<>();
response.setCode(code);
response.setMessage(message);
return response;
}
}
2 自定义异常类
import lombok.Getter;
@Getter
public class BusinessException extends RuntimeException {
private Integer code;
public BusinessException(Integer code, String message) {
super(message);
this.code = code;
}
public BusinessException(String message) {
super(message);
this.code = 500;
}
}
3 全局异常处理器
import org.springframework.http.HttpStatus;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;
@RestControllerAdvice
public class GlobalExceptionHandler {
// 处理参数校验异常
@ExceptionHandler(MethodArgumentNotValidException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiResponse<Void> handleValidationExceptions(MethodArgumentNotValidException ex) {
String errorMessage = ex.getBindingResult().getFieldErrors()
.stream()
.map(FieldError::getDefaultMessage)
.collect(Collectors.joining(", "));
return ApiResponse.error(400, errorMessage);
}
// 处理单个参数校验异常
@ExceptionHandler(ConstraintViolationException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiResponse<Void> handleConstraintViolation(ConstraintViolationException ex) {
String errorMessage = ex.getConstraintViolations()
.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(", "));
return ApiResponse.error(400, errorMessage);
}
// 处理业务异常
@ExceptionHandler(BusinessException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public ApiResponse<Void> handleBusinessException(BusinessException ex) {
return ApiResponse.error(ex.getCode(), ex.getMessage());
}
// 处理通用异常
@ExceptionHandler(Exception.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ApiResponse<Void> handleException(Exception ex) {
return ApiResponse.error(500, "服务器内部错误: " + ex.getMessage());
}
}
参数校验工具类
import org.apache.commons.lang3.StringUtils;
import java.util.regex.Pattern;
public class ValidateUtils {
// 手机号正则
private static final String PHONE_REGEX = "^1[3-9]\\d{9}$";
// 邮箱正则
private static final String EMAIL_REGEX = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
// 身份证正则
private static final String ID_CARD_REGEX = "^[1-9]\\d{5}(18|19|20)\\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\\d|3[01])\\d{3}[0-9Xx]$";
public static boolean isPhone(String phone) {
if (StringUtils.isBlank(phone)) {
return false;
}
return Pattern.matches(PHONE_REGEX, phone);
}
public static boolean isEmail(String email) {
if (StringUtils.isBlank(email)) {
return false;
}
return Pattern.matches(EMAIL_REGEX, email);
}
public static boolean isIdCard(String idCard) {
if (StringUtils.isBlank(idCard)) {
return false;
}
return Pattern.matches(ID_CARD_REGEX, idCard);
}
public static void validatePhone(String phone) {
if (!isPhone(phone)) {
throw new BusinessException(400, "手机号格式不正确");
}
}
public static void validateEmail(String email) {
if (!isEmail(email)) {
throw new BusinessException(400, "邮箱格式不正确");
}
}
}
DTO对象校验示例
1 基础校验
import lombok.Data;
import javax.validation.constraints.*;
import java.time.LocalDate;
@Data
public class UserCreateRequest {
@NotBlank(message = "用户名不能为空")
@Size(min = 2, max = 20, message = "用户名长度在2-20个字符之间")
private String username;
@NotBlank(message = "密码不能为空")
@Size(min = 6, max = 20, message = "密码长度在6-20个字符之间")
private String password;
@NotBlank(message = "手机号不能为空")
@ValidPhone(message = "手机号格式不正确")
private String phone;
@Email(message = "邮箱格式不正确")
private String email;
@NotNull(message = "年龄不能为空")
@Min(value = 1, message = "年龄最小为1")
@Max(value = 150, message = "年龄最大为150")
private Integer age;
@NotNull(message = "生日不能为空")
@Past(message = "生日必须是过去的时间")
private LocalDate birthday;
}
2 分组校验
import javax.validation.groups.Default;
public class ValidationGroups {
public interface Create extends Default {}
public interface Update extends Default {}
public interface Query extends Default {}
}
@Data
public class UserDTO {
@NotNull(groups = {Update.class}, message = "ID不能为空")
private Long id;
@NotBlank(groups = {Create.class}, message = "用户名不能为空")
private String username;
@NotBlank(groups = {Create.class}, message = "密码不能为空")
private String password;
@NotBlank(groups = {Create.class, Update.class}, message = "手机号不能为空")
@ValidPhone(groups = {Create.class, Update.class}, message = "手机号格式不正确")
private String phone;
}
Service层校验封装
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
@Service
@Validated
public class UserService {
public User createUser(@Valid @NotNull UserCreateRequest request) {
// 业务逻辑
return new User();
}
@Validated(ValidationGroups.Update.class)
public User updateUser(@Valid UserUpdateRequest request) {
// 业务逻辑
return new User();
}
}
高级校验器封装
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import java.util.Set;
import java.util.stream.Collectors;
@Component
public class ValidationHelper {
private final Validator validator;
public ValidationHelper(Validator validator) {
this.validator = validator;
}
public <T> void validate(T object) {
Set<ConstraintViolation<T>> violations = validator.validate(object);
if (!CollectionUtils.isEmpty(violations)) {
String errorMessage = violations.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(", "));
throw new BusinessException(400, errorMessage);
}
}
public <T> void validate(T object, Class<?>... groups) {
Set<ConstraintViolation<T>> violations = validator.validate(object, groups);
if (!CollectionUtils.isEmpty(violations)) {
String errorMessage = violations.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(", "));
throw new BusinessException(400, errorMessage);
}
}
}
使用示例
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/users")
public class UserController {
@PostMapping
public ApiResponse<User> createUser(@Valid @RequestBody UserCreateRequest request) {
// 参数已自动校验
User user = userService.createUser(request);
return ApiResponse.success(user);
}
@GetMapping("/{id}")
public ApiResponse<User> getUser(@PathVariable @Min(value = 1, message = "ID必须大于0") Long id) {
User user = userService.getUser(id);
return ApiResponse.success(user);
}
@PostMapping("/validate")
public ApiResponse<String> manualValidate(@RequestBody UserCreateRequest request) {
// 手动调用校验
validationHelper.validate(request);
// 或者使用工具类
ValidateUtils.validatePhone(request.getPhone());
ValidateUtils.validateEmail(request.getEmail());
return ApiResponse.success("校验通过");
}
}
这个封装方案提供了:
- 声明式校验(@Valid注解)
- 自定义校验器
- 全局异常处理
- 分组校验
- 工具类支持
- 手动校验支持
可以根据项目需求选择合适的校验方式组合使用。