自定义排序器统一自动排序

在项目写的差不多的时候,突然增加需求,要对之前的接口返回的list进行排序,要一个个回去重新添加排序好麻烦,所以尝试写了拦截器,拦截接口统一排序:

公共响应体

先是Controller返回的公共响应体:

import java.io.Serializable;

public class CommonResult<T> implements Serializable {

    private String message;
    private int code;
    private T data;

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }

    public CommonResult() {
    }

    public CommonResult(int code, String message, T data) {
        this.message = message;
        this.code = code;
        this.data = data;
    }

    public static <T> CommonResult<T> success(String message, T data) {
        return new CommonResult<>(200, message, data);
    }

}

配置类:

这个配置类的目的是:
有时排序字段可能不一致,所以通过这中配置的方式来灵活配置想要的排序字段

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
@ConfigurationProperties(prefix = "sort")
@EnableConfigurationProperties
public class SortConfig {

    private Map<String, String> sortMap = new HashMap<>();

    public Map<String, String> getSortMap() {
        return sortMap;
    }

    public void setSortMap(Map<String, String> sortMap) {
        this.sortMap = sortMap;
    }
}

配置nacos中定义的map可以实现灵活排序

在这里插入图片描述

拦截器:ResultAspect

通过反射来遍历object的每个属性,若是集合则排序,并且会递归对象属性中的嵌套集合;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

@Aspect
@Component
public class ResultAspect {
    private SortConfig sortConfig;

    /**
     * 将所有controller层级的方法作为切入点
     */

    @Pointcut(" execution(public *controller的层级路径")
    public void handlePlaceholder() {

    }

    /**
     * pointcut/value:这两个属性的作用是一样的, 它们都属于指定切入点对应的切入表达式*。
     * 一样既可以是已有的切入点,也可直接定义切入点表达式。当指定J pointcut属性值后,value属性值将会被覆盖。
     * 在这里把已经定义好的 handLePlaceholder 作为切入点
     * returning:该属性指定一个形参名, 用于表示Advice方法中可定义与此同名的形参,该形参可用F访问目标方法的返回值。
     * 除此之外,在Advice方法中定 义该形参(代表目标方法的返回值)时指定的类型,会限制目标方法必须返回指定类型的值或没有返回值。
     */
    @AfterReturning(returning = "ret", pointcut = "handlePlaceholder()")
    public void doAfterReturning(Object ret) throws Throwable {
        // 在清求処理之后迸行搓截処理
        if (ret != null) {
            CommonResult<?> result = (CommonResult<?>) ret;
            Object data = result.getData();

            if (data instanceof List<?>) {
                // 排最外层
                List<Object> dataList = (List<Object>) data;
                dataList.sort(new CustomFieldComparator(sortConfig.getSortMap()));
                //排内居嵌套
                sortObjField(dataList);
            }
        }
    }

    /**
     * 递归,排序属性中的list
     *
     * @param dataList 数据的List
     * @throws IllegalAccessException 漂移车
     */
    public void sortObjField(List<?> dataList) throws IllegalAccessException {

        // 遍历data中的属性中是否有list

        for (Object obj : dataList) {
            Field[] fields = obj.getClass().getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Class<?> type = field.getType();
                // 是否是list
                if (type.isAssignableFrom(List.class)) {
                    List<Object> list = (List<Object>) field.get(obj);
                    list.sort(new CustomFieldComparator(sortConfig.getSortMap()));
                    // 递归
                    sortObjField(list);
                }
            }
        }
    }

    static class CustomFieldComparator implements Comparator<Object> {

        private Map<String, String> sortMap;

        CustomFieldComparator(Map<String, String> sortMap) {
            this.sortMap = sortMap;
        }
		// 设置一个默认的排序字段
        private static final String SHORT_NAME = " shortName";

        @SneakyThrows
        @Override
        public int compare(Object o1, Object o2) {
            String sortName = this.getSortName(o1);
            //根据指定字段进行比较,并返回比较结果
            //假设指定字段为fieldName, 类型为String
            String v1 = this.getFieldValueByFieldName(sortName, o1);
            if (v1 == null) {
                return 0;
            }
            String v2 = this.getFieldValueByFieldName(sortName, o2);
            return v1.compareTo(v2);

        }

        public String getSortName(Object obj) {
            String[] split = obj.getClass().getName().split(".");
            String className = split[split.length - 1];
            // 根据类名,获取在nacos中配置的排序字段,若获取不到值,则使用默认的排序字段
            String sortName = sortMap.get(className);
            sortName = sortName == null ? SHORT_NAME : sortName;

            return sortName;
        }

        /**
         *
         * @param fieldName 属性名
         * @param object 对象
         * @return 返回属性值
         */
        private String getFieldValueByFieldName(String fieldName, Object object) {
            try {
                Field field = object.getClass().getDeclaredField(fieldName);
                // 设置对象的访问权限,保证对private的属性的访问
                field.setAccessible(true);
                return ((String) field.get(object)).toLowerCase();
            } catch (Exception e) {
                return null;
            }
        }
    }

}

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值