Spring boot怎么实现超灵活的注解式数据校验
导读:本文共4069字符,通常情况下阅读需要14分钟。同时您也可以点击右侧朗读,来听本文内容。按键盘←(左) →(右) 方向键可以翻页。
摘要: 通过切面,实现超灵活的注解式数据校验在企业系统的开发中,用户表单输入的场景是会经常遇见的,如何让数据校验脱离于业务代码逻辑,谁也不想在逻辑代码里对字段逐一判断。。。。Spring MVC的校验方式在使用Spring MVC时的时候,直接使用hibernate-validator的注解,如下:publicclassUser{privateLongid;@Not... ...
目录
(为您整理了一些要点),点击可以直达。通过切面,实现超灵活的注解式数据校验
在企业系统的开发中,用户表单输入的场景是会经常遇见的,如何让数据校验脱离于业务代码逻辑,谁也不想在逻辑代码里对字段逐一判断。。。。
Spring MVC的校验方式
在使用Spring MVC时的时候,直接使用hibernate-validator的注解,如下:
publicclassUser{privateLongid;@NotBlank(message="name不能为空")@Size(min=5,max=10,message="字符在5到10个")privateStringname;privateStringdes;@NotNull@Max(value=3,message="type参数错误")@Min(value=0,message="type参数错误")privateIntegertype;@Min(value=0,message="参数错误,limit必须大于或等于0")privateintlimit;@Pattern(regexp="^(true|false)$",message="参数错误,参数isActive只能是true或者false")privateStringflag;//settersandgetters
然后将User对象作为Controller的参数,交给Spring MVC去帮你校验。
通过切面实现自己的注解式数据校验
这是一个SOA的微服务应用,没有controller和Spring MVC,当然也没有所谓的容器(Tomcat、Jetty),对于来自于client的调用,也要进行参数校验。继续基于hibernate-validator,
参看validator的官方文档
引入依赖:
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator-cdi</artifactId><version>5.4.1.Final</version></dependency><dependency><groupId>org.glassfish</groupId><artifactId>javax.el</artifactId><version>3.0.1-b08</version></dependency>
这里需要引入spring boot和aop的一些知识点,自行去网上google吧。我直接上代码了,谁叫我是代码的搬运工。
定义一个切面:
@Aspect//一个切面@Configuration//springboot配置类publicclassRequestParamValidAspect{privatefinalValidatorFactoryfactory=Validation.buildDefaultValidatorFactory();privatefinalExecutableValidatormethodValidator=factory.getValidator().forExecutables();privatefinalValidatorbeanValidator=factory.getValidator();private<T>Set<ConstraintViolation<T>>validMethodParams(Tobj,Methodmethod,Object[]params){returnmethodValidator.validateParameters(obj,method,params);}private<T>Set<ConstraintViolation<T>>validBeanParams(Tbean){returnbeanValidator.validate(bean);}@Pointcut("execution(*com.jiaobuchong.commodity.service.*.*(..))")publicvoidsoaServiceBefore(){}/**通过连接点切入*/@Before("soaServiceBefore()")publicvoidtwiceAsOld1(JoinPointpoint){//获得切入目标对象Objecttarget=point.getThis();//获得切入方法参数Object[]args=point.getArgs();//获得切入的方法Methodmethod=((MethodSignature)point.getSignature()).getMethod();//校验以基本数据类型为方法参数的Set<ConstraintViolation<Object>>validResult=validMethodParams(target,method,args);Iterator<ConstraintViolation<Object>>violationIterator=validResult.iterator();while(violationIterator.hasNext()){//此处可以抛个异常提示用户参数输入格式不正确System.out.println("methodcheck---------"+violationIterator.next().getMessage());}//校验以javabean对象为方法参数的for(Objectbean:args){if(null!=bean){validResult=validBeanParams(bean);violationIterator=validResult.iterator();while(violationIterator.hasNext()){//此处可以抛个异常提示用户参数输入格式不正确System.out.println("beancheck-------"+violationIterator.next().getMessage());}}}}}
具体的Service
//DemoService.javapublicinterfaceDemoService{voidone(@NotNull(message="不能为null")Integera,@NotBlankStringb);voidtwo(@NotNull(message="paramsVo不能为null")ParamsVoparamsVo,@NotNull(message="go不能为null")Stringgo);}//ParamsVo.javapublicclassParamsVo{@NotBlank(message="不能为空")privateStringname;@NotBlank@Length(min=2,max=20,message="不可以为空,最多20个字")privateStringdesc;@NotNull@Valid//需要加上@Valid注解,不然不会校验到Img对象privateList<Img>imgList;@NotNull(message="length不能为null")@Range(min=3,max=100,message="长度范围3-100")privateIntegerlength;//omittedothercode}publicclassImg{@NotNull(message="imgid不能为null")privateLongid;@NotBlank(message="imgname不能为空")privateStringname;//omittedothercode}
运行DemoService:
@AutowiredprivateDemoServicedemoService;@TestpublicvoidtestGo(){demoService.one(null,"");ParamsVoparamsVo=newParamsVo();List<Img>list=newArrayList<>();Imgimg=newImg();list.add(img);paramsVo.setImgList(list);paramsVo.setDesc("你");paramsVo.setLength(1);demoService.two(paramsVo,null);}
运行结果:
method check———不能为空
method check———不能为null
method check———go不能为null
bean check——-img name 不能为空
bean check——-不能为空
bean check——-深度范围3-100
bean check——-img id 不能为null
bean check——-不可以为空,最多20个字
这样比Spring MVC的校验功能还强大了,
//SpringMVC中对下面这样的校验是没有作用的voidone(@NotNull(message="不能为null")Integera,@NotBlankStringb);
经过一番改造后,啥都支持了。而且独立于业务逻辑,维护和新增校验都很方便,代码量也变少了!
Spring boot aop注解数据权限校验
注解类
@Retention(RetentionPolicy.RUNTIME)public@interfaceDataAuthValid{//位置publicintindex()default0;//字段id//publicStringid()default"id";//字段idpublicStringorgId()default"org_id";//mapper@SuppressWarnings("rawtypes")publicClass<?extendsMapper>mapper();}
AOP切面
@Aspect@Component@Order(1)publicclassDataAuthAop{privatestaticStringtypes="java.lang.String,java.lang.Long,long";@Before("@annotation(dataAuth)")publicvoidbeforeMethod(JoinPointpoint,DataAuthValiddataAuth)throwsException{HttpServletRequestrequest=((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();Map<String,Object>payloadMap=(Map<String,Object>)request.getAttribute("payloadMap");Longcompanyid=Long.parseLong(payloadMap.get("companyid")+"");if(companyid!=1){Object[]args=point.getArgs();Objectobj=args[dataAuth.index()];Stringids=null;StringtypeName=obj.getClass().getTypeName();if(types.contains(typeName)){ids=obj+"";}else{Field[]fields=obj.getClass().getDeclaredFields();for(Fieldf:fields){f.setAccessible(true);if("id".equals(f.getName())){Longid=(Long)f.get(obj);ids=id+"";}}}String[]idArr=ids.split(",");for(Stringid:idArr){Classcla=dataAuth.mapper();Mappermapper=(Mapper)SpringBeanFactoryUtils.getApplicationContext().getBean(cla);Objectobject=mapper.selectByPrimaryKey(Long.valueOf(id));Fieldfield=obj.getClass().getDeclaredField(dataAuth.orgId());field.setAccessible(true);LongorgId=(Long)field.get(obj);if(!companyid.equals(orgId)){thrownewRuntimeException();}}}}}
使用
</div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
Spring boot怎么实现超灵活的注解式数据校验的详细内容,希望对您有所帮助,信息来源于网络。