查詢結果緯度補全

註解:

package com.demo.aop;

import java.lang.annotation.*;

/**
 * @author LiHaitao
 * @description DimensionPaddingsList:
 * @date 2019/12/5 18:11
 **/
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DimensionPaddingList {
    DimensionPadding[] value();
}

package com.demo.aop;

import java.lang.annotation.*;

/**
 * @author LiHaitao
 * @description DimensionPadding:
 * @date 2019/12/5 16:43
 **/

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface DimensionPadding {

    /**
     * 維度補全的原始字段, 如人員編號, 設備編號, 支持嵌套對象, 如fieldA.FieldB.FieldC
     *
     * @return
     */
    String field();

    /**
     * 維度補全底層數據源字段. 如果爲空, 使用field
     *
     * @return
     */
    String fieldAs() default "";

    /**
     * 需要補全的字段名稱, 如人員名稱, 設備名稱
     *
     * @return
     */
    String name();

    /**
     * 維度補全底層數據源字段. 如果爲空, 使用name
     *
     * @return
     */
    String nameAs() default "";

    //    /**
    //     * 補全方式類型.
    //     *
    //     * @return
    //     */
    //    DimensionPaddingEnum serviceType() default DimensionPaddingEnum.DATA_DICT;


    /**
     * 補全方式的service類型,如果serviceType 爲DimensionPaddingEnum#SPRINT_BEAN 該service必須繼承自QueryParamService;
     *
     * @return
     */
    Class<?> service() default Object.class;


}

切面實現:

package com.demo.aop;

import com.demo.service.QueryService;
import com.demo.util.AopUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.springframework.aop.support.StaticMethodMatcherPointcutAdvisor;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

/**
 * Created by Administrator on 2019/7/26.
 */

@Component
public class DiamensionPaddingAop extends StaticMethodMatcherPointcutAdvisor implements ApplicationContextAware {


    private ApplicationContext applicationContext;


    public DiamensionPaddingAop() {
        this.setAdvice((MethodInterceptor) (methodInvocation) -> {

            Object response;

            try {
                response = methodInvocation.proceed();
                if (response == null) {
                    return null;
                }
                Method method = methodInvocation.getMethod();
                Object aThis = methodInvocation.getThis();
                DimensionPaddingList dimensionPaddingList = AopUtil.findMethodAnnotation(aThis.getClass(), method, DimensionPaddingList.class);
                if (dimensionPaddingList != null && dimensionPaddingList.value() != null) {
                    valueComplement(response, Arrays.asList(dimensionPaddingList.value()));
                }

                /* DimensionPaddings 和 DimensionPadding 兩個標籤是可以共存的 */
                DimensionPadding dimensionPadding = AopUtil.findMethodAnnotation(aThis.getClass(), method, DimensionPadding.class);
                if (dimensionPadding != null) {
                    valueComplement(response, dimensionPadding);
                }


            } catch (Throwable a) {
                throw a;
            }
            return response;
        });
    }

    private void valueComplement(Object response, List<DimensionPadding> dimensionPaddings) {
        dimensionPaddings.forEach(dimensionPadding -> valueComplement(response, dimensionPadding));
    }


    private void valueComplement(Object response, DimensionPadding dimensionPadding) {
        /**
         * 通過field的值作爲fieldAs,查找出來後,將nameAs賦值給name
         */
        String field = dimensionPadding.field();//已知值
        String fieldAs = dimensionPadding.fieldAs();//數據源查詢條件值,對應已知值
        String name = dimensionPadding.name();//要補全的值
        String nameAs = dimensionPadding.nameAs();//數據源,要對應要補全的值
        Class<?> service = dimensionPadding.service();
        QueryService queryService = (QueryService) applicationContext.getBean(service);
        if (response instanceof Collection) {
            Collection dataList = (Collection) response;
            for (Object data : dataList) {
                Object value = getValue(field, fieldAs, nameAs, queryService, data);
                try {
                    Field declaredField = data.getClass().getDeclaredField(name);
                    declaredField.setAccessible(true);
                    if (value instanceof Number) {
                        declaredField.set(data, (Number) value);
                    }
                    if (value instanceof String) {
                        declaredField.set(data, String.valueOf(value));
                    }
                } catch (IllegalAccessException | NoSuchFieldException e) {
                    e.printStackTrace();
                }
            }


        }
    }

    private Object getValue(String field, String fieldAs, String nameAs, QueryService queryService, Object data) {
        Field declaredField = null;
        try {
            declaredField = getDeclaredField(data, field);
            assert declaredField != null;
            Object o = declaredField.get(data);
            //這裏的查詢可以利用fieldAs來進行條件查詢。fieldAs=o。但這裏用id查詢。沒有使用到fieldAs
            Object entity = queryService.findById((Long) o);
            Field f = getDeclaredField(entity, nameAs);
            assert f != null;
            return f.get(entity);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return null;
    }

    private Field getDeclaredField(Object obj, String fieldName) {
        try {
            Field declaredField = obj.getClass().getDeclaredField(fieldName);
            if (declaredField != null) {
                declaredField.setAccessible(true);
                return declaredField;
            }
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }


    @Override
    public boolean matches(Method method, Class<?> aClass) {
        DimensionPaddingList dimensionPaddingList = AopUtil.findAnnotation(aClass, method, DimensionPaddingList.class);
        DimensionPadding dimensionPadding = AopUtil.findAnnotation(aClass, method, DimensionPadding.class);
        return dimensionPadding != null || dimensionPaddingList != null;
    }


    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

使用:

package com.demo.controller;

import com.demo.aop.DimensionPadding;
import com.demo.aop.DimensionPaddingList;
import com.demo.model.TeacherStudentVO;
import com.demo.service.StudentService;
import com.demo.service.TeacherService;
import com.demo.service.TeacherStudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * @author LiHaitao
 * @description Test:
 * @date 2019/12/4 14:32
 **/
@RestController
@RequestMapping
public class Test {


    @Autowired
    private TeacherStudentService service;

    @RequestMapping("/test")
    @DimensionPaddingList({
            @DimensionPadding(field = "studentsId", fieldAs = "id", name = "studentName", nameAs = "name", service = StudentService.class)
            ,
            @DimensionPadding(field = "studentTeacherId", fieldAs = "id", name = "teacherName", nameAs = "name", service = TeacherService.class)
            ,
            @DimensionPadding(field = "studentsId", fieldAs = "id", name = "studentAge", nameAs = "age", service = StudentService.class)
            ,
            @DimensionPadding(field = "studentTeacherId", fieldAs = "id", name = "teacherAge", nameAs = "age", service = TeacherService.class)
    }
    )
    public List<TeacherStudentVO> createData() {
        return service.getAll();
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章