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

前言

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

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

使用

Auth.java

接口信息对象

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

packagecom.wwj.springboot.model;importjava.io.Serializable;importjava.util.Date;public class Auth implementsSerializable {privateString authName;privateString authUrl;privateString authUniqueMark;privateDate createTime;privateString methodType;//get set 省略

}

UserController.java

用户接口

用于测试的接口。

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

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

packagecom.wwj.springboot.controller;importio.swagger.annotations.Api;importio.swagger.annotations.ApiOperation;importorg.apache.shiro.authz.annotation.RequiresPermissions;import org.springframework.web.bind.annotation.*;@RestController

@RequestMapping("/users")

@Api(value= "用户管理", tags = {"用户管理"})public classUserController {

@GetMapping

@ApiOperation("获取列表")

@RequiresPermissions("user:list")public voidlist() {

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 voidsave() {

System.out.println();

}

@PutMapping("/{userId}")

@ApiOperation("修改保存")

@RequiresPermissions("user:update")public voideditSave(@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 methods = reflections.getMethodsAnnotatedWith(RequiresPermissions.class);

3.通过反射获取类上的注解

method.getDeclaringClass().getAnnotation(RequestMapping.class);

4.通过反射获取方法上的注解

method.getAnnotation(PutMapping.class);

5.获取注解中的某个属性(这里是获取value属性)

method.getAnnotation(PutMapping.class).value();

完整的主函数代码

packagecom.wwj.springboot;importcom.alibaba.fastjson.JSON;importcom.wwj.springboot.model.Auth;importio.swagger.annotations.Api;importio.swagger.annotations.ApiOperation;importorg.apache.shiro.authz.annotation.RequiresPermissions;importorg.reflections.Reflections;importorg.reflections.scanners.MethodAnnotationsScanner;importorg.reflections.util.ClasspathHelper;importorg.reflections.util.ConfigurationBuilder;import org.springframework.web.bind.annotation.*;importjava.lang.reflect.Method;importjava.util.ArrayList;importjava.util.Date;importjava.util.List;importjava.util.Set;

public classAnnoTest {public static voidmain(String[] args) {

getRequestMappingMethod("com.wwj.springboot.controller");

}/***@paramscanPackage 需要扫描的包路径*/

private static voidgetRequestMappingMethod(String scanPackage) {//设置扫描路径

Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(scanPackage)).setScanners(newMethodAnnotationsScanner()));//扫描包内带有@RequiresPermissions注解的所有方法集合

Set methods = reflections.getMethodsAnnotatedWith(RequiresPermissions.class);

List list = new ArrayList<>();

Date now= newDate();//循环获取方法

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 = newAuth();

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"}]

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289036.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#窗体的Load事件与Shown事件的区别

Load&#xff1a;在第一次显示窗体前发生。 <pre name"code" class"csharp"> private void Form1_Load(object sender, EventArgs e){} Shown&#xff1a;只有在首次显示窗体时才会引发 Shown 事件&#xff1b;随后执行的最小化、最大化、还原、隐藏…

在CentOS7.0上制作openstack-juno本地yum源 .doc

在CentOS7.0上制作openstack-juno本地yum源参考文献&#xff1a; 2014/09/27 | http://www.kekeyun.net/?p222可可云计算网以http://www.kekeyun.net/?p222文为参考&#xff0c;在CentOS7.0上制作本地源&#xff0c;过程如下&#xff1a;一、创建CentOS7虚拟主机安装过程有…

【C语言简单说】二:第一个C语言程序详解(1)

如有错误请给与纠正… 上一个教程只说明了第一个C语言程序源码中的&#xff1a; printf("Hello Wrold!"); 这行代码的含义&#xff0c;现在我们来说说全部代码&#xff1b;当然为了各位的方便&#xff0c;我就把那个代码给复制过来了&#xff0c;如下: #include&…

C++之智能指针和普通指针单例模式两种实现

1 问题 实现c++的单例模式,这里测试分别写了通过智能指针返回对象和普通返回指针 2 代码测试 include <iostream> #include <mutex> #include <memory>using namespace std;class Single { public:static Single& getInstance(){std::mutex mt;if (…

mybatis 返回 插入的主键

2019独角兽企业重金招聘Python工程师标准>>> 一般返回的是 数据库的 自增的 主键&#xff0c;&#xff0c;&#xff0c; 百度了一通&#xff0c;&#xff0c;我 刚开始 以后 可以 通过 插入的方法的&#xff0c;&#xff0c; 返回值 可以获取到 自增的主键&#xff…

Source Generator实战

前言最近刷B站的时候浏览到了老杨的关于Source Generator的简介视频。其实当初.Net 6刚发布时候看到过微软介绍这个东西&#xff0c;但并没有在意。因为粗看觉得这东西限制蛮多的&#xff0c;毕竟C#是强类型语言&#xff0c;有些动态的东西不好操作&#xff0c;而且又有Fody、N…

python图片解析库_python用来获得图片exif信息的库实例分析

本文实例讲述了python用来获得图片exif信息的库用法。分享给大家供大家参考。具体分析如下&#xff1a; exif-py是一个纯python实现的获取图片元数据的python库&#xff0c;官方下载地址&#xff1a; http://exif-py.svn.sourceforge.net/viewvc/exif-py/source/EXIF.py?revis…

Linux Swap分区设定

因为准备在linux上面安装Oracle数据库&#xff0c;据说swap分区小于4G容易失败&#xff0c;天啦噜的我连swap分区是啥都不是非常清楚&#xff0c; 大概有个印象吧&#xff0c;但先搞大了再说。 测试证明Ubuntu14默认的swap分区是和初期设定的内存大小一样一样的。 最初因为手速…

java servlet https_javaweb项目对https的配置01

1.准备证书生成a.进入到jdk下的bin目录(如果配置了Java的环境&#xff0c;可以直接在cmd命令窗口中直接输入如下命令)keytool -v -genkey -alias tomcat -keyalg RSA -keystore d:/tomcat.keystore -validity 36500附&#xff1a;d:/tomcat.keystore是将生成的tomcat.keystore放…

OC开发_Storyboard——MapKit

一、Core Location 1、基本对象 propertys: coordinate, altitude, horizontal/verticalAccuracy, timestamp, speed, course property (readonly) CLLocationCoordinate2D coordinate; typedef { CLLocationDegrees latitude; // double型 纬度 CLLocationDegrees longitu…

【C语言简单说】二:第一个C语言程序详解(2)

如有错误请给与纠正… (_)? 不知道你在什麼 其实这一节可以跳过&#xff0c;不信你往下看… 上一个教程只说明了第一个C语言程序源码中的头文件&#xff1a; #include<stdio.h> #include<stdlib.h> 照例&#xff0c;我又把这一节说的源代码的内容给复制过来&a…

Effective C++学习笔记之copy构造函数和default函数和copy赋值函数(operator=)

1 、C一个空的类里面一般默认的函数 比如我们写 class A {}; 一般里面系统会给你哪些默认函数呢&#xff1f; class A { public:A(){} //default函数~A(){} //析构函数A(const A& a) {} //copy构造函数A& operator (const A& a) {} //copy assignment操…

python学习笔记 --- 随机数进阶

你真的懂随机数&#xff1f; Author : Jasper YangSchool : Bupt Q:为什么要写这篇文章&#xff1f;A:因为我发现在最近的科学计算中&#xff0c;常常遇到随机数&#xff0c;所有的随机数都是基于0,1随机&#xff0c;而这个0,1随机怎么实现呢&#xff1f;下面我会娓娓道来~ 这篇…

一套关于 内存对齐 的C#面试题,做错的人很多!

这是一套朋友公司的面试题&#xff0c;挺有意思分享一下。题目&#xff1a;判断下面的 Location1 和 Location2 的结构体大小各是多少&#xff1f;public struct Location1{public int X;public int Y;public long Z;}public struct Location2{public int X;public long Y;publ…

pythonweb服务器怎么让别人访问_Django配置让其他电脑访问网站

其实在Django 带有一个内建的轻量级 Web 服务器&#xff0c;可供站点开发过程中使用。我们提供这个服务器是为了让你快速开发站点&#xff0c;也就是说在准备发布产品之前&#xff0c;无需进行产品级 Web 服务器&#xff08;比如 Apache&#xff09;的配置工作。 但是实际开发中…

python3-day4(装饰器)

一.基本 第一波 #### def foo():print foofoo #表示是函数 foo() #表示执行foo函数#### 第二波 #### def foo():print foofoo lambda x: x 1foo() # 执行下面的lambda表达式&#xff0c;而不再是原来的foo函数&#xff0c;因为函数 foo 被重新定义了二.example #一个…

【C语言简单说】二:第一个C语言程序详解(3)

如有错误请给与纠正… 注&#xff1a;注意我们每一行代码后面的分号表示我们一句代码的结束&#xff0c;就像我们在写文字的时候的标点符号&#xff0c;一个句号表示一句话的结尾。 上一个教程只说明了第一个C语言程序源码中的main&#xff08;其实等于没说&#xff09;&…

【转载】关于测试人员的职业发展

近期由于项目组人手不够&#xff0c;需要招聘一些测试人员。本周及上周陆陆续续面试了十多个应征者&#xff0c;工作年限在2年~9年之间&#xff0c;但无一满意。期间&#xff0c;种种感叹&#xff0c;回想起去年面试六十余人仅有3人满足要求&#xff0c;如有鲠在喉&#xff0c;…

python之闭包

1 闭包概念 绑定了函数内部引用的所有变量&#xff0c;把它引用的东西都放在一个上下文中“包”了起来 2 闭包的Demo理解 需求:比如我们要实现2个函数,每个函数有个参数,然后现在需要实现这2个函数参数的相加功能 1) 不用闭包python普通实现 #!/usr/bin/env pythondef plus…