目录

排序场景

排序实现思路

        1. 静态代码排序实现

        2.数据库驱动排序实现

        3. 基于Java反射的动态排序实现

通用排序工具 SortListUtil

结语


排序场景

        在面向前端数据展示的应用场景中,我们旨在实现一个更加灵活的排序机制,该机制能够支持对从后端传递至前端的全部字段进行排序操作。用户通过点击排序按钮,即可实现对特定字段或多字段的升序或降序排列,从而快速实现页面的排序展示效果。

排序实现思路

        1. 静态代码排序实现

  • 内容:后端对前端传递的所有字段进行判断,以编写代码的方式实现排序逻辑
  • 优点:采用静态代码实现排序逻辑的方法简洁明了,能够适应各种不同的场景
  • 缺点:该方法会导致代码冗余,每个报表都需要独立实现排序逻辑,缺乏代码的可复用性

        2.数据库驱动排序实现

  • 内容:基于数据库排序的方式,前端将要排序的字段传给后端,后端转成数据库字段进行排序
  • 优点:当涉及简单字段排序时,利用数据库自身的排序功能可以提高排序效率
  • 缺点:该方法不适用于复合字段(即需要计算得出的字段)或前端字段与数据库字段没有直接映射关系的情况

        3. 基于Java反射的动态排序实现

        前后端交互通用排序策略-LMLPHP

  • 内容:前端传递排序字段和排序方式,排序字段基于后端提供的返回字段。在接口层接收到查询请求后,首先通过业务逻辑层获取到一个尚未排序的数据集合。随后,通过调用一个通用的排序工具来对集合进行排序处理,最终返回经过排序的集合。
  • 优点:采用通用排序工具使得排序逻辑与业务逻辑和应用逻辑分离,利用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日上午完成编码,并已通过初步的单元测试和系统测试。需要注意的是,目前提供的版本并非工具类的最终形态。我们欢迎各位同仁提出宝贵的优化建议,共同探讨和提升工具的性能与可用性。

11-06 13:31