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("文件解析失败");
	}

}

posted @ 2020-10-18 20:25  快点ヤ给我起来♪♫  阅读(93)  评论(0)    收藏  举报