温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Spring boot怎么实现超灵活的注解式数据校验

发布时间:2021-12-02 11:46:17 来源:亿速云 阅读:214 作者:iii 栏目:开发技术

本篇内容主要讲解“Spring boot怎么实现超灵活的注解式数据校验”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Spring boot怎么实现超灵活的注解式数据校验”吧!

通过切面,实现超灵活的注解式数据校验

在企业系统的开发中,用户表单输入的场景是会经常遇见的,如何让数据校验脱离于业务代码逻辑,谁也不想在逻辑代码里对字段逐一判断。。。。

Spring MVC的校验方式

在使用Spring MVC时的时候,直接使用hibernate-validator的注解,如下:

public class User {     private Long id;     @NotBlank(message = "name不能为空")     @Size(min = 5, max = 10, message = "字符在5到10个")     private String name;     private String des;     @NotNull     @Max(value = 3, message = "type 参数错误")     @Min(value = 0, message = "type 参数错误")     private Integer type;     @Min(value = 0, message = "参数错误, limit必须大于或等于0")       private int limit;     @Pattern(regexp = "^(true|false)$", message = "参数错误, 参数isActive只能是true或者false")     private String flag;     // setters and getters

然后将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  // spring boot 配置类 public class RequestParamValidAspect {     private final ValidatorFactory factory = Validation.buildDefaultValidatorFactory();     private final ExecutableValidator methodValidator = factory.getValidator().forExecutables();     private final Validator beanValidator = factory.getValidator();     private <T> Set<ConstraintViolation<T>> validMethodParams(T obj, Method method, Object [] params){         return methodValidator.validateParameters(obj, method, params);     }     private <T> Set<ConstraintViolation<T>> validBeanParams(T bean) {         return beanValidator.validate(bean);     }     @Pointcut("execution(* com.jiaobuchong.commodity.service.*.*(..))")     public void soaServiceBefore(){}     /* * 通过连接点切入 */     @Before("soaServiceBefore()")     public void twiceAsOld1(JoinPoint point) {         //  获得切入目标对象         Object target = point.getThis();         // 获得切入方法参数         Object [] args = point.getArgs();         // 获得切入的方法         Method method = ((MethodSignature)point.getSignature()).getMethod();         // 校验以基本数据类型 为方法参数的         Set<ConstraintViolation<Object>> validResult = validMethodParams(target, method, args);         Iterator<ConstraintViolation<Object>> violationIterator = validResult.iterator();         while (violationIterator.hasNext()) {             // 此处可以抛个异常提示用户参数输入格式不正确             System.out.println("method check---------" + violationIterator.next().getMessage());         }         // 校验以java bean对象 为方法参数的          for (Object bean : args) {             if (null != bean) {                 validResult = validBeanParams(bean);                 violationIterator = validResult.iterator();                 while (violationIterator.hasNext()) {             // 此处可以抛个异常提示用户参数输入格式不正确                     System.out.println("bean check-------" + violationIterator.next().getMessage());                 }             }         }     } }

具体的Service

// DemoService.java public interface DemoService {     void one(@NotNull(message = "不能为null") Integer a, @NotBlank String b);     void two(@NotNull(message = "paramsVo不能为null") ParamsVo paramsVo,              @NotNull(message = "go不能为null") String go); } // ParamsVo.java public class ParamsVo {     @NotBlank(message = "不能为空")     private String name;     @NotBlank     @Length(min = 2, max = 20, message = "不可以为空,最多20个字")     private String desc;     @NotNull     @Valid  // 需要加上@Valid注解,不然不会校验到Img对象     private List<Img> imgList;     @NotNull(message = "length不能为null")     @Range(min = 3, max = 100, message = "长度范围3-100")     private Integer length;     // omitted other code } public class Img {     @NotNull(message = "img id 不能为null")     private Long id;     @NotBlank(message = "img name 不能为空")     private String name;     // omitted other code }

运行DemoService:

@Autowired      private DemoService demoService;     @Test     public void testGo() {         demoService.one(null, "");         ParamsVo paramsVo = new ParamsVo();         List<Img> list = new ArrayList<>();         Img img = new Img();         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的校验功能还强大了,

// Spring MVC中对下面这样的校验是没有作用的 void one(@NotNull(message = "不能为null") Integer a, @NotBlank String b);

经过一番改造后,啥都支持了。而且独立于业务逻辑,维护和新增校验都很方便,代码量也变少了!

Spring boot aop注解数据权限校验

注解类

@Retention(RetentionPolicy.RUNTIME) public @interface DataAuthValid {         //位置     public int index() default 0;          //字段   id     //public String id() default "id";          //字段   id     public String orgId() default "org_id";          //mapper     @SuppressWarnings("rawtypes")     public Class<? extends Mapper> mapper(); }

AOP切面

@Aspect @Component @Order(1) public class DataAuthAop {      private static String types = "java.lang.String,java.lang.Long,long";         @Before("@annotation(dataAuth)")     public void beforeMethod(JoinPoint point,DataAuthValid dataAuth) throws Exception {                  HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();         Map<String, Object> payloadMap = (Map<String, Object>) request.getAttribute("payloadMap");         Long companyid = Long.parseLong(payloadMap.get("companyid")+"");         if(companyid != 1) {             Object[] args = point.getArgs();             Object obj = args[dataAuth.index()];             String ids = null;             String typeName = obj.getClass().getTypeName();             if(types.contains(typeName)) {                 ids = obj + "";             }else {                 Field[] fields = obj.getClass().getDeclaredFields();                 for (Field f : fields) {                     f.setAccessible(true);                     if("id".equals(f.getName())) {                         Long id = (Long) f.get(obj);                         ids = id + "";                     }                 }             }             String[] idArr = ids.split(",");             for (String id : idArr) {                 Class cla = dataAuth.mapper();                 Mapper mapper = (Mapper) SpringBeanFactoryUtils.getApplicationContext().getBean(cla);                 Object object = mapper.selectByPrimaryKey(Long.valueOf(id));                 Field field = obj.getClass().getDeclaredField(dataAuth.orgId());                 field.setAccessible(true);                 Long orgId = (Long)field.get(obj);                 if(!companyid.equals(orgId)) {                     throw new RuntimeException();                 }             }         }     } }

使用

Spring boot怎么实现超灵活的注解式数据校验

到此,相信大家对“Spring boot怎么实现超灵活的注解式数据校验”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI