java自定义注解annotation记录操作日志

说到注解我们平常用的可以说非常多啦,说几个常用的的注解 @RestController @Service @Autowired
这些都是我们平常使用spring框架最常见的注解了,我们只知道它们非常好用,使用@RestController 就能构建一个restful的控制器,@Service 这个是我们常用的mvc架构中的业务层使用的注解,将类交给spring容器管理,我们要用的话直接使用@Autowired就能将类自动注入。我们都知道用了这些注解非常的方便,今天我们自己也来写一个自己的注解。

需求

一个项目,有些方法是需要被保护起来的,有写方法是开放出来不需要保护的,比如登录 注册等 都不需要保护,解决方案有很多,今天我们就使用springboot的aop 和自定义注解来解决这个需求。
在创建自己的注解之前,了解一些注解的知识。
1.首先java jdk给我们提供了meta-annotation用于自定义注解的时候使用,这四个注解为:@Target,@Retention,@Documented 和@Inherited。

  • 第一个注解@Target
    @Target:用于描述注解的使用范围(即:被描述的注解可以用在什么地方),其源码如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Target {ElementType[] value();
}

我们可以看到它只有一个属性值,是个枚举类型的数组,我们进该枚举类型看看

public enum ElementType {TYPE,//用于描述类、接口(包括注解类型) 或enum声明FIELD, //用于描述成员变量;METHOD,//用于描述方法PARAMETER,//用于描述参数CONSTRUCTOR,//用于描述构造器LOCAL_VARIABLE,//用于描述局部变量;ANNOTATION_TYPE,//注解类型声明 该注解可用于描述注解PACKAGE,//用于描述包TYPE_PARAMETER,//这个是jdk1.8后加入的类型  表示这个 Annotation 可以用在 Type 的声明式前TYPE_USE//表示这个 Annotation 可以用在所有使用 Type 的地方(如:泛型,类型转换等)
}
  • 第二个注解@Retention
    @Retention:指定被描述的注解在什么范围内有效。源码如下:
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {RetentionPolicy value();
}

可以看到,该注解也只有一个枚举的属性,我们进该枚举类型看看

public enum RetentionPolicy {SOURCE,//表示描述程序编译时CLASS,//在class文件中有效(即class保留RUNTIME//在运行时有效(即运行时保留)
}
  • 第三个注解:@Documented

@Documented 是一个标记注解,木有成员,用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Documented {
}
  • 第四个注解 @Inherited

@Inherited 元注解是一个标记注解,@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {RetentionPolicy value();
}

下面我们开始编写我们自己的注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface IgnoreToken {
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Log {String name() default "";
}

编写aop拦截所有的controller请求

@Component
@Aspect
@Order(1)
public class TokenAspect {@Autowiredprivate HttpServletRequest request;@Autowiredprivate HttpServletResponse response;@Autowiredprivate LoginController loginController;@Pointcut("within(com.niehziliang.annotation.demo.controller..*)")public void checkToken () {}@Before("checkToken()")public void checkToken (JoinPoint joinPoint) throws IOException {MethodSignature signature = (MethodSignature)joinPoint.getSignature();//获取当前访问的类方法Method targetMethod = signature.getMethod();//判断是否是注解修饰的类,如果是则不需要校验tokenif(!targetMethod.isAnnotationPresent(IgnoreToken.class)){String token = request.getParameter("token");if (null == token || "".equals(token)) {response.setCharacterEncoding("utf-8");response.setContentType("application/json; charset=utf-8");PrintWriter out = response.getWriter();out.print("token不能为空");out.flush();out.close();} else {if (!loginController.chkToken(token)) {response.setCharacterEncoding("utf-8");response.setContentType("application/json; charset=utf-8");PrintWriter out = response.getWriter();out.print("token不合法");out.flush();out.close();}}}}}

aop日志拦截

@Component
@Aspect
@Order(2)
public class LogAspect {@Autowiredprivate HttpServletRequest request;@Autowiredprivate LoginController loginController;@Pointcut("@annotation(com.niehziliang.annotation.demo.annos.Log)")public void saveLog() {}@Around("saveLog()")public Object saveLog(ProceedingJoinPoint point) throws Throwable {long start = System.currentTimeMillis();MethodSignature signature = (MethodSignature) point.getSignature();Method method = signature.getMethod();Log logAnnotation = method.getAnnotation(Log.class);String name = null;if (logAnnotation != null) {// 注解上的描述name = logAnnotation.name();}// 请求的方法名String className = point.getTarget().getClass().getName();String methodName = signature.getName();// 请求的方法参数值Object[] args = point.getArgs();LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();String[] paramNames = u.getParameterNames(method);String params = "";if (args != null && paramNames != null) {for (int i = 0; i < args.length; i++) {params += "  " + paramNames[i] + ": " + args[i];}}String ip = IpUtils.getIpAddress(request);long time = System.currentTimeMillis() - start;StringBuffer log = new StringBuffer();log.append("注解上的name:").append(name).append("=======").append("请求的方法:").append(className).append(".").append(methodName).append("=====").append("请求参数:").append(params).append("=======").append("请求的ip:").append(ip).append("耗时:").append(time).append("ms");System.out.println(log.toString());loginController.saveLog(log.toString());return point.proceed();}
}

编写controller代码, 登录方法加了我自己定义的注解@IgnoreToken aop在拦截的时候判断有我们自己定义注解就不会去校验token啦,获取密码的方法则会进行token的校验

@RestController
public class LoginController {public static Map<String,String> map = new HashMap<>();public static List<String> logList = new ArrayList<>();public static Set<String> tokenSet = new HashSet<>();@RequestMapping(value = "login")@IgnoreToken@Logpublic String login(String userName,String password) {map.put(userName,password);//保存tokentokenSet.add(userName+password);//返回tokenreturn userName+password;}@RequestMapping(value = "query")@Log(name = "获取密码")public String getPassword(String userName) {//获取用户密码return map.get(userName);}@RequestMapping(value = "logs")@Log(name = "获取日志信息")public String getLogMap() {return JSON.toJSONString(logList);}}

下面我在浏览器输入请求登录地址进行登录

// 登录获取token
http://127.0.0.1:8080/login?userName=admin&password=adminadmin

在这里插入图片描述

不带token访问受保护的方法

// 获取用户密码
http://127.0.0.1:8080/query?userName=admin

在这里插入图片描述

带正确的token访问受保护的犯法

// 获取用户密码
http://127.0.0.1:8080/query?userName=admin&token=adminadminadmin
12

在这里插入图片描述

获取用户访问日志信息
在这里插入图片描述

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

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

相关文章

数组concat_js 标准二维数组变一维数组的方法

问题&#xff1a;[[1, 1], [2, 3], [4, 5]] -> [1, 1, 2, 3, 4, 5]&#xff1f;方法一利用es5的arr.reduce(callback[, initialValue])实现var arr1 [[0, 1], [2, 3], [4, 5]]; var arr2 arr1.reduce(function (a, b) { return a.concat(b)} ); // arr2 [0, 1, 2, 3, 4, 5…

java 自定义注解+AOP实现日志记录

ssm版本&#xff1a; 1、首先自定义一个注解&#xff0c;该注解有两个属性&#xff0c;一个是模块名&#xff0c;一个是操作的内容。该注解是用来修饰Service层中的方法的。 2、创建一个切面类&#xff0c;该切面使用Aspect和Component注解修饰&#xff0c;该页面需要注入一个…

是人是谁_谁是白鹤滩最可爱的人

白鹤滩水电站是全球在建第一大水电站&#xff0c;主要特性指标均位居世界水电工程前列&#xff0c;2021年7月&#xff0c;首批机组投产发电将是白鹤滩工程为建党一百周年献礼的重大壮举。建设中的白鹤滩水电站工程建设不停步&#xff0c;白鹤滩水电站未来的运行管理者——白鹤滩…

potplayer 多个进程_进程组、会话、控制终端概念,如何创建守护进程?

守护进程概念&#xff1a;守护进程&#xff0c;也就是通常所说的Daemon进程&#xff0c;是Linux中的后台服务进程。周期性的执行某种任务或等待处理某些发生的事件。Linux系统有很多守护进程&#xff0c;大多数服务都是用守护进程实现的。比如&#xff1a;像我们的tftp&#xf…

acs880 用户手册_华中数控、广州数控系统用户手册

数控加工仿真系统 广州数控系统用户手册上海宇龙软件工程有限公司2004 年 5 月华中数控、广州数控系统用户手册 目录I目录第一章 基本操作 ............................................................................................ 1 1.1 项目文件 ...................…

亚马逊出的平板电脑_美国最畅销的安卓平板电脑,还只有2GB内存

在美国除了iPad&#xff0c;谁家的平板电脑卖得最好&#xff1f;不是华为小米&#xff0c;也不是微软或谷歌&#xff0c;而是Amazon亚马逊。主打入门级定位的亚马逊Fire系列平板电脑&#xff0c;在北美的平板市场上&#xff0c;有着举足轻重的地位。今天&#xff0c;亚马逊正式…

对接kafka_Kafka系列9:面试题是否有必要深入了解其背后的原理?我觉得应该刨根究底(上)...

​前言在本文开始之前&#xff0c;作者一直有个疑惑&#xff0c;就是面试题是只写写问题和答案就草草了事&#xff0c;还是应该深入分析一下其背后发生的一些原理。和朋友探讨以后作者还是决定采用后者的方式&#xff0c;因为我认为不仅要做到知其一&#xff0c;更要知其二&…

资源不足的情况怎么设置sparkrdd并行度_监控录像机资源不足或达到上限的原因及解决方法!...

在安装网络监控摄像机过程中&#xff0c;很多人遇到硬盘录像机画面上提升“资源不足”或性能“达到上限”的问题&#xff0c;新手遇到这样的问题会选择重启录像机&#xff0c;但是几次反复发现并不能解决。监控录像机资源不足或达到上限的原因及解决方法&#xff01;首先这种提…

主动变被动9个例句_高中英语 :主动表被动的适用范围

1. 表衡量的动词。The room measures 5 by 6.2. sell, write, wash, read, wear, keep, drink等表状态的情况下。The pen writes well. The clothes wash well.3. 在动词不定式中主语发出的动作。I have a lot of work to do.4. 动词不定式前面的词为形容词时。The question …

为什么要重写hashcode方法和equals方法

为什么要重写hashcode方法和equals方法 我们可能经常听到说重写equals方法必须重写hashcode方法&#xff0c;这是为什么呢&#xff1f;java中所有的类都是Object的子类&#xff0c;直接上object源码 /** Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights …

python代码_python爬虫19 | 遇到需要的登录的网站怎么办?用这3招轻松搞定!

你好由于你是游客无法查看本文请你登录再进谢谢合作当你在爬某些网站的时候需要你登录才可以获取数据咋整&#xff1f;莫慌小帅b把这几招传授给你让你以后从容应对那么接下来就是学习 python 的正确姿势登录的常见方法无非是这两种1、让你输入帐号和密码登录2、让你输入帐号密码…

利用电脑上自带指纹识别嵌入程序中_Win 10 隐藏功能:不用任何软件就可实现手机投屏到电脑...

投屏工具我也介绍了不少&#xff0c;所有的都是需要安装第三方软件的。不过&#xff0c;其实 Windows 10 就自带了手机投影到电脑的功能&#xff0c;不需要任何软件就能实现。在设置中打开系统&#xff0c;找到投影到此电脑&#xff0c;在红框中根据你的需要设置好&#xff0c;…

为什么要重写hashCode()方法和equals()方法以及如何进行重写

一、前言 本篇文章主要探讨的问题有三个&#xff1a; 1、首先我们为什么需要重写hashCode()方法和equals()方法&#xff1f; 2、在什么情况下需要重写hashCode()方法和equals()方法&#xff1f; 3、如何重写这两个方法&#xff1f; 二、为什么需要重写hashCode()方法和equal…

bloomberg用法 固定收益_内部收益率的用法浅谈某保险的真实收益率

公司财务课程&#xff0c;魏教授讲得非常棒&#xff0c;治愈了大家的瞌睡&#xff0c;激起了大家的学习热情。我一直认为&#xff0c;大牛在讲课&#xff0c;吹牛还是演讲中&#xff0c;都能够给现场观众提供强大的能量&#xff0c;使得彼此运行在同一个共振频率。内部收益率(I…

联想小新锐7000主板型号_2020年高性价比游戏本选购推荐指南——7000价位游戏本推荐...

玩电脑的老猫&#xff0c;只说你最想听的话&#xff01;大家好&#xff0c;我是老猫&#xff0c;这段时间很多小伙伴问我&#xff0c;多少钱能买到一台不错的游戏本呢&#xff1f;知乎中很多人说5000元买游戏本&#xff0c;就是等于买一台“电子垃圾”虽然5000元的游戏本不是非…

Java重写equals方法时为什么要重写hashCode方法

在我们平时编写Java代码时&#xff0c;重写equals方法时一定要重写hashCode方法&#xff0c;这是为什么呢&#xff1f; 在讨论这个问题前&#xff0c;我们先看下Object类中hashCode方法和equals方法。 hashCode方法&#xff1a; 翻译如下&#xff1a; equals方法&#xff1a;…

iot nb 曹淑敏 鹰潭_移动物联时代来啦 鹰潭一项成就为全球首个 江西力争在全国“四个领先”...

移动物联网是基于移动通信网络的物联网技术体系&#xff0c;主要由NB-IoT(窄带物联网技术)、eMTC(增强机器类通信技术)、蜂窝网的未来演进技术5G(第五代移动通信技术)三种技术共同构成。江西网络广播电视台9月1日讯(记者 李希文)9月1日下午&#xff0c;江西省工信委、中国信息通…

RPC(一)[概述]

文章目录RPC-概述简介1.服务的调用过程2.RPC框架1.Dubbo–电商2.Motan–互联网3.Thrift4.gRPC5.RPCX3.RPC 和 RESTful1.RPC over HTTP 和 RESTful2.RPC over TCP 和 RESTfulRPC-概述 简介 远程过程调用&#xff08;Remote Procedure Call&#xff0c;缩写为 RPC&#xff09;是…

epic登陆按钮一直在转_双剑合璧!GOG GALAXY 2.0官方支持Epic商店集成

2020年7月21日晚&#xff0c;GOG官方宣布提供与Epic商城的集成服务&#xff0c;这也是GOG GALAXY 2.0推出以来又一次与超大型游戏平台达成的合作。现在玩家可以通过GOG GALAXY 2.0管理、安装和启动来自Epic商城的游戏。需要注意的是&#xff0c;因为这次行为是完全官方的&#…

用 Java 实现人脸识别功能

引言 人脸识别SDK 人脸识别技术是很复杂的&#xff0c;自己用Java手撕一个识别算法有点不切实际&#xff0c;毕竟实力不允许我这么嚣张&#xff0c;还是借助三方的SDK吧&#xff01; 找了一圈发现一个免费的人脸识别SDK&#xff1a; ArcSoft:&#xff0c;地址&#xff1a;ht…