中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

列表頁的動態條件搜索

發布時間:2020-07-23 17:21:26 來源:網絡 閱讀:272 作者:jjjssswww 欄目:網絡安全

之前在搞.net的時候,我們可以借助強大的ExpressionTree來解決,之前有一篇是微軟的EntityFramework表達式轉換:Linq to Entity經驗:表達式轉換,是將一種表達式轉換成數據庫組件能夠識別的表達式,只不過那篇沒有涉及到View中的條件而已。頁面動態查詢的最簡單的方法就是解析View中特定的值來得到后臺組件能夠識別的查詢邏輯。
  
  我們期待View中能夠這樣指定條件:
 

<input type="text" name="WHERE.storeName.LIKE" class="form-control"  " />


  它的意思是查詢字段storeName,操作符是like,看起來并不難,但要解決這么幾個問題:

  1.   參數收集問題,表單域的值以什么樣的方式提交到后臺?

  2.   后臺接收參數類型是什么?

  3.   如何將表單域中的條件轉換成數據庫組件能夠識別的條件?


  我們選擇的數據庫組件是mybatis+mysql。個人感覺mybatis在處理動態查詢時比JPA在前期(技術學習前期,即水平還不太夠的時候)要簡單些,也可能是我對JPA的認識還不夠,總感覺mybatis這種拼SQL的方式比較熟悉一些,也比較容易控制。當然它們的定位本身就不同,這里不多討論。基于mybatis我們采用了tk.mybatis這個開源的組件,它的功能非常豐富,分頁,通用mapper,代碼生成等大部分功能都已經包含,大家有興趣可以去搜索。

   注:下面的功能是我的同事完成,這里我做為學習的過程來分享下,可能也有理解不到位的地方,純屬個人學習理解。其中有部分功能未展示出來(比如權限過濾,and or這些分組查詢的支持等),只包含最基本的,每個項目的需求不同以及團隊環境不同可以會有多種實現方式,選擇大家都能接受的就可以了。

  我們再分別看下上面的三個問題怎么解決:

  1.   參數收集問題,表單域的值以什么樣的方式提交到后臺方法?

     一般做頁面查詢時請求數據就兩種方式,get或者post。get一般是在采用了ajax這類技術,post就復雜一些,分為兩種:一種也是采用ajax提交到后臺,一種是表單的提交。這里呢,由于我們采用了angularjs,所以很顯然只能采用ajax提交,如果查詢條件多,可采用ajax的post。由于上面貼的代碼片段顯示條件的name是動態的,所以我們不可能定義一個具體的后臺的業務Model對前臺的條件,比如有name,email,phone等等,所以我們采用將表單域整個序列化后的結果傳遞到后臺。

     

列表頁的動態條件搜索

                 var requestData = $("#"+options.searchFormId+"").serialize();                     var url = listUrl+"?"+requestData+"&pageNum="+$scopeLocal.pageRequest.pageNum;
                     $.ajax({
                         type : "POST",
                         url : url,
                         dataType : 'json',
                         async : false,
                         beforeSend:options.beforeSend,
                         error:options.error,
                         success : function(data) {
                             $scopeLocal.pageResponse = data;
                             $scopeLocal.content=data.list;
                             options.callback($scopeLocal,data);
                         }
                     });

列表頁的動態條件搜索


  2:參數類型是什么?
     如果是表單提交方式,我們可以采用HttpServletRequest這個對象來接收所有表單域的值,但上一步我們采用的提交方式并非表單自身的提交,而是ajax的提交,ajax的請求,是不識別HttpServletRequest這個參數類型的,為此我們需要定義一個自定義的公共的對象來接收我們動態View中指定的條件,這里就有個我們的SearchModel,它包含如下內容:

  • 分頁信息,當前頁,頁數據大小

  • 搜索條件信息集合List<SearchFilter>,一堆我們自己定義的條件,主要包含字段名稱,操作符以及值,這里是本文的重點。

  • 轉換為SQL的邏輯

     SearchFilter:

列表頁的動態條件搜索

  public final class SearchFilter implements Serializable {    private String propertyName;    private Object value;    private Operator operator;    private String orGroup;

列表頁的動態條件搜索

      SearchModel:

public class SearchModel implements Serializable {    private List<SearchFilter> searchFilters;    private int pageNum = 1;    private int pageSize = 10;

 

     上面搜索條件的信息,我們需要從View中獲取,這里應用HandlerMethodArgumentResolver來解決,它只有兩個方法:

  • 判斷是否是支持的參數類型

boolean supportsParameter(MethodParameter parameter);

       這個方法實現比較簡單,只需要判斷下當前的參數類型是否是指定的類型即可:

@Override    public boolean supportsParameter(MethodParameter parameter) {
         Class<?> parameterType = parameter.getParameterType();         return SearchModel.class.isAssignableFrom(parameterType);
    }

 

  • 解析數據的詳細過程

Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception;

      這個方法是核心,之前有提到過,因為我們是ajax提交,在后臺的controller方法中不能包含HttpServletRequest request 這個參數,但后臺要想取表單域的值從哪取呢?其實還是從這個參數中取,只不過我們需要換一種方法,可以從上面接口的的webRequest對象中獲取,有了這個對象也就意味著你得到了表單域的所有值了,后臺的事情就好辦了。

HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

      下面只需要一個轉換類將HttpServletRequest中的表單值填充到我們自定義的SearchModel中就可以了,這里需要一個專業處理轉換有類SearchFilterBuilder,首先將表單值轉換成一個集合,字符串類型的:

列表頁的動態條件搜索

    public static SearchFilterBuilder from(final HttpServletRequest request) {        return new SearchFilterBuilder(request);
    }    public List<String> buildToStrings() {        return buildToStrings(true);
    }    public List<String> buildToStrings(final boolean containsDataAuth) {
        List<String> searchFilterStrings = Lists.newArrayList();

        Map<String, String[]> map = request.getParameterMap();        for (Map.Entry<String, String[]> entry : map.entrySet()) {
            String strKey = entry.getKey();            for (String value : entry.getValue()) {                if (!Strings.isNullOrEmpty(value)                        && !"none".equals(value)                        && strKey.startsWith(preWhere)) {

                    String filedAndOp = strKey.substring(preWhere.length());
                    searchFilterStrings.add(String.format("%s=%s", filedAndOp, value));
                }
            }
        }        if (containsDataAuth) {           // to do        }        return searchFilterStrings;
    }

列表頁的動態條件搜索

     基于上面得到的條件集合進一步解析條件,由于我們前端View傳遞的條件是字符串的,所以這里應用了一個專門的正則表達式的類DefaultSearchFilterStringProcessor去解析數據

    

列表頁的動態條件搜索

   public List<SearchFilter> build() {

        List<String> searchFilterStrings = buildToStrings();

        List<SearchFilter> searchFilters = Lists.newArrayList();

        searchFilters.addAll(searchFilterStrings.stream()
                .map(DefaultSearchFilterStringProcessor::from)
                .collect(Collectors.toList()));        return searchFilters;

    }

列表頁的動態條件搜索

 

   由于字符串處理的邏輯與本文關聯并不大,這里就不貼相關代碼了,不會正則的用最笨的人肉解析字符串也是可以的,如前面說的都拿到Request對象了后面都好操作。

  3:如果將表單域中的條件轉換成數據庫組件能夠識別的條件?
     tk.mybatis或者是官方的mybatis-spring組件都支持動態條件,由于我這采用的是tk.mybatis,所以某些類都是tk.mybatis的,tk是進一步的封裝,所以原理大體是相同的,之前有提到過操作mybtis有點像操作原生SQL,感覺就是一種拼SQL的過程,這里我們拼這個動態條件也是類似,簡單的話只需要一個靜態轉換方法就可以了,如果再深入一點可以想辦法做成自動識別并轉換,有能力的可研究。無非就是如下的轉換:

列表頁的動態條件搜索

             switch (op) {                case EQ:                    this.criteria.andEqualTo(filed, value);                    break;                case NOTEQ:                    this.criteria.andNotEqualTo(filed, value);                    break;                case LE:                    this.criteria.andLessThanOrEqualTo(filed, value);                    break;

列表頁的動態條件搜索


  解決完上面這些,我們就可以直接這樣寫后臺代碼了:
  controller:

列表頁的動態條件搜索

@RequestMapping(value = "/getAllByPage")
    @ResponseBody    public PageInfo<BcStore> getAllByPage(final SearchModel s1) {        this.convertSearchModel(s1);        
        return storeService.select(s1);
    }

列表頁的動態條件搜索


  service:有了example對象,分頁信息,排序字段,后面的就是tk.mybatis的基本功能了。

@Override    public final PageInfo<T> select(final SearchModel searchModel) {
        Example example = ExampleBuilder.forClass(genericType).fromSearchFilters(searchModel.getSearchFilters()).build();        return select(example, searchModel.getPageNum(), searchModel.getPageSize(), searchModel.getOrderBy());
    }

 

  基于上面的內容,針對查詢條件,我們可以在View中任意指定查語語句所包含的條件,后臺的controller以及service基本保持不變,應付普通的管理界面查詢足夠了。

 列表頁的動態條件搜索


向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

漳平市| 桓仁| 云林县| 平邑县| 光山县| 聊城市| 龙山县| 襄城县| 桐梓县| 潞西市| 雷波县| 桐柏县| 葫芦岛市| 治多县| 南岸区| 洪泽县| 方山县| 新源县| 遂昌县| 禄丰县| 黄骅市| 溆浦县| 灵台县| 藁城市| 沂南县| 沽源县| 泸定县| 城固县| 博兴县| 麻城市| 张家界市| 民勤县| 拉萨市| 竹北市| 饶阳县| 衡水市| 繁峙县| 通道| 阿克| 利辛县| 屏东县|