• java反射注解妙用-获取所有接口说明


    转载请注明出处:https://www.cnblogs.com/wenjunwei/p/10293490.html

    前言

    最近在做项目权限,使用shiro实现restful接口权限管理,对整个项目都进行了重构。而权限管理需要用到所有的接口配置,包括接口url地址,接口唯一编码等。想要收集所有的接口信息,如果工程接口很多,工作量可想而知。

    这里用了反射,来获取所有接口的信息,接口再多,也不过几秒钟的事。

    使用

    Auth.java

    接口信息对象

    主要包括授权地址,权限唯一标识,权限名称,创建时间,请求方式

    package com.wwj.springboot.model;
    
    import java.io.Serializable;
    import java.util.Date;
    
    public class Auth implements Serializable {
    
        private String authName;
        private String authUrl;
        private String authUniqueMark;
        private Date createTime;
        private String methodType;
    
        //get set 省略
    }

    UserController.java

    用户接口

    用于测试的接口。

    这里使用了标准的restful接口风格,swagger自动API接口,shiro 接口权限注解@RequiresPermissions组合成的一个controller。当然也可以使用其他技术,只要能获取到接口信息就行。

    注解不重要,重要的是注解里的信息。

    package com.wwj.springboot.controller;
    
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.apache.shiro.authz.annotation.RequiresPermissions;
    import org.springframework.web.bind.annotation.*;
    
    
    @RestController
    @RequestMapping("/users")
    @Api(value = "用户管理", tags = {"用户管理"})
    public class UserController {
    
        @GetMapping
        @ApiOperation("获取列表")
        @RequiresPermissions("user:list")
        public void list() {
            System.out.println();
        }
    
    
        @GetMapping(path = "/{userId}")
        @ApiOperation("获取详情")
        @RequiresPermissions("user:get")
        public void getUserById(@PathVariable("userId") String userId) {
            System.out.println();
        }
    
        @PostMapping
        @ApiOperation("新增一个用户")
        @RequiresPermissions("user:save")
        public void save() {
            System.out.println();
        }
    
        @PutMapping("/{userId}")
        @ApiOperation("修改保存")
        @RequiresPermissions("user:update")
        public void editSave(@PathVariable String userId) {
            System.out.println();
        }
    
    }

    主函数

    这里通过反射,获取了UserController的所有接口的说明,并存入数据库中。这是最主要的类。

    1.设置扫描的package路径
    Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(scanPackage)).setScanners(new MethodAnnotationsScanner()));
    2.获取到扫描包内带有@RequiresPermissions注解的所有方法集合
    Set<Method> methods = reflections.getMethodsAnnotatedWith(RequiresPermissions.class);
    3.通过反射获取类上的注解
    method.getDeclaringClass().getAnnotation(RequestMapping.class);
    4.通过反射获取方法上的注解
    method.getAnnotation(PutMapping.class);
    5.获取注解中的某个属性(这里是获取value属性)
    method.getAnnotation(PutMapping.class).value();
    完整的主函数代码
    package com.wwj.springboot;
    
    import com.alibaba.fastjson.JSON;
    import com.wwj.springboot.model.Auth;
    import io.swagger.annotations.Api;
    import io.swagger.annotations.ApiOperation;
    import org.apache.shiro.authz.annotation.RequiresPermissions;
    import org.reflections.Reflections;
    import org.reflections.scanners.MethodAnnotationsScanner;
    import org.reflections.util.ClasspathHelper;
    import org.reflections.util.ConfigurationBuilder;
    import org.springframework.web.bind.annotation.*;
    
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.Set;
    
    
    public class AnnoTest {
    
        public static void main(String[] args) {
            getRequestMappingMethod("com.wwj.springboot.controller");
        }
    
        /**
         * @param scanPackage 需要扫描的包路径
         */
        private static void getRequestMappingMethod(String scanPackage) {
            //设置扫描路径
            Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(scanPackage)).setScanners(new MethodAnnotationsScanner()));
    
            //扫描包内带有@RequiresPermissions注解的所有方法集合
            Set<Method> methods = reflections.getMethodsAnnotatedWith(RequiresPermissions.class);
    
            List<Auth> list = new ArrayList<>();
            Date now = new Date();
    
            //循环获取方法
            methods.forEach(method -> {
    
                //用于保存方法的请求类型
                String methodType = "";
    
                //获取类上的@RequestMapping注解的值,作为请求的基础路径
                String authUrl = method.getDeclaringClass().getAnnotation(RequestMapping.class).value()[0];
    
                //获取方法上的@PutMapping,@GetMapping,@PostMapping,@DeleteMapping注解的值,作为请求路径,并区分请求方式
                if (method.getAnnotation(PutMapping.class) != null) {
                    methodType = "put";
                    if (method.getAnnotation(PutMapping.class).value().length > 0) {
                        authUrl = method.getAnnotation(PutMapping.class).value()[0];
                    }
                } else if (method.getAnnotation(GetMapping.class) != null) {
                    methodType = "get";
                    if (method.getAnnotation(GetMapping.class).value().length > 0) {
                        authUrl = method.getAnnotation(GetMapping.class).value()[0];
                    }
                } else if (method.getAnnotation(PostMapping.class) != null) {
                    methodType = "post";
                    if (method.getAnnotation(PostMapping.class).value().length > 0) {
                        authUrl = method.getAnnotation(PostMapping.class).value()[0];
                    }
                } else if (method.getAnnotation(DeleteMapping.class) != null) {
                    if (method.getAnnotation(DeleteMapping.class).value().length > 0) {
                        authUrl = method.getAnnotation(DeleteMapping.class).value()[0];
                    }
                }
    
                //使用Auth对象来保存值
                Auth auth = new Auth();
                auth.setMethodType(methodType);
                auth.setAuthUniqueMark(method.getAnnotation(RequiresPermissions.class).value()[0]);
                auth.setAuthUrl(authUrl);
                auth.setAuthName(method.getDeclaringClass().getAnnotation(Api.class).value() + "-" + method.getAnnotation(ApiOperation.class).value());
                auth.setCreateTime(now);
                list.add(auth);
            });
            //TODO 输出到控制台,此处存数据库即可
            System.out.println(JSON.toJSONString(list));
        }
    }  

    通过上面所说的方法即可获取到注解中的值,这样就可以获取到我们想要的接口信息了,执行结果如下

    [{"authName":"用户管理-获取详情","authUniqueMark":"user:get","authUrl":"/users","createTime":1540977757616,"methodType":"get"},
    {"authName":"用户管理-新增一个用户","authUniqueMark":"user:save","authUrl":"/users","createTime":1540977757616,"methodType":"post"},
    {"authName":"用户管理-修改保存","authUniqueMark":"user:update","authUrl":"/{userId}","createTime":1540977757616,"methodType":"put"},
    {"authName":"用户管理-获取列表","authUniqueMark":"user:list","authUrl":"/users","createTime":1540977757616,"methodType":"get"}]

    感谢您的阅读,如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮。本文欢迎各位转载,但是转载文章之后必须在文章开头给出原文链接。

     
  • 相关阅读:
    用CSS3实现上下左右箭头
    让input框只能输入数字
    给内联元素设置宽高的几种方式
    当文本溢出包含的元素时加省略号之text-overflow
    通过box盒子模型给元素内容设置居中
    CSS3中的字体rem
    封装一个取消事件冒泡的方法
    HTML5 web workes实现多线程
    通过imeMode禁用键盘只能输入数字
    jquery的children方法和css3选择器配合使用
  • 原文地址:https://www.cnblogs.com/wenjunwei/p/10293490.html
Copyright © 2020-2023  润新知