SpringMVC优雅的实现数据校验

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/lynnlovemin/article/details/78989040

我们在使用SpringMVC提供接口时,所提供的参数难免会进行参数的合法性校验,比如非空校验,最原始的办法就是手动校验,比如下面的代码:

if(StringUtils.isBlank(authorize.getClientId())){
    log.debug("clientId为必填项!");
}

如果一个两个参数还好,如果参数很多比如几十个,那么就要判断几十次,代码量剧增,可读性也不好。
SpringMVC为我们提供了Valid,通过Valid很方便的进行数据的合法性校验,请看代码:

@GetMapping("authorize")
public void authorize(@Valid AuthorizeIn authorize, BindingResult ret){
    if(result.hasFieldErrors()){
            List<FieldError> errorList = result.getFieldErrors();
            //通过断言抛出参数不合法的异常
            errorList.stream().forEach(item -> Assert.isTrue(false,item.getDefaultMessage()));
        }
}
public class AuthorizeIn extends BaseModel{

    @NotBlank(message = "缺少response_type参数")
    private String responseType;
    @NotBlank(message = "缺少client_id参数")
    private String ClientId;

    private String state;

    @NotBlank(message = "缺少redirect_uri参数")
    private String redirectUri;

    public String getResponseType() {
        return responseType;
    }

    public void setResponseType(String responseType) {
        this.responseType = responseType;
    }

    public String getClientId() {
        return ClientId;
    }

    public void setClientId(String clientId) {
        ClientId = clientId;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public String getRedirectUri() {
        return redirectUri;
    }

    public void setRedirectUri(String redirectUri) {
        this.redirectUri = redirectUri;
    }
}

在controller的方法需要校验的参数后面必须跟BindingResult,否则无法进行校验。但是这样会抛出异常,对用户而言不太友好!
那怎么办呢?
很简单,我们可以利用Spring的AOP特性,拦截异常,并输出友好的参数。接下来我们就来实现异常的拦截:

@Component
@Aspect
public class WebExceptionAspect implements ThrowsAdvice{

    public static final Logger logger = LoggerFactory.getLogger(WebExceptionAspect.class);

//拦截被GetMapping注解的方法    @Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")
    private void webPointcut() {
    }

    @AfterThrowing(pointcut = "webPointcut()",throwing = "e")
    public void afterThrowing(Exception e) throws Throwable {
        logger.debug("exception 来了!");
        if(StringUtils.isNotBlank(e.getMessage())){
                           writeContent(e.getMessage());
        }else{
            writeContent("参数错误!");
        }

    }

    /**
     * 将内容输出到浏览器
     *
     * @param content
     *            输出内容
     */
    private void writeContent(String content) {
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getResponse();
        response.reset();
        response.setCharacterEncoding("UTF-8");
        response.setHeader("Content-Type", "text/plain;charset=UTF-8");
        response.setHeader("icop-content-type", "exception");
        PrintWriter writer = null;
        try {
            writer = response.getWriter();

            writer.print((content == null) ? "" : content);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

这样当我们传入不合法的参数时就会进入WebExceptionAspect类,从而输出友好参数。
我们再把验证的代码单独封装成方法:

protected void validate(BindingResult result){
        if(result.hasFieldErrors()){
            List<FieldError> errorList = result.getFieldErrors();
            errorList.stream().forEach(item -> Assert.isTrue(false,item.getDefaultMessage()));
        }
    }

这样每次参数校验只需要调用validate方法就行了,我们可以看到代码的可读性也大大的提高了。

猜你喜欢

转载自blog.csdn.net/lynnlovemin/article/details/78989040
今日推荐