Controller 层参数校验方案

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 思路Controller层有两种校验场景单个参数的校验// 用户登录 Controller 方法@PostMapping("/login")public Message login(String verifyCode,String account,String password){ //.

思路

Controller层有两种校验场景

  1. 单个参数的校验
// 用户登录 Controller 方法
@PostMapping("/login")
public Message login(String verifyCode,String account,String password){
  //....       
  return null;
}
  1. 实体类的校验
    实体类User里,有多个字段需要校验,比如用户名不能为空,密码不能为空等等
// 添加用户 Controller 方法
@PostMapping("/add")
public Message addUser(User user){
  //....       
  return null;
}

对于第一种场景,我们可以使用GET参数校验(@RequestParam参数校验)来方便校验参考:
GET参数校验(@RequestParam参数校验)
第二种场景,则结合AOP使用请求参数校验。参考:
[Spring] Web层AOP方式进行参数校验
[SpringMVC] Web层注解式参数校验

下面介绍GET参数校验的实现方法。

环境

注意,Spring boot 内已经集成了Hibernate validator

  • Spring boot
  • Hibernate validator
  • lombok

Hibernate 参数校验 - GET参数校验模式 的实现

  • 编写配置类
package com.spz.demo.security.config;

import lombok.extern.slf4j.Slf4j;
import org.hibernate.validator.HibernateValidator;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.beanvalidation.MethodValidationPostProcessor;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

/**
 * 配置 Hibernate 参数校验
 * 参考:https://blog.csdn.net/u010454030/article/details/53009327
 */
@Slf4j(topic = "SYSTEM_LOG")//日志模块
@Configuration
@EnableAutoConfiguration
public class ValidatorConfig {
    @Bean
    public MethodValidationPostProcessor methodValidationPostProcessor() {
        MethodValidationPostProcessor postProcessor = new MethodValidationPostProcessor();
        postProcessor.setValidator(validator());//快速校验,只要有错马上返回
        return postProcessor;
    }

    @Bean
    public Validator validator(){
        ValidatorFactory validatorFactory = Validation.byProvider( HibernateValidator.class )
                .configure()
                .addProperty( "hibernate.validator.fail_fast", "true" )
                .buildValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        return validator;
    }

}

  • 编写验证错误信息提示
    校验未通过时,将抛出ConstraintViolationException异常,此时需要在异常处理方法里获取错误信息,并进行返回
package com.spz.demo.security.config;

import com.spz.demo.security.bean.Message;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.ValidationException;
import java.util.Set;

@ControllerAdvice
@Component
public class GlobalExceptionHandler {

    /**
     * hibernate 参数校验出错会抛出 ConstraintViolationException 异常
     * 在此方法中处理,将错误信息输出
     * @param exception
     * @return
     */
    @ExceptionHandler
    @ResponseBody
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Object handle(ValidationException exception) {
        String errorInfo = "";
        if(exception instanceof ConstraintViolationException){
            ConstraintViolationException exs = (ConstraintViolationException) exception;

            Set<ConstraintViolation<?>> violations = exs.getConstraintViolations();

            for (ConstraintViolation<?> item : violations) {
                errorInfo = errorInfo + "[" + item.getMessage() + "]";
            }
        }
        return new Message().setErrorMessage(errorInfo);
    }
}

  • Message类是包装请求返回,一般在Controller层使用,用于返回json格式数据
package com.spz.demo.security.bean;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.spz.demo.security.common.MessageCode;
import lombok.Data;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求响应Bean
 * 使用JSON包装请求返回,使用jackson库
 *
 * @author spz
 */
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Message implements Serializable {
    private int code ;
    private String message ;
    private Map<String,Object> data = new HashMap<String, Object>();

    /**
     * 自定义返回
     * @param code
     * @param message
     * @return
     */
    public Message setMessage(int code, String message){
        this.code = code;
        this.message = message;
        return this;
    }

    /**
     * 返回成功
     * @return
     */
    public Message setSuccessMessage(){
        this.code = MessageCode.SUCCESS ;
        this.message = "操作成功" ;
        return this;
    }

    /**
     * 返回成功
     * @param message
     * @return
     */
    public Message setSuccessMessage(String message){
        this.code = MessageCode.SUCCESS ;
        this.message = message ;
        return this;
    }

    /**
     * 返回错误
     * @param message
     * @return
     */
    public Message setErrorMessage(String message){
        this.code = MessageCode.ERROR ;
        this.message = message ;
        return this;
    }

    /**
     * 返回警告
     * @param message
     * @return
     */
    public Message setWarnMessage(String message){
        this.code = MessageCode.WARN ;
        this.message = message ;
        return this;
    }

    /**
     * 返回未登录
     * @param message
     * @return
     */
    public Message setNoLoginMessage(String message){
        this.code = MessageCode.NO_LOGIN ;
        this.message = message ;
        return this;
    }

    /**
     * 返回没有权限
     * @param message
     * @return
     */
    public Message setPermissionDeniedMessage(String message){
        this.code = MessageCode.PERMISSION_DENIED ;
        this.message = message ;
        return this;
    }
}

  • Controller 层使用校验
package com.spz.demo.security.controller;

import com.spz.demo.security.bean.Message;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.validation.constraints.NotEmpty;

/**
 * 用户控制器
 *
 * @author spz
 */
@Slf4j(topic = "USER_LOG")
@RestController
@RequestMapping("/user")
@Validated//需要使用Hibernate非实体类参数校验,需要加入此注解
public class UserController {

    @Autowired
    StringRedisTemplate redis;

    /**
     * 用户登录
     * @return
     */
    @PostMapping("/login")
    public Message login(@NotEmpty(message = "账号不能为空") String account,
                         @NotEmpty(message = "密码不能为空") String password,
                         @NotEmpty(message = "验证码不能为空") String verifyCode){
        //....
        return new Message().setSuccessMessage();
    }

}

使用时,发送用户登录请求,如果参数校验失败,将返回错误信息:

{
  "code": 5000,
  "message": "[验证码不能为空]",
  "data": { }
}

Hibernate 参数校验 - 实体类校验模式的实现

[Spring] Web层AOP方式进行参数校验
[SpringMVC] Web层注解式参数校验

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
2月前
thinkphp5.1全局验证层封装
thinkphp5.1全局验证层封装
27 1
thinkphp5.1全局验证层封装
|
7月前
|
存储 前端开发 Java
Service 层异常抛到 Controller 层处理还是直接处理?
Service 层异常抛到 Controller 层处理还是直接处理?
355 1
|
JSON 前端开发 API
统一处理controller层接口返回的数据
要对controller层的内容进行统一返回,需要用到 @ControllerAdvice ResponseBodyAdvice
370 0
|
前端开发
controller层设计
MVC架构下,我们的web工程结构会分为三层,自下而上是dao层,service层和controller层。controller层为控制层,主要处理外部请求。调用service层,一般情况下,controller层不应该包含业务逻辑,controller的功能应该有以下五点: ⑴、接收请求并解析参数 ⑵、业务逻辑执行成功做出响应 ⑶、异常处理 ⑷、转换业务对象 ⑸、调用 Service 接口
|
JSON JavaScript 前端开发
如何优雅地校验后端接口数据,不做前端背锅侠
最近新接手了一批项目,还没来得及接新需求,一大堆bug就接踵而至,仔细一看,应该返回数组的字段返回了 null,或者没有返回,甚至返回了字符串 "null"???
302 0
如何优雅地校验后端接口数据,不做前端背锅侠
|
Java API
SpringBoot中如何参数校验、统一异常、统一响应以及自定义注解
SpringBoot中如何参数校验、统一异常、统一响应以及自定义注解
283 7
SpringBoot中如何参数校验、统一异常、统一响应以及自定义注解
|
前端开发
GoFrame数据校验之校验结果 | Error接口对象
这篇总结分享:GoFrame数据校验的另外一个知识点:校验结果相关的总结分享。
135 0
|
JSON 前端开发 JavaScript
如何优雅的写 Controller 层代码?
如何优雅的写 Controller 层代码?
如何优雅的写 Controller 层代码?
|
中间件
【TP5.1】使用路由进行权限验证(跟使用全局中间件验证是一样的)
【TP5.1】使用路由进行权限验证(跟使用全局中间件验证是一样的)
192 1
【TP5.1】使用路由进行权限验证(跟使用全局中间件验证是一样的)
|
前端开发 Java Spring
@Validated和@Valid的区别?教你使用它完成Controller参数校验(含级联属性校验)以及原理分析【享学Spring】(下)
@Validated和@Valid的区别?教你使用它完成Controller参数校验(含级联属性校验)以及原理分析【享学Spring】(下)

热门文章

最新文章