说到注解我们平常用的可以说非常多啦,说几个常用的的注解 @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

获取用户访问日志信息

java自定义注解annotation记录操作日志相关推荐

  1. 如何在springboot项目中使用自定义注解实现系统操作日志的功能

    通常我们的项目中都需要记录操作日志,方便回溯问题,找到根源. 因为给项目添加日志记录功能是属于系统级别的功能,所以这个问题我们马上会想到spring的AOP,可以通过切面的形式.那么怎么来实现呢? 先 ...

  2. Java自定义注解Annotation的实现原理

    文章目录 1.什么是注解? 2.注解的用处: 3.注解的原理: 4.元注解: 5.常见标准的Annotation: 6.自定义注解: 7.自定义注解实例: 1.什么是注解?   对于很多初次接触的开发 ...

  3. springmvc 切面记录操作日志

    <!-- 启动对@AspectJ注解的支持 --> <aop:aspectj-autoproxy proxy-target-class="true" /> ...

  4. slf4j注解log报错_SpringBoot自定义日志注解,用于数据库记录操作日志,你用过吗?...

    大家好,我是程序员7歌! 今天我将为大家讲解如何通过自定义注解记录接口访问日志.一般的开发中,有两种方式可以记录日志信息,第一种:把接口日志信息保存到日志文件中,第二种:把接口操作日志保存到数据库中, ...

  5. spring中自定义注解(annotation)与AOP中获取注解___使用aspectj的@Around注解实现用户操作和操作结果日志

    spring中自定义注解(annotation)与AOP中获取注解 一.自定义注解(annotation) 自定义注解的作用:在反射中获取注解,以取得注解修饰的类.方法或属性的相关解释. packag ...

  6. JAVA记录操作日志步骤

    项目地址:https://gitee.com/Selegant/logs-demo.git 说明 系统日志不论是在日常的管理还是维护中都会起到很大的作用,但是在日志的记录中通常会存在很多的问题 日志记 ...

  7. 记录操作日志(JAVA版某大厂基础实践)

    1. 操作日志的使用场景 2. 实现方式 2.1 使用 Canal 监听数据库记录操作日志 2.2 通过日志文件的方式记录 2.3 通过 LogUtil 的方式记录日志 2.4 方法注解实现操作日志 ...

  8. 数据脱敏——基于Java自定义注解实现日志字段脱敏

    上文说了数据过敏主要有两个思路:第一个就是在序列化实体之前先把需要脱敏的字段进行处理,之后正常序列化:第二个就是在实体序列化的时候,对要脱敏的字段进行处理. 脱敏实现思路 这里探讨第一种方法,用基于自 ...

  9. 如何使用SpringBoot AOP 记录操作日志、异常日志?

    点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:咫尺的梦想_w cnblogs.com/wm-dv/ ...

最新文章

  1. Docker多阶段镜像构建Dockerfile脚本示例:构建nodejs前端项目
  2. 开源开放 | 多模态实体链接数据集MELBench(CCKS2021)
  3. Soul递交IPO招股书:腾讯为第一大股东,依然处于亏损状态
  4. 华为金融业务部总裁曹冲:没有进入支付市场的计划
  5. 人脸表情识别从0到部署,猜猜『轮到你了』的微笑狼人到底是谁!
  6. jdk7 HashSet和HashMap源码分析
  7. Python实战案例:金庸的功夫流派、人物关系的分析案例(下)
  8. MATLAB与STK互联23:卫星对象操作(14)—仿真分析案例1,建立8个地面站,分析对卫星的可见性
  9. 十三种Java开发工具
  10. android CTS GTS 环境搭建
  11. 中国人民银行招聘计算机考什么,求中国人民银行招聘计算机专业人员的考试题。...
  12. MONGODB的压力测试
  13. IDEA——问题汇总
  14. IDEA+Java控制台实现宠物管理系统
  15. 用python画玫瑰花
  16. usgs dem 导入matlab 程序,用GDAL打开从USGS下载的img影像文件
  17. python常见算法(chatgpt算法实现)
  18. [CDQ分治与整体二分]个人对CDQ分治与整体二分的理解
  19. 原神QQ机器人云崽bot安卓手机整合包解压即用安装教程
  20. 沈阳故宫挂“门神”迎新年

热门文章

  1. 进度条设置_为你的练习设置进度条
  2. 图像增强_Keras 常用的图像增强方式
  3. 用2468这四个数字c语言,C语言作业及参考答案.doc
  4. 合并排序算法排序过程_外部合并排序算法
  5. java相关是什么,什么是java
  6. 东北大学 计算机技术导师,报考东北大学 计算机技术 329分 求调剂相关专业
  7. android界面设计字体大小,Andoird用户界面设计上手指南:设置字体大小
  8. 绘图的尺寸_Auto CAD机械绘图尺寸标注教程1(尺寸标注简介)
  9. 绝了,66道并发多线程面试题汇总
  10. 图文并茂的聊聊Java内存模型!