天天看點

PatternSyntaxException: Dangling meta character ‘*‘ near index 8

背景

上司們需要檢視一些彙總資料,這些彙總資料可從離線數倉平台查詢得到,而企微是一個比較好的企業内部通訊工具。

基于此,現在全職負責(一個人負責前端,後端,測試,小部分産品設計)的報表平台,具備功能點:Impala資料推送到企微。

頁面設計大緻如下:

PatternSyntaxException: Dangling meta character ‘*‘ near index 8
PatternSyntaxException: Dangling meta character ‘*‘ near index 8

問題

因為另外一個任務執行時間比較久,故而想知道資料源某個表的數量級,然後把這個數字以可視化的方式發到自己的企微。故而在來源處修改上面的SQL為:

select count(*) from ods.aaa      

點選自動生成名額,把上面這個SQL語句的查詢字段自動填充到企微發送模版裡面,得到:​

​{count(*)}​

本地測試,繼續運作,突然報錯:

ERROR c.x.c.a.b.d.b.JdbcDataProvider- jdbc execAutoWork impala-2-target error: {}
java.util.regex.PatternSyntaxException: Dangling meta character '*' near index 8
\{count(*)}
        ^
  at com.xy.cloudiview.autojob.business.dataprovider.business.TargetProvider.execAutoWorkTo(TargetProvider.java:58)
  at com.xy.cloudiview.autojob.business.dataprovider.business.JdbcDataProvider.execAutoWork(JdbcDataProvider.java:180)
  at com.xy.cloudiview.autojob.business.service.DataProviderService.execAutoWork(DataProviderService.java:194)
  at com.xy.cloudiview.autojob.controller.AutoJobController.execAutoWork(AutoJobController.java:33)      

排查

對應的代碼片段:

public JSONObject execAutoWorkTo(Map query, List<Map<String, Object>> datalist) {
    if (CollectionUtils.isEmpty(datalist)) {
        return null;
    }
    String jobName = query.get("jobName") + "";
    // 取使用者limit數和限制條數的較小值
    int num = Math.min(datalist.size(), targetNum);
    List<Map<String, Object>> mapResultList = datalist.subList(0, num);
    String sendMsg = query.get("targetTemplate") + "";
    List<String> targetList = StringUtil.getMatchValue(sendMsg);
    StringBuilder finalMsg = new StringBuilder();
    for (Map<String, Object> mapResult : mapResultList) {
        for (String target : targetList) {
            Object obj = mapResult.get(target);
            sendMsg = sendMsg.replaceAll("\\{" + target + "}", String.valueOf(obj));
        }
        finalMsg.append(sendMsg).append(";");
    }
}      

斷點調試,再現問題:

PatternSyntaxException: Dangling meta character ‘*‘ near index 8

幾乎也不需要Google,原因很顯然。因為程式實作邏輯是:對企微模版,即需要發送的内容,進行替換時使用​

​replaceAll()​

​​方法,即使用正規表達式實作替換,報錯PatternSyntaxException,因為有正則保留字元​

​*​

​。

解決

問題已然定位。

如何解決呢?

前面提到,需要實作的功能已經說的很清楚(産品經理角色提出的需求),但是産品在設計這個功能時,很大機率上不會意識到使用者輸入的SQL語句裡面會出現​

​count(*)​

​​(并且沒有加上​

​as cnt​

​别名),也不知道程式員在實作這個功能時,會用到正規表達式全局比對替換。

現在的處境,隻有我一個人在負責這個産品,我作為一個所謂全棧工程師,要如何解決這種潛在問題。

一開始,想着從使用者界面(前端使用React Ant Design實作)入口,限制使用者輸入正則保留字元,即加上rules校驗,不允許使用者輸入保留字元。使用者體驗不是很好?保留字元有哪些呢?

差一點走偏。。。

從後端來實作。解決方案很簡單,當然也不是一蹴而就想到:

sendMsg = sendMsg.replace("{" + target + "}", String.valueOf(obj));      

參考