SpringBoot + Hibernate Validator 进行参数验证
SpringBoot Validator 进行参数验证
service的参数验证写多了自然就会觉得烦,最近发现个可以简化参数验证的好东西,学习记录一下
一、需要的依赖
<dependencies>
<!--引入web模块-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- validation -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- spring-boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.3.12.RELEASE</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
二、编写需要进行参数验证的dto
import lombok.Data;
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
@Data // 这里用了Lombok
public class ValidationTest {
@Size(min = 2, max = 4, message = "姓名长度要在2到4之间")
private String name;
@Min(value = 0, message = "年龄不能低于0")
@Max(value = 60, message = "年龄不能大于60")
private Integer age;
@Pattern(regexp = "^1[3|4|5|7|8][0-9]{9}$", message = "手机号码格式有误")
private String phone;
@Pattern(regexp = "^(\\w+([-.][A-Za-z0-9]+)*){3,18}@\\w+([-.][A-Za-z0-9]+)*\\.\\w+([-.][A-Za-z0-9]+)*$",
message = "电子邮箱格式错误")
private String email;
}
三、编写Controller
import com.domain.JsonResult;
import com.domain.ValidationTest;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
@Validated
@RestController
@RequestMapping("test")
public class TestController {
@GetMapping("validation/result")
public String validationTest(@Validated ValidationTest v) throws PracException {
return "成功";
}
}
四、编写通用异常处理 (ResponseMsg 为自定义的类)
package com.education.service.base.config;
import com.education.service.base.entity.ResponseMsg;
import com.education.service.base.entity.ServiceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import static com.education.service.base.entity.enums.ResponseEnum.ERROR;
/**
* @author Mr_W
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
private static final Logger LOGGER = LoggerFactory.getLogger(GlobalExceptionHandler.class);
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(value = Exception.class)
public ResponseMsg internalErrorHandler(Exception e) {
ResponseMsg resp;
if (e instanceof ServiceException) {
LOGGER.error("happened serviceException, Caused by " + getMessage(e), e);
resp = ResponseMsg.resp(((ServiceException) e).getCode(), ((ServiceException) e).getMsg());
} else {
LOGGER.error("happened systemException, Caused by " + getMessage(e), e);
resp = ResponseMsg.fail();
}
return resp;
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(value = MethodArgumentNotValidException.class)
public ResponseMsg paramErrorHandler(MethodArgumentNotValidException e) {
BindingResult exceptions = e.getBindingResult();
// 判断异常中是否有错误信息,如果存在就使用异常中的消息,否则使用默认消息
if (exceptions.hasErrors()) {
List<ObjectError> errors = exceptions.getAllErrors();
if (!errors.isEmpty()) {
// 这里列出了全部错误参数,按正常逻辑,只需要第一条错误即可
FieldError fieldError = (FieldError) errors.get(0);
LOGGER.error("invalid parameter, Caused by " + fieldError.getDefaultMessage(), e);
return ResponseMsg.resp(ERROR.getCode(), fieldError.getDefaultMessage());
}
}
return ResponseMsg.resp(ERROR);
}
private String getMessage(Exception e) {
StringWriter sw = new StringWriter();
try (PrintWriter pw = new PrintWriter(sw)) {
e.printStackTrace(pw);
pw.flush();
sw.flush();
}
return sw.toString();
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(MissingServletRequestParameterException.class)
public ResponseMsg handlerMissingServletRequestParameterException(MissingServletRequestParameterException e) {
LOGGER.error(e.getParameterName() + "不能为空", e);
return ResponseMsg.resp(ERROR, e.getParameterName() + "不能为空");
}
@ResponseStatus(HttpStatus.BAD_REQUEST)
@ExceptionHandler(BindException.class)
public ResponseMsg handlerBindException(BindException e) {
// PropertyAccessException
if (e.getAllErrors().get(0).contains(TypeMismatchException.class)) {
LOGGER.error(((FieldError) e.getAllErrors().get(0)).getField() + " 字段类型错误", e);
return ResponseMsg.resp(ERROR, ((FieldError) e.getAllErrors().get(0)).getField() + " 字段类型错误");
} else {
LOGGER.error(e.getAllErrors().get(0).getDefaultMessage(), e);
return ResponseMsg.resp(ERROR, e.getAllErrors().get(0).getDefaultMessage());
}
}
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ExceptionHandler(MultipartException.class)
public ResponseMsg handleMultipartException(MultipartException e) {
LOGGER.error("文件解析失败", e);
return ResponseMsg.fail("文件解析失败");
}
}

浙公网安备 33010602011771号