基于Java反射技术扫描Controller接口列表(完整代码)

基于org.reflections依赖包简化反射代码

1. 导入依赖

<dependency>
    <groupId>org.reflections</groupId>
    <artifactId>reflections</artifactId>
    <version>0.10.2</version>
</dependency>

2. 实现代码

2.1 配置类:ApiConfig

import java.util.HashSet;
import java.util.Set;
import java.util.function.Predicate;

public class ApiConfig {

    /**
     * 扫描注解
     */
    public Set<Class> annotations = new HashSet<>();

    /**
     * 扫描路径
     */
    public String basePackage = "com.dwp";

    /**
     * 判断是否需要处理此文件,入参为文件名(含.class后缀)
     */
    public Predicate<String> classPredicate = clazz -> clazz.endsWith("Controller.class");

    protected ApiConfig() {

    }
}

2.2 配置类构建类:ApiConfigBuilder

import java.util.Arrays;
import java.util.Collection;

public class ApiConfigBuilder {

    private ApiConfig apiConfig;

    public ApiConfigBuilder() {
        this.apiConfig = new ApiConfig();
    }

    public ApiConfigBuilder addAnnotations(Class clazz) {
        addAnnotations(Arrays.asList(clazz));
        return this;
    }

    public ApiConfigBuilder addAnnotations(Collection<Class> clazz) {
        apiConfig.annotations.addAll(clazz);
        return this;
    }

    public ApiConfigBuilder forPackage(String basePackage) {
        apiConfig.basePackage = basePackage;
        return this;
    }

    public ApiConfig build() {
        return this.apiConfig;
    }

}

2.3 接口实体类:ApiEntity

import lombok.Data;

import java.io.Serializable;

@Data
public class ApiEntity implements Serializable {

    private static final long serialVersionUID = 1L;

    private String moduleName;

    private String name;

    private String remark;

    private String path;

    private String method;

    public ApiEntity() {

    }

    public ApiEntity(String path) {
        this.path = path;
    }

    public ApiEntity(String path, String method) {
        this(path);
        this.method = method;
    }

    public ApiEntity(String name, String remark, String path, String method) {
        this(path, method);
        this.name = name;
        this.remark = remark;
    }
}

2.4 核心逻辑工具类:ApiUtil

import com.dwp.entity.ApiEntity;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.stream.Collectors;

import static org.springframework.web.bind.annotation.RequestMethod.*;

@Slf4j
public class ApiUtil {

    private static final Map<Class, RequestMethod> METHOD_TYPE = new HashMap<Class, RequestMethod>() {{
        put(PostMapping.class, POST);
        put(PutMapping.class, PUT);
        put(DeleteMapping.class, DELETE);
        put(GetMapping.class, GET);
        put(PatchMapping.class, PATCH);
    }};

    public ApiConfig config;

    public ApiUtil() {

    }

    public ApiUtil(ApiConfig config) {
        this.config = config;
    }

    /**
     * 扫描所有文件下的方法,默认扫描具有以下注解的接口
     * {@link RequestMapping},
     * {@link PostMapping},
     * {@link PutMapping},
     * {@link GetMapping},
     * {@link DeleteMapping},
     * {@link PatchMapping}
     *
     * @return
     */
    public List<ApiEntity> scanApis() {
        return scanList(getMethods());
    }

    /**
     * 构造反射器
     *
     * @return
     */
    private Reflections buildReflections() {
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .setInputsFilter(config.classPredicate)
                .forPackage(config.basePackage)
                .setScanners(new MethodAnnotationsScanner()));
        return reflections;
    }

    /**
     * 获取方法集合
     *
     * @return
     */
    private Set<Method> getMethods() {
        Reflections reflections = buildReflections();
        Set<Method> result = new HashSet<>();
        Set<Class> annotations = config.annotations;
        if (CollectionUtils.isEmpty(annotations)) {
            annotations.add(RequestMapping.class);
            annotations.add(PostMapping.class);
            annotations.add(PutMapping.class);
            annotations.add(GetMapping.class);
            annotations.add(DeleteMapping.class);
            annotations.add(PatchMapping.class);
        }

        for (Class clazz : annotations) {
            Set<Method> set = Optional.ofNullable(reflections.getMethodsAnnotatedWith(clazz)).orElse(new HashSet());
            result.addAll(set);
        }
        return result;
    }

    /**
     * 解析方法集合
     *
     * @param methods 方法集合
     * @return
     */
    private List<ApiEntity> scanList(Set<Method> methods) {
        List<ApiEntity> list = new ArrayList<>();
        try {
            //循环获取方法
            log.info("开始解析...");
            long startTime = new Date().getTime();
            for (Method method : methods) {
                log.info("parsing class = '{}', method = '{}'", method.getDeclaringClass().getName(), method.getName());
                List<ApiEntity> item = parser(method);
                list.addAll(item);
            }
            log.info("解析完成, 耗时: {}ms", (new Date().getTime() - startTime));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 对扫描到的方法进行解析
     *
     * @param method 方法
     * @return
     */
    private List<ApiEntity> parser(Method method) {
        List<ApiEntity> list = new ArrayList<>();
        /**
         * 同时存在RequestMapping和其它如PostMapping注解时,RequestMapping具有最高优先级
         */
        if (method.getDeclaredAnnotation(RequestMapping.class) != null) {
            parseRequestMapping(method, list);
            return list;
        }

        /**
         * 其它注解按顺序决定优先级
         */
        Annotation[] annotations = method.getDeclaredAnnotations();
        List<Annotation> annotationList = Arrays.stream(annotations).filter(annotation -> METHOD_TYPE.get(annotation.annotationType()) != null).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(annotationList)) {
            return list;
        }

        Annotation annotation = annotationList.get(0);
        RequestMethod methodType = METHOD_TYPE.get(annotation.annotationType());
        switch (methodType) {
            case POST:
                parsePostMapping(method, list);
                break;
            case GET:
                parseGetMapping(method, list);
                break;
            case PUT:
                parsePutMapping(method, list);
                break;
            case DELETE:
                parseDeleteMapping(method, list);
                break;
            case PATCH:
                parsePatchMapping(method, list);
                break;
            default:
                break;
        }
        return list;
    }

    private void parseRequestMapping(Method method, List<ApiEntity> list) {
        RequestMapping annotation = method.getDeclaredAnnotation(RequestMapping.class);
        if (annotation != null) {
            List<String> paths = new ArrayList<>(Arrays.asList(annotation.value()));
            RequestMethod[] methods = annotation.method();
            if (methods.length == 0) {
                methods = RequestMethod.values();
            }

            //处理接口前缀
            addPrefix(method, paths);
            for (String path : paths) {
                for (RequestMethod methodType : methods) {
                    ApiEntity api = new ApiEntity(path, methodType.name());
                    //补充接口描述信息
                    parseSwaggerAnnotation(method, api);
                    list.add(api);
                }
            }
        }
    }

    private void parseGetMapping(Method method, List<ApiEntity> list) {
        GetMapping annotation = method.getDeclaredAnnotation(GetMapping.class);
        if (annotation == null) {
            return;
        }
        parseApiEntity(method, list, annotation.value(), GET.name());
    }

    private void parsePostMapping(Method method, List<ApiEntity> list) {
        PostMapping annotation = method.getDeclaredAnnotation(PostMapping.class);
        if (annotation == null) {
            return;
        }
        parseApiEntity(method, list, annotation.value(), POST.name());
    }

    private void parsePutMapping(Method method, List<ApiEntity> list) {
        PutMapping annotation = method.getDeclaredAnnotation(PutMapping.class);
        parseApiEntity(method, list, annotation.value(), PUT.name());
    }

    private void parseDeleteMapping(Method method, List<ApiEntity> list) {
        DeleteMapping annotation = method.getDeclaredAnnotation(DeleteMapping.class);
        parseApiEntity(method, list, annotation.value(), DELETE.name());
    }

    private void parsePatchMapping(Method method, List<ApiEntity> list) {
        PatchMapping annotation = method.getDeclaredAnnotation(PatchMapping.class);
        parseApiEntity(method, list, annotation.value(), PATCH.name());
    }

    private void parseApiEntity(Method method, List<ApiEntity> list, String[] pathArr, String methodType) {
        List<String> paths = new ArrayList<>(Arrays.asList(pathArr));
        //处理根路径
        addPrefix(method, paths);
        for (String path : paths) {
            ApiEntity api = new ApiEntity(path, methodType);
            //补充接口描述信息
            parseSwaggerAnnotation(method, api);
            list.add(api);
        }
    }

    /**
     * 拼接Controller类上的路径前缀
     *
     * @param method
     * @param paths
     */
    private void addPrefix(Method method, List<String> paths) {
        if (CollectionUtils.isEmpty(paths)) {
            paths.add("");
        }
        paths = paths.stream().map(path -> path.startsWith("/") ? path : "/" + path).collect(Collectors.toList());

        RequestMapping rootMapping = method.getDeclaringClass().getAnnotation(RequestMapping.class);
        if (rootMapping == null || rootMapping.value().length == 0) {
            return;
        }

        String[] roots = rootMapping.value();
        for (String root : roots) {
            paths = paths.stream().map(path -> {
                String prefix = root.endsWith("/") ? root.substring(0, root.length() - 1) : root;
                path = prefix + path;
                return path;
            }).collect(Collectors.toList());
        }
    }

    /**
     * 解析swagger注解
     *
     * @param method
     * @param entity
     * @return
     */
    private ApiEntity parseSwaggerAnnotation(Method method, ApiEntity entity) {
        Api api = method.getDeclaringClass().getAnnotation(Api.class);
        if (api != null && api.tags().length > 0) {
            String[] tags = api.tags();
            entity.setModuleName(tags[0]);
        }
        ApiOperation apiOperation = method.getDeclaredAnnotation(ApiOperation.class);
        if (apiOperation != null) {
            entity.setName(apiOperation.value());
            entity.setRemark(apiOperation.notes());
        }
        return entity;
    }

}

3 使用示例

 public static void main(String[] args) {
        List<ApiEntity> list = new ApiUtil(new ApiConfigBuilder()
                .forPackage("com.dwp.project")
                .addAnnotations(ApiOperation.class)
                .build()
        ).scanApis();
        System.out.println(list);
}

给大家推荐一个程序员必备网站,功能方便、实用,页面精美,下面是部分功能截图:

代码生成
在这里插入图片描述

云剪切板
在这里插入图片描述

工作日报生成
在这里插入图片描述
专利文章生成
在这里插入图片描述
毕业论文生成
在这里插入图片描述
点击访问

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
很抱歉,我无法提供完整的项目代码,因为一个完整的工厂物料管理系统项目涉及多个模块和大量的代码。这样的项目需要详细的需求分析、架构设计、数据库设计和开发工作。而且每个公司和团队的实现方式可能有所不同。 我可以给您提供一个基本的项目结构和一些关键代码片段来帮助您开始开发工厂物料管理系统。您可以根据这些代码片段进行进一步的开发和定制。 以下是一个简单的项目结构示例: ``` - src/main/java - com.example.factories (主包) - config (配置类) - WebConfig.java (Web配置) - DatabaseConfig.java (数据库配置) - controller (控制器类) - UserController.java (用户管理控制器) - MaterialController.java (物料管理控制器) - SupplierController.java (供应商管理控制器) - CustomerController.java (客户管理控制器) - InventoryController.java (库存管理控制器) - PurchaseController.java (采购管理控制器) - SalesController.java (销售管理控制器) - ReportController.java (报表管理控制器) - model (模型类) - User.java (用户模型) - Material.java (物料模型) - Supplier.java (供应商模型) - Customer.java (客户模型) - Inventory.java (库存模型) - PurchaseOrder.java (采购订单模型) - SalesOrder.java (销售订单模型) - repository (数据访问层) - UserRepository.java (用户数据访问接口) - MaterialRepository.java (物料数据访问接口) ***

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值