Mybatis-plus如何通過反射實(shí)現(xiàn)動(dòng)態(tài)排序不同字段功能
Mybatis-plus反射實(shí)現(xiàn)動(dòng)態(tài)排序不同字段
最近在做項(xiàng)目,使用到了Mybatis-plus,頁(yè)面上需要對(duì)某些字段進(jìn)行排序,原來是固定好哪些字段需要排序,然后在Controller里接收參數(shù)。
如下代碼所示
@LogOperation(name = "query urpOfi", objType = "Config") @GetMapping public ResponseEntity<DtoResponse<OfiDto>> queryOfi( @RequestParam(name = "pageSize", defaultValue = "-1", required = false) Integer pageSize, @RequestParam(name = "page", defaultValue = "-1", required = false) Integer page, @RequestParam(value = "sort", defaultValue = "", required = false) String sort, @RequestParam(value = "msFlag", defaultValue = "", required = false) String msFlag) throws UnsupportedEncodingException { sort = URLDecoder.decode(sort, StandardCharsets.UTF_8.toString()); msFlag = URLDecoder.decode(msFlag, StandardCharsets.UTF_8.toString()); 余下省略......
其中@LogOperation使我們自定義的AOP日志注解,可以不用關(guān)注。
這里存在的問題是參數(shù)沒有校驗(yàn)
直接接收了,可能會(huì)被惡意攻擊,同時(shí)sort為排序字段,前臺(tái)會(huì)傳一個(gè)固定好的字段值過來,
無法實(shí)現(xiàn)動(dòng)態(tài)排序(比如:前臺(tái)隨意傳一個(gè)字段,只要在我的表數(shù)據(jù)Entity中存在該字段,就可以實(shí)現(xiàn)排序)
通過以下方式實(shí)現(xiàn)動(dòng)態(tài)排序
@Data public class BaseQueryDto<T> { // 排序方式標(biāo)識(shí)符號(hào),”-“代表倒序 private static final String ORDER_BY_IDENTIFIER = "-"; private static final int MAX_PAGE_SIZE = 100; private static final int MAX_PAGE = 10000; private static final int MAX_SORT_LENGTH = 100; /** * 每頁(yè)顯示記錄數(shù) */ @Range(min = 0, max = MAX_PAGE_SIZE) protected Integer pageSize = 10; /** * 當(dāng)前頁(yè) */ @Range(min = 0, max = MAX_PAGE) protected Integer page = 0; /** * 排序,包含2部分內(nèi)容,排序方式及排序字段 */ @Length(max = MAX_SORT_LENGTH) protected String sort; /** * 獲取排序方式,默認(rèn)升序(asc) * * @return 排序方式 */ public SqlOrderType getOrderType() { if (StringUtils.isEmpty(sort)) { return SqlOrderType.ASC; } if (sort.startsWith(ORDER_BY_IDENTIFIER)) { return SqlOrderType.DESC; } return SqlOrderType.ASC; } private Optional<Class<?>> getEntityClass() { Type type = getClass().getGenericSuperclass(); if (type instanceof ParameterizedType) { Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); try { return Optional.of(Class.forName(actualTypeArguments[0].getTypeName())); } catch (ClassNotFoundException e) { return Optional.empty(); } } return Optional.empty(); } private Optional<Field> getEntityField(String fieldName) { Optional<Class<?>> optionalClass = getEntityClass(); return optionalClass.flatMap(it -> { try { return Optional.of(it.getDeclaredField(fieldName)); } catch (NoSuchFieldException e) { return Optional.empty(); } }); } /** * 獲取數(shù)據(jù)排序的列 * * @return 排序列 */ public Optional<String> getOrderColumn() { if (StringUtils.isEmpty(sort)) { return Optional.empty(); } return getEntityField(sort.replaceFirst(ORDER_BY_IDENTIFIER, "")).map(Field::getName); } /** * 設(shè)置排序的QueryWrapper * * @param queryWrapper query wrapper */ public void setOrderQueryWrapper(QueryWrapper<T> queryWrapper) { this.getOrderColumn().ifPresent(column -> { queryWrapper.orderBy(true, this.getOrderType().equals(SqlOrderType.ASC), column); }); } }
BaseQueryDto是公共的查詢Dto父類,泛型T為具體的表數(shù)據(jù)Entity。
通過java beanvalidation控制入?yún)⒋笮〖伴L(zhǎng)度,前端傳遞的參數(shù)sort值一般為Entity中的字段名,例如“id”或者“-id”,帶有“-”的代表是降序。
會(huì)根據(jù)傳入的sort值通過反射去判斷在Entity中是否存在該字段,存在就正常排序,不存在就什么也不做。
如果只需要排序,那么Controller中用BaseQueryDto去接收參數(shù)即可,然后在Service中調(diào)用baseQueryDto.setOrderQueryWrapper(queryWrapper);
如果不僅僅排序,還需要對(duì)某些字段做模糊查詢或者下拉框過濾查詢,需要新建Dto繼承BaseQueryDto。
@Data public class OfiQueryDto extends BaseQueryDto<OfiEntity> { /** * 主從標(biāo)識(shí)(過濾查詢) */ @Length(max = 5) private String msFlag = ""; /** * 國(guó)內(nèi),國(guó)內(nèi)備用,國(guó)際,國(guó)際備用網(wǎng)編碼(模糊查詢) */ @Length(max = 6) private String networkCode1 = ""; @Length(max = 6) private String networkCode2 = ""; @Length(max = 6) private String networkCode3 = ""; @Length(max = 6) private String networkCode4 = ""; }
Service中設(shè)置模糊查詢,下拉框過濾和排序。
public ListPage<OfiEntity> queryOfiListPage(OfiQueryDto dto, Integer clusterId) throws UnsupportedEncodingException { QueryWrapper<OfiEntity> queryWrapper = Wrappers.query(); queryWrapper.lambda().eq(OfiEntity::getClusterId, clusterId); setSelectQueryWrapper(dto, queryWrapper.lambda()); setLikeQueryWrapper(dto, queryWrapper.lambda()); dto.setOrderQueryWrapper(queryWrapper); Page<OfiEntity> ofiEntityPage = new Page<>(dto.getPage(), dto.getPageSize()); ofiEntityPage = getBaseMapper().selectPage(ofiEntityPage, queryWrapper); return ListPage.of(ofiEntityPage); }
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringBoot設(shè)置動(dòng)態(tài)定時(shí)任務(wù)的方法詳解
這篇文章主要為大家詳細(xì)介紹了SpringBoot設(shè)置動(dòng)態(tài)定時(shí)任務(wù)的方法,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)有一定的參考價(jià)值,需要的可以參考一下2022-06-06基于swagger參數(shù)與實(shí)體中參數(shù)不一致的原因分析
這篇文章主要介紹了基于swagger參數(shù)與實(shí)體中參數(shù)不一致的原因分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-11-11一個(gè)簡(jiǎn)單的類加載器URLClassLoader案例
這篇文章主要介紹了一個(gè)簡(jiǎn)單的類加載器URLClassLoader案例,這里寫了一個(gè)小 demo,來加深對(duì)于反射的理解,需要的朋友可以參考下2023-04-04