您好,欢迎访问一九零五行业门户网

SpringBoot参数怎么校验

使用传统方式的弊端public string adduser(user user) { if (user == null || user.getid() == null || user.getaccount() == null || user.getpassword() == null || user.getemail() == null) { return "对象或者对象字段不能为空"; } if (stringutils.isempty(user.getaccount()) || stringutils.isempty(user.getpassword()) || stringutils.isempty(user.getemail())) { return "不能输入空字符串"; } if (user.getaccount().length() < 6 || user.getaccount().length() > 11) { return "账号长度必须是6-11个字符"; } if (user.getpassword().length() < 6 || user.getpassword().length() > 16) { return "密码长度必须是6-16个字符"; } if (!pattern.matches("^[a-za-z0-9_-]+@[a-za-z0-9_-]+(\\.[a-za-z0-9_-]+)+$", user.getemail())) { return "邮箱格式不正确"; } // 参数校验完毕后这里就写上业务逻辑 return "success"; }
这样做确实没有什么问题,而且排版也工整,但代码太繁琐了,如果有几十个字段要校验,那这个方法里面将会变得非常臃肿,实在不够优雅。下面我们就来讲讲如何使用最优雅的方式来解决。
引入依赖<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-validation</artifactid></dependency>
注解说明注解说明
@assertfalse 被注解的元素必须为 false
@asserttrue 被注解的元素必须为 true
@decimalmax(value) 被注解的元素必须是一个数字,其值必须小于等于指定的最大值
@decimalmin(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最小值
@digits (integer, fraction) 被注解的元素必须是一个数字,其值必须在可接受的范围内
@null 被注解的元素必须为空
@notnull 被注解的元素必须不为空
@min(value) 被注解的元素必须是一个数字,其值必须大于等于指定的最大值
@max(value) 被注解的元素必须是一个数字,其值必须小于等于指定的最大值
@size(max, min) 被注解的元素的长度必须在指定的范围内
@past 被注解的元素必须是一个过去的日期
@future 被注解的元素必须是一个未来的日期
@pattern(value) 被注解的元素必须符合指定的正则表达式
下面我们以此来在业务中实现
一、对实体类进行校验1、entity@datapublic class user { @notnull(message = "用户id不能为空") private long id; @notnull(message = "用户账号不能为空") @size(min = 6, max = 11, message = "账号长度必须是6-11个字符") private string account; @notnull(message = "用户密码不能为空") @size(min = 6, max = 11, message = "密码长度必须是6-16个字符") private string password; @notnull(message = "用户邮箱不能为空") @email(message = "邮箱格式不正确") private string email;}
2、controller@restcontrollerpublic class usercontroller { @postmapping("/adduser") public void adduser(@requestbody @valid user user) { //业务 }}
3、编写全局统一异常处理import org.springframework.validation.objecterror;import org.springframework.web.bind.methodargumentnotvalidexception;import org.springframework.web.bind.annotation.exceptionhandler;import org.springframework.web.bind.annotation.restcontrolleradvice;import javax.validation.constraintviolation;import javax.validation.constraintviolationexception;import java.util.stream.collectors;/** * 全局异常处理 * * @author master */@restcontrolleradvicepublic class exceptionconfig { /** * 参数为实体类 * @param e * @return */ @exceptionhandler(value = methodargumentnotvalidexception.class) public string handlevalidexception(methodargumentnotvalidexception e) { // 从异常对象中拿到objecterror对象 objecterror objecterror = e.getbindingresult().getallerrors().get(0); // 然后提取错误提示信息进行返回 return objecterror.getdefaultmessage(); } /** * 参数为单个参数或多个参数 * @param e * @return */ @exceptionhandler(value = constraintviolationexception.class) public string handleconstraintviolationexception(constraintviolationexception e) { // 从异常对象中拿到objecterror对象 return e.getconstraintviolations() .stream() .map(constraintviolation::getmessage) .collect(collectors.tolist()).get(0); }}
然后我们使用apipost测试
二、针对单个参数进行校验import org.springframework.validation.annotation.validated;import org.springframework.web.bind.annotation.getmapping;import org.springframework.web.bind.annotation.postmapping;import org.springframework.web.bind.annotation.restcontroller;import javax.validation.constraints.notnull;@restcontroller@validatedpublic class testcontroller { @getmapping("/test") public void test(@notnull(message = "id不能为空") integer id) { }}
然后我们使用apipost测试
三、分组校验场景:在新增时我们需要id为空,但修改时我们又需要id不为空,总不可能搞两个类吧,这时候分组校验的用处就来了
1、entityimport lombok.data;import javax.validation.constraints.email;import javax.validation.constraints.notnull;import javax.validation.constraints.size;@datapublic class user { public interface insert{ } public interface update{ } @notnull(message = "用户id不能为空",groups = update.class) @null(message = "用户id必须为空",groups = integer.class) private long id; private string account; private string password; private string email;}
2、controller@postmapping("/add")public void add(@requestbody @validated(user.insert.class) user user) {}
添加时就用user.insert.class,修改时就用user.update.class
四、自定义分组校验场景:当type为1时,需要参数a不为空,当type为2时,需要参数b不为空。
1、entityimport com.example.demo.provider.customsequenceprovider;import lombok.data;import org.hibernate.validator.group.groupsequenceprovider;import javax.validation.constraints.notempty;import javax.validation.constraints.pattern;@data@groupsequenceprovider(value = customsequenceprovider.class)public class customgroup { /** * 类型 */ @pattern(regexp = "[a|b]" , message = "类型不必须为 a|b") private string type; /** * 参数a */ @notempty(message = "参数a不能为空" , groups = {whentypeisa.class}) private string parama; /** * 参数b */ @notempty(message = "参数b不能为空", groups = {whentypeisb.class}) private string paramb; /** * 分组a */ public interface whentypeisa { } /** * 分组b */ public interface whentypeisb { }}
2、customsequenceproviderimport com.example.demo.controller.customgroup;import org.hibernate.validator.spi.group.defaultgroupsequenceprovider;import java.util.arraylist;import java.util.list;public class customsequenceprovider implements defaultgroupsequenceprovider<customgroup> { @override public list<class<?>> getvalidationgroups(customgroup form) { list<class<?>> defaultgroupsequence = new arraylist<>(); defaultgroupsequence.add(customgroup.class); if (form != null && "a".equals(form.gettype())) { defaultgroupsequence.add(customgroup.whentypeisa.class); } if (form != null && "b".equals(form.gettype())) { defaultgroupsequence.add(customgroup.whentypeisb.class); } return defaultgroupsequence; }}
3、controller@postmapping("/add")public void add(@requestbody @validated customgroup user) {}
五、自定义校验虽然官方提供的校验注解已经满足很多情况了,但还是无法满足我们业务的所有需求,比如校验手机号码,下面我就以校验手机号码来做一个示例。
1、定义校验注解@target({elementtype.field})@retention(retentionpolicy.runtime)@constraint(validatedby = phonevalidator.class)public @interface phone { string message() default "手机号码格式有误"; class<?>[] groups() default {}; class<? extends payload>[] payload() default {};}
注:groups和payload是必须要写的,constraint是使用哪个类来进行校验。
2、实现注解import javax.validation.constraintvalidator;import javax.validation.constraintvalidatorcontext;import java.util.regex.pattern;/** * @author master */public class phonevalidator implements constraintvalidator<phone, object> { @override public boolean isvalid(object telephone, constraintvalidatorcontext constraintvalidatorcontext) { string pattern = "^1[3|4|5|6|7|8|9]\\d{9}$"; return pattern.matches(pattern, telephone.tostring()); }}
最后直接用到参数前面或者实体类变量上面即可。
六、嵌套校验当某个对象中还包含了对象需要进行校验,这个时候我们需要用嵌套校验。
@datapublic class testaa { @notempty(message = "id不能为空") private string id; @notnull @valid private job job; @data public class job { @notempty(message = "content不能为空") private string content; }}
七、快速失败spring validation默认会校验完所有字段,然后才抛出异常。可以通过配置,开启fali fast模式,一旦校验失败就立即返回。
import org.hibernate.validator.hibernatevalidator;import org.springframework.context.annotation.bean;import org.springframework.context.annotation.configuration;import javax.validation.validation;import javax.validation.validator;import javax.validation.validatorfactory;@configurationpublic class failfastconfig { @bean public validator validator() { validatorfactory validatorfactory = validation.byprovider(hibernatevalidator.class) .configure() // 快速失败模式 .failfast(true) .buildvalidatorfactory(); return validatorfactory.getvalidator(); }}
注意事项springboot 2.3.x 移除了validation依赖需要手动引入依赖。
以上就是springboot参数怎么校验的详细内容。
其它类似信息

推荐信息