目录
排序场景
排序实现思路
1. 静态代码排序实现
2.数据库驱动排序实现
3. 基于Java反射的动态排序实现
通用排序工具 SortListUtil
结语
排序场景
在面向前端数据展示的应用场景中,我们旨在实现一个更加灵活的排序机制,该机制能够支持对从后端传递至前端的全部字段进行排序操作。用户通过点击排序按钮,即可实现对特定字段或多字段的升序或降序排列,从而快速实现页面的排序展示效果。
排序实现思路
1. 静态代码排序实现
- 内容:后端对前端传递的所有字段进行判断,以编写代码的方式实现排序逻辑
- 优点:采用静态代码实现排序逻辑的方法简洁明了,能够适应各种不同的场景
- 缺点:该方法会导致代码冗余,每个报表都需要独立实现排序逻辑,缺乏代码的可复用性
2.数据库驱动排序实现
- 内容:基于数据库排序的方式,前端将要排序的字段传给后端,后端转成数据库字段进行排序
- 优点:当涉及简单字段排序时,利用数据库自身的排序功能可以提高排序效率
- 缺点:该方法不适用于复合字段(即需要计算得出的字段)或前端字段与数据库字段没有直接映射关系的情况
3. 基于Java反射的动态排序实现
- 内容:前端传递排序字段和排序方式,排序字段基于后端提供的返回字段。在接口层接收到查询请求后,首先通过业务逻辑层获取到一个尚未排序的数据集合。随后,通过调用一个通用的排序工具来对集合进行排序处理,最终返回经过排序的集合。
- 优点:采用通用排序工具使得排序逻辑与业务逻辑和应用逻辑分离,利用Java反射机制实现了这一过程,从而显著提升了系统的可扩展性和灵活性。
- 缺点:Java反射机制的使用会增加资源消耗;同时,它可能会违背封装原则,并有可能引入安全风险。
通用排序工具 SortListUtil
sortListUtil是一个java语言实现的工具类方法。通过泛型、Comparator和Java 反射机制实现单字段排序,多字段排序。其中sortListByField方法处理集合单字段排序;sortListByFields方法处理集合多字段排序;getComparator方法为通用的排序方法,封装了处理集合排序字段的逻辑,通过这个方法组装成comparator对象,最后统一使用stream().sorted()方法进行排序。
- 方法内容
package com.streamax.bus.report.server.utils;import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;@Component
@Slf4j
public class SortListUtil<T> {public List<T> sortListByField(List<T> list, String fieldName, Integer orderBySort) {if (fieldName == null || fieldName == "") {return list;}// 构建getter方法名String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);Comparator<T> comparator = getComparator(getterName, orderBySort);// 使用sorted和collect来排序并收集结果return list.stream().sorted(comparator).collect(Collectors.toList());}/*** 多字段排序** @param list* @param fieldNames* @param orderBySort* @return*/public List<T> sortListByFields(List<T> list, String[] fieldNames, Integer orderBySort) {if (fieldNames == null || fieldNames.length == 0) {return list;}Comparator<T> comparator = null;for (String fieldName : fieldNames) {// 构建getter方法名String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);if (comparator == null) {comparator = getComparator(getterName, orderBySort);} else {comparator.thenComparing(getComparator(getterName, orderBySort));}}// 使用sorted和collect来排序并收集结果return list.stream().sorted(comparator).collect(Collectors.toList());}private Comparator<T> getComparator(String getterName, Integer orderBySort) {Comparator<T> comparator = (dto1, dto2) -> {try {Class<?> clazz = dto1.getClass();// 获取对应的getter方法Method getterMethod = clazz.getMethod(getterName);// 调用getter方法获取值Object value1 = getterMethod.invoke(dto1);Object value2 = getterMethod.invoke(dto2);// 关于有值为空的处理if (value1 == null || value2 == null) {return (value1 == null) ? (value1 == null ? -1 : 0) : 1;}// 比较两个值if (value1 instanceof Comparable && value2 instanceof Comparable) {if (orderBySort != null && orderBySort == 1) {return ((Comparable) value2).compareTo(value1);}return ((Comparable) value1).compareTo(value2);} else {throw new IllegalArgumentException("Field values are not comparable");}} catch (Exception e) {throw new RuntimeException("Error comparing field values", e);}};return comparator;}
}
- 使用方式
-
public static void main(String[] args) {QueryParams reqQuery = new QueryParams();reqQuery.setOrderByCommon("排序字段");reqQuery.setOrderBySort("排序类型 升序,降序");ObjectList resultList = new ArrayList<>();resultList = new SortListUtil<ObjectList>().sortListByField(resultList, reqQuery.getOrderByCommon(), reqQuery.getOrderBySort());}
- resultList : 需要排序的集合
- reqQuery:前端请求参数
- orderByCommon:需要排序的字段
- orderBySort:排序的方式(正序,倒序)
结语
本文简单阐述了排序功能的实现策略,并提供了一款基于Java反射机制的排序工具类名为SortListUtil。该工具于2024年11月5日上午完成编码,并已通过初步的单元测试和系统测试。需要注意的是,目前提供的版本并非工具类的最终形态。我们欢迎各位同仁提出宝贵的优化建议,共同探讨和提升工具的性能与可用性。