美文网首页
巧用Spring Expression(SpEL)做动态校验

巧用Spring Expression(SpEL)做动态校验

作者: 清风_81d9 | 来源:发表于2019-05-17 16:28 被阅读0次

    Spring Expression是Spring Framework的一个组件,有时候也管它叫Spring Expression Language,所以简称就成了SpEL,你也可以管它叫Spring表达式。

    它能做什么呢?

    简单地说, 就是能将一个带有变量的字符串解析为完整的String字符串,当然也可以是其他类型,比如int,long,或者最常用的boolean类型,说它最常用,是因为boolean类型是可以直接改变业务逻辑的,下面会有实例。

    不多说,直接说说如何实现动态校验。

    假定前端发送一个保险订单Order到后端,由于保险订单的特殊性,该订单中一般还有用户的信息和保险产品的信息,如果保的是车,还有车辆的信息,那么问题来了,产品说,当订单中车辆是品牌BrandA时,车辆的经销商编码不能为空,当保险产品ProductA时,年龄必须是18-60岁,等等,这些可能是产品在上线之前确定的需求,上线之后可能会突然说,当品牌为BrandB时,兑换码不能为空,作为开发,你会怎么办?

    - if-esle的解决方案,自然拿不上台面的,也解决不了问题,因为你今天增加了这个条件,明天产品一定会提出其他的条件;

    - 策略模式听起来很高大上,但策略的数量一般都是在编码时已经确定的,是需要代码扩展的,扩展完,还需要发版;

    - 动态校验是我目前(加个时间限制吧,也许将来有更好的)想到的最佳方案,具体怎么做呢?

    其实品牌和保险产品,以及经销商编码、年龄和兑换码都是该订单的字段,这个维度可以扩展到该类所定义的所有字段,包括继承自父类的,可以将规则列表总结如下:

    上述表中的规则已经不是简单的需要在开始时编写的代码,而是发版后在管理平台编辑的规则,该规则可以任意添加、删除和修改。

    下面是解析的代码:

    StandardEvaluationContext context = new StandardEvaluationContext();

    context.setVariable(“o”,order);

    List result = new ArrayList<>();

    ExpressionParser parser = new SpelExpressionParser();

    try {

      rules(rule -> {

        Expression preExpression =parser.parseExpression(rule.getPrerequisite());

        if(preExpression.getValue(context,Boolean.class)){

          Expression postExpression =parser.parseExpression(rule.getRequirement());

          if(!postExpression.getValue(context,Boolean.class)){

            result.add(rule.getValidationMsg().getError());

          }

        }

      });

    } catch(Exception e){

      e.printStackTrace();

    }

    - rules是针对该订单所设定的规则,如果你觉得rules每次从数据库中获取性能不好,可以实现你自己的缓存策略,有优化的空间;

    - result存的就是错误消息列表,空表示没有触发任何错误;

    - ExpressionParser和StandardEvaluationContext便是Spring Expression的大杀器,其中context字面意思理解下就差不多了,上下文,同样的规则在不一样的上下文中解析出来的结果自然是不一样的,context中我们放置了一个变量o,即订单,如果你的上下文中有多个变量,尽管往里面扔,解析器parser是可以定义为static,每次实例化是没必要的,这里是为了大家好理解直接定义成了局部变量。

    上述例子中,是将一个待解析的字符串解析为boolean类型直接用于判断,事实上,也可以解析为String类型,比如要访问一个形如

    https://stackoverflow.com/questions/:id

    的网页,可以将该字符串写成如下形式:

    ‘https://stackoverflow.com/questions/' + #article.getId()

    同样的代码只需要改变setVariable,将article的变量放进去,同时在parseExpression方法中指定返回类型为String.class,返回值就是一个真正的可被访问的URL。

    其实笔者也多次处理过使用freemarker处理模板文件,技术非常类似,但很多人总以为是生成html的,其实都可以活用,为啥不是xml,为啥不是email,为啥不是格式合同?

    活用、巧用才会有创新。

    相关文章

      网友评论

          本文标题:巧用Spring Expression(SpEL)做动态校验

          本文链接:https://www.haomeiwen.com/subject/sdtfyqtx.html