1. 程式人生 > >spring boot專案實戰之工具篇(ognl)

spring boot專案實戰之工具篇(ognl)

當解析複雜的json結構時,ognl是一個很方便的工具,實現基於圖對屬性的訪問,類似於以(user.name | user.depart[0])的方式獲取json內的巢狀物件欄位值。

請看以下示例,你將對ognl的作用有一個更清晰的理解:

String json = "{\"user\":{\"name\":\"123\",\"depart\":[1,2]}}";
Map<?, ?> map = JacksonHelper.fromJson(json, Map.class);
OgnlWrapper ognlWrapper = new OgnlWrapper(map);
System.err.println(ognlWrapper.get("user.name"));
System.err.println(ognlWrapper.get("user.depart.size"));
System.err.println(ognlWrapper.get("user.depart[0]"));
  • 內部物件的普通欄位可以通過user.name這樣的方式獲取
  • 內部物件的集合欄位可以通過user.depart.size獲取其集合長度
  • 內部物件的集合欄位可以通過user.depart[0]的方式獲取對應下標出的值

通常json物件解析可以通過一層一層的轉換為map來實現,但如果巢狀物件層次有3層以上,內部結構較複雜,那實現起來就很繁瑣,程式碼冗長,這種情況下使用ognl能讓程式碼精簡很多。

1、新增maven依賴

<!-- ognl -->
<dependency>
    <groupId>ognl</groupId>
    <artifactId>ognl</artifactId>
    <version>3.2.1</version>
</dependency>

2、OgnlWrapper

@SuppressWarnings("unchecked")
public class OgnlWrapper {

    private static Logger logger = LoggerFactory.getLogger(OgnlWrapper.class);

    private static ObjectMapper om = new ObjectMapper();
    private Map<String, Object> payload;

    public OgnlWrapper(Map<String, Object> playload) {
        Validate.notEmpty(playload, "can not construct with none playload!");
        this.payload = playload;
    }


    public OgnlWrapper(Object playload) {
        this.payload = om.convertValue(playload, Map.class);
    }

    public <T> T get(String expression) {
        try {
            return (T) Ognl.getValue(expression, this.payload);
        } catch (OgnlException e) {
            logger.trace(String.format("get value with expression:[%s] due to error, return null instead of",
                expression), e);
            return null;
        }
    }

    public Long getLong(String expression) {
        try {
            Object obj = Ognl.getValue(expression, this.payload);
            if (null == obj)
                return null;
            try {
                return Long.parseLong(obj.toString());
            } catch (NumberFormatException nfe) {
                logger.warn(String.format("get value with expression:[%s] due to error, return null. value[%s] cannot be cast to java.lang.Long",
                    expression,
                    obj.toString()));
                return null;
            }
        } catch (OgnlException e) {
            logger.trace(String.format("get value with expression:[%s] due to error, return null instead of",
                expression), e);
            return null;
        }
    }

    public Integer getInt(String expression) {
        try {
            Object obj = Ognl.getValue(expression, this.payload);
            if (null == obj)
                return null;
            try {
                return Integer.parseInt(obj.toString());
            } catch (NumberFormatException nfe) {
                logger.warn(String.format("get value with expression:[%s] due to error, return null. value[%s] cannot be cast to java.lang.Integer",
                    expression,
                    obj.toString()));
                return null;
            }
        } catch (OgnlException e) {
            logger.trace(String.format("get value with expression:[%s] due to error, return null instead of",
                expression), e);
            return null;
        }
    }

    @Override
    public String toString() {
        return String.format("OgnlWrapper[%s]", this.payload.toString());
    }

    public static void main(String[] args) {
        String json = "{\"user\":{\"name\":\"123\",\"depart\":[1,2]}}";
        Map<?, ?> map = JacksonHelper.fromJson(json, Map.class);
        OgnlWrapper ognlWrapper = new OgnlWrapper(map);
        System.err.println(ognlWrapper.get("user.name"));
        System.err.println(ognlWrapper.get("user.depart.size"));
        System.err.println(ognlWrapper.get("user.depart[0]"));
    }
}

3、使用手冊

說明

OgnlWrapper是基於ognl.Ognl類的一個工具類,實現基於圖對屬性的訪問,支援ognl的所有語法。 提供三個核心方法:
get();
getLong(); //如果值非long型,將返回null
getInt(); //如果值非int型,將返回null

使用注意

在使用Long longvalue = ognlWrapper.get(“body.payload.page.page_size”); 時出現如下錯誤: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.Integer
解決方法:使用getLong方法
Long longvalue = ognlWrapper.getLong(“body.payload.page.page_size”);

獲取不存在的屬性時返回null,日誌中會列印warn警告日誌。 如:ognlWrapper.getLong(“body.payload[0].childrens[0].childrens.size”); // return null

單個物件

User user = new User(); //設定使用者的相關屬性
//...省略屬性設定
//使用OgnlWrapper
OgnlWrapper ognlWrapper = new OgnlWrapper(user);
String id = ognlWrapper.get("id");//獲取id

//狀態. 請使用基本資料型別的封裝型別
Integer status = ognlWrapper.getInt("status");  
//聯絡資訊中的郵件地址
String email = ognlWrapper.get("contact_info.email");

//獲取一個不存在的屬性
//將返回null
String noexist = ognlWrapper.get("noexist");

//將返回null
noexist = ognlWrapper.get("contact_info.noexist");

對list操作

//將存放使用者的列表資料放到map中 map.put("users",list);
//使用OgnlWrapper獲取使用者列表資料
OgnlWrapper ognlWrapper = new OgnlWrapper(map);

//獲取list大小。如果map未存放list則返回null
Integer size = ognlWrapper.getInt("users.size"); 
if(null == size || 0 == size.intValue())  return ;

//獲取list中第一使用者的使用者id和name 注意:下標從0開始
String id = ognlWrapper.get("users[0].id");
String name = ognlWrapper.get("users[0].name");

//如果索引超出list的大小,將返回null
String nullvalue = ognlWrapper.get("users[9999999].id");    

使用OgnlWrapper獲取屬性值時,請使用物件型別。如int 使用Integer型別。

完整程式碼請參考github內rest-base專案com.onecoderspace.base.util.ognl.OgnlWrapper。
https://github.com/q7322068/rest-base

相關推薦

spring boot專案實戰工具ognl

當解析複雜的json結構時,ognl是一個很方便的工具,實現基於圖對屬性的訪問,類似於以(user.name | user.depart[0])的方式獲取json內的巢狀物件欄位值。 請看以下示例,你將對ognl的作用有一個更清晰的理解: String js

Sping Boot入門到實戰入門Spring Boot屬性配置

git 測試 add 禁用 rop fix ron org set   該篇為Sping Boot入門到實戰系列入門篇的第三篇。介紹Spring Boot的屬性配置。   傳統的Spring Web應用自定義屬性一般是通過添加一個demo.properties配置文件(

Spring Boot簡明教程資料訪問:MyBatis

Spring Boot簡明教程之資料訪問(三):MyBatis 文章目錄 Spring Boot簡明教程之資料訪問(三):MyBatis MyBatis簡介 使用註解進行資料訪問 專案建立 專案目錄

Spring Boot簡明教程資料訪問:JPA(超詳細)

Spring Boot簡明教程之資料訪問(二):JPA(超詳細) 文章目錄 Spring Boot簡明教程之資料訪問(二):JPA(超詳細) 建立專案 Spring Data簡介 JPA簡介 Spring Data 與JP

Spring Boot學習入門Hello World

1.通過Spring Initializr(地址:http://start.spring.io/)生成Spring Boot專案結構 2.匯入Spring Boot專案 pom.xml內容: 3.編寫RESTful API 4.啟動Spring Boot應用 三

Spring Boot 入門基礎

一、前言 Spring Boot 是由 Pivotal 團隊提供的全新框架,其設計目的是用來簡化新 Spring 應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。 本系列以快速入門為主,可當作工具小手冊閱讀

Spring Boot 入門 Web

一、前言 上一篇《Spring Boot 入門之基礎篇(一)》介紹了 Spring Boot 的環境搭建以及專案啟動打包等基礎內容,本篇繼續深入介紹 Spring Boot 與 Web 開發相關的知識。 二、整合模板引擎 由於 jsp 不被 SpringBoot 推薦使用,所以模板引擎主

Spring Boot 學習基礎

該系列並非完全原創,官方文件、作者Spring Boot 是由 Pivotal 團隊提供的全新框架,其設計目的是用來簡化新 Spring 應用的初始搭建以及開發過程。該框架使用了特定的方式來進行配置,從而使開發人員不再需要定義樣板化的配置。一、環境搭建建立一個Maven專案,

Spring Boot 學習 Web

該系列並非完全原創,官方文件、作者一、前言上一篇《Spring Boot 入門之基礎篇(一)》介紹了 Spring Boot 的環境搭建以及專案啟動打包等基礎內容,本篇繼續深入介紹 Spring Boot 與 Web 開發相關的知識。二、整合模板引擎由於 jsp 不被 Spr

資料庫redis2—— redis配置檔案,常用命令,效能測試工具

redis配置 如果你是找網上的其他教程來完成以上操作的話,相信你見過有的啟動命令是這樣的:   啟動命令帶了這個引數:redis.windows.conf,由於我測試環境是windows平臺,所以是這個,有的是redis.conf。顧名思義,redis.conf就是配置檔案,然後啟動時加

Spring boot+Security OAuth2 爬坑日記2授權碼模式升級

1. 開發環境和本專案用到的框架 接著上一篇Spring boot+Security OAuth2 爬坑日記(1)授權碼模式部落格中的內容,上篇介紹了基本的開發環境,系統以及jdk版本等,本篇再來詳細介紹下專案中用到的框架和相關類庫。 框架/類庫/資

spring boot 專案中hanlp的配置可增加自定義詞典

pom.xml檔案中增加: com.hankcs hanlp system ${project.basedir}/src/main/resources/lib/hanlp-1.5.2.jar 字典和模型檔案在專案中的位置,其中包括自定義詞典: data資料夾在專案中的位置:

UML工具Win10無法使用VGAPlayer播放asf格式與VGA課件的解決辦法

      軟體工程學習完之後的專案是UML,在學習這個UML視訊時發現文件裡有兩個檔案,一個是asf格式的,一個是vga格式的,在經過志帥師哥的指導後才曉得原來是要兩個檔案一起開啟看的,但當下載下來VGAPlayer程式後發現我下載的播放器無法使用,然後就從師哥和小夥

Spring Boot 整合Mybatis Mapper外掛自動生成XML及Mapper程式碼

pom檔案 主要程式碼 <dependencies> <dependency> <groupId>mysql</groupId> <artifactI

spring boot專案實戰:跨域問題解決

背景 前後端分離架構,前端anglerjs,後端spring boot,使用shiro作為許可權控制,已配置通用跨域請求支援。 前端呼叫介面時部分情況正常,部分情況出現跨域請求不支援情況,錯誤資訊如下: Response to preflight requ

SpringCloud實戰初級入門spring cloud config搭建git配置中心

目錄 1.環境介紹 2.配置中心 2.1 建立工程 2.2 修改配置檔案 2.3 在github中加入配置檔案 2.3 修改啟動檔案 3. 訪問配置中心 1.環境介紹 上一篇文章中,我們介紹瞭如何利用eureka註冊中心釋出服務以及呼叫服務

Spring Cloud實戰初級入門— 利用Hystrix實現服務熔斷與服務監控

close 哪些 cati status netflix turn 遠程倉庫 monitor mri 目錄 1.環境介紹 2.服務監控 2.1 加入依賴 2.2 修改配置文件 2.3 修改啟動文件 2.4 監控服務 2.5 小結 3. 利用hystrix實現消費服務熔斷

spring boot專案實戰-集合操作

集合操作在web應用開發中也是很常見的,目前也有一些比較方便的工具如java.util.Collections、org.apache.commons.collections.CollectionUtils等,但是根據自己公司專案開發中的具體情況提取一套更何用的集

spring boot 學習(七)小工具:表單重複提交

註解 + 攔截器:解決表單重複提交 前言 學習 Spring Boot 中,我想將我在專案中新增幾個我在 SpringMVC 框架中常用的工具類(主要都是涉及到 Spring AOP 部分知識)。比如,表單重複提交,?秒防重新整理,全域性異常捕抓類,IP

Spring+SpringMVC+MyBatis+easyUI整合基礎專案簡述及技術選型介紹

萌芽階段 很久之前就開始打算整理一下自己的技術部落格了,由於各種原因(藉口總是可以找到的),實在抽不出時間所以計劃一直處於擱置狀態,一直只是心底的一顆小萌芽,日復一日的悠悠歲月如同手中緊抓的沙子,無聲無息的流失,不過這顆小生命也在我渴望與期待的澆灌下不斷的長大。