SpEL 實例

SpEl 實例

  • 基於 Spring 解析
@RestController
@RequestMapping("/spel")
@Slf4j
public class SpELController implements ApplicationRunner {
    /**
     *  1)字面值
     */
    @Value("#{ 'zxd' }")
    private String name;
    @Value("#{ 29 }")
    private int age;
    @Value("#{ true }")
    private boolean male;
    @Value("#{ 15505883728L }")
    private long phone;

    /**
     * org.springframework.beans.factory.config.BeanExpressionContext
     *  2)對象屬性
     */
    @Value("#{ beanFactory.beanDefinitionNames }")
    private List<String> beanDefinitionNames;

    /**
     *  3)實例方法調用
     */
    @Value("#{ 'zxd'.length() }")
    private int length;

    /**
     *  4)關係操作符
     */
    @Value("#{ 2>=1 }")
    private boolean operator;
    @Value("#{ true or false}")
    private boolean or;
    @Value("#{ true and false}")
    private boolean and;
    @Value("#{ !true }")
    private boolean not;
    @Value("#{ (1+2)*3/4-5 }")
    private int plus;
    @Value("#{ 7%3 }")
    private int mod;

    /**
     *  5)靜態屬性
     */
    @Value("#{ T(java.lang.Math).PI }")
    private double pi;

    /**
     * 6)構造函數
     */
    @Value("#{ new org.zxd.spring5.springmvc.controller.User('zxd',29)}")
    private User user;

    /**
     *  7)靜態方法調用
     */
    @Value("#{ T(org.zxd.spring5.springmvc.controller.User).of('prince',28) }")
    private User staticUser;

    /**
     *  8)#root 永遠表示根對象
     */
    @Value("#{ #root }")
    private BeanExpressionContext beanExpressionContext;

    /**
     *  9)#this 永遠表示當前評估的對象
     */
    @Value("#{ {1,3,5,7}.?[#this>2] }")
    private List<Integer> gt2;

    /**
     *  10)使用 beanResolver 讀取名稱爲 spELController 的 bean
     *  使用 @ 讀取實例 bean,使用 & 讀取工廠 bean
     */
    @Value("#{ @jacksonObjectMapper }")
    private ObjectMapper objectMapper;

    /**
     *  11)三元操作符
     */
    @Value("#{ true?'trueExpr':'falseExpr' }")
    private String expr;

    /**
     *  12)埃維爾斯操作符
     */
    @Value("#{ null?:'defaultValue' }")
    private String unkonwn;

    /**
     *  13)安全導航操作符
     */
    @Value("#{ null?.field }")
    private String safeNull;

    /**
     *  14)集合選擇
     *  .?[]    從集合中篩選元素,返回一個新的集合
     *  .^[]    獲取第一個匹配的元素
     *  .$[]    獲取最後一個匹配的元素
     */
    @Value("#{ {'java','maven','hello'}.^[#this.length()==5] }")
    private String firstMatch;
    @Value("#{ {'java','maven','hello'}.$[#this.length()==5] }")
    private String lastMatch;

    /**
     *  15)集合投影
     */
    @Value("#{ {'java','maven','hello'}.![#this.length()] }")
    private List<Integer> projection;

    /**
     *  16)表達式模板
     */
    @Value("random number is #{ T(java.lang.Math).random() }")
    private String template;

    @GetMapping("/validate")
    public void validate() {
        assertEquals("zxd", name);
        assertEquals(29, age);
        assertTrue(male);
        assertEquals(15505883728L, phone);
        assertNotNull(beanDefinitionNames);
        assertEquals(3, length);
        assertTrue(operator);
        assertTrue(or);
        assertFalse(and);
        assertFalse(not);
        assertEquals(-3, plus);
        assertEquals(1, mod);
        assertEquals(Math.PI, pi, 0);
        assertEquals("zxd", user.getName());
        assertEquals(29, user.getAge());
        assertEquals("prince", staticUser.getName());
        assertEquals(28, staticUser.getAge());
        assertNotNull(beanExpressionContext);
        assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(3, 5, 7), gt2));
        assertNotNull(objectMapper);
        assertEquals("trueExpr", expr);
        assertEquals("defaultValue", unkonwn);
        assertNull(safeNull);
        assertEquals("maven", firstMatch);
        assertEquals("hello", lastMatch);
        assertTrue(CollectionUtils.isEqualCollection(Lists.newArrayList(4, 5, 5), projection));
    }

    /**
     *  查看容器中註冊的所有 bean及其類型
     */
    @Autowired
    private AnnotationConfigServletWebServerApplicationContext applicationContext;
    @Override
    public void run(ApplicationArguments args) throws Exception {
        log.info("applicationContext {}", applicationContext.getClass());
        Stream.of(applicationContext.getBeanDefinitionNames()).forEach(name -> {
            log.info("{}==={}", name, applicationContext.getBean(name).getClass());
        });
    }
}
  • 自定義解析
public class SpelEvaluate {

    @Test
    public void evaluate() {
        // SpelExpressionParser 是線程安全的,可複用
        final SpelExpressionParser spelExpressionParser = new SpelExpressionParser();
        final String expressionString = "#{name}";
        final ParserContext context = ParserContext.TEMPLATE_EXPRESSION;
        final Expression rootExpress = spelExpressionParser.parseExpression(expressionString, context);

        final User user = User.of("zxd", 29);
        final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(user);
        // 基於 evaluationContext 的 root 執行計算
        final String name = rootExpress.getValue(evaluationContext, String.class);
        // 基於自定義 root 執行計算
        final String fromRoot = rootExpress.getValue(user, String.class);
        assertEquals(name, fromRoot);

        /**
         *  直接以 # 開頭的表達式表示從變量映射中讀取,而不是從根開始解析
         *  #root 表示根對象,#this 表示當前解析對象【適用於集合操作】
         */
        final Expression rootName = spelExpressionParser.parseExpression("#root.name");
        final String root = rootName.getValue(evaluationContext, String.class);

        evaluationContext.setVariable("zxd", user);
        final Expression variableName = spelExpressionParser.parseExpression("#zxd.name");
        final String variable = variableName.getValue(evaluationContext, String.class);
        assertEquals(root, variable);
    }

    @Value(staticConstructor = "of")
    private static class User {
        private String name;
        private int age;
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章