Java 反射注解妙用,获取所有 Restful API 说明!

    科技2022-07-12  130

    点击上方“芋道源码”,选择“设为星标”

    管她前浪,还是后浪?

    能浪的浪,才是好浪!

    每天 8:55 更新文章,每天掉亿点点头发...

    源码精品专栏

     

    原创 | Java 2020 超神之路,很肝~

    中文详细注释的开源项目

    RPC 框架 Dubbo 源码解析

    网络应用框架 Netty 源码解析

    消息中间件 RocketMQ 源码解析

    数据库中间件 Sharding-JDBC 和 MyCAT 源码解析

    作业调度中间件 Elastic-Job 源码解析

    分布式事务中间件 TCC-Transaction 源码解析

    Eureka 和 Hystrix 源码解析

    Java 并发源码

    来源:cnblogs.com/wenjunwei/p/10293490.html

    前言

    使用

    Auth.java

    UserController.java

    主函数

    完整的主函数代码


    前言

    最近在做项目权限,使用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"}]

    欢迎加入我的知识星球,一起探讨架构,交流源码。加入方式,长按下方二维码噢:

    已在知识星球更新源码解析如下:

    最近更新《芋道 SpringBoot 2.X 入门》系列,已经 20 余篇,覆盖了 MyBatis、Redis、MongoDB、ES、分库分表、读写分离、SpringMVC、Webflux、权限、WebSocket、Dubbo、RabbitMQ、RocketMQ、Kafka、性能测试等等内容。

    提供近 3W 行代码的 SpringBoot 示例,以及超 4W 行代码的电商微服务项目。

    获取方式:点“在看”,关注公众号并回复 666 领取,更多内容陆续奉上。

    兄弟,艿一口,点个赞!????

    Processed: 0.011, SQL: 8