我们先自定义一个注解(一个有关自定义注解的LJ文章 https://www.cnblogs.com/guomie/p/10824973.html

/**
*
* 自定义日志注解
* Retention(RetentionPolicy.RUNTIME) 生命周期永远不会被丢弃
* Target(ElementType.METHOD) 作用于方法上
* Documented
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface LogAnnotation { // 描述
String actiondese() default ""; //类型
public enum Logtype {ADD,UPDATE,DEL,SET,LOGIN,LOGOUT,MESSAGE}; Logtype actionvalue() default Logtype.ADD;
}

我们编写一个切面类

@Aspect
@Component
public class LogAop {
@Autowired
private RedisService redisService; @Autowired
private LogService logService; // 切点
// @Pointcut("execution(* com.monitoring.controller..*.*(..))")
@Pointcut("@annotation(com.annotations.LogAnnotation)")
private void controllerAspect() {} //增强
@Around("controllerAspect()")
public Object log(ProceedingJoinPoint pjp )throws Throwable{     //先运行目标方法
Object object = pjp.proceed(); //获取request
RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest(); // 拦截当前方法的对象
Object target = pjp.getTarget();
// 获取正在拦截方法名称
String methodName = pjp.getSignature().getName();
// 获取方法的参数
Object[] args = pjp.getArgs();
// 获取请求的路径
// String requestURI = request.getRequestURI(); // 拦截的放参数类型
Signature sig = pjp.getSignature();
MethodSignature msig = null;
if (!(sig instanceof MethodSignature)) {
throw new IllegalArgumentException("该注解只能用于方法");
}
msig = (MethodSignature) sig;
Class[] parameterTypes = msig.getMethod().getParameterTypes(); Method method = null;
String actionType = "07";
String actionDesc = "";
try { // 获取当前方法
method = target.getClass().getMethod(methodName, parameterTypes); } catch (NoSuchMethodException | SecurityException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
} if (null != method) { // 获取方法上的注解
LogAnnotation annotation = method.getAnnotation(LogAnnotation.class);
if(null == annotation) {
return object;
}
// 获取注解上的信息
actionDesc = annotation.actiondese();
// 获取类型
Logtype actionvalue = annotation.actionvalue(); switch (actionvalue) {
case ADD:
actionType = "00";
break;
case UPDATE:
actionType = "01";
break;
case DEL:
actionType = "02";
break;
case SET:
actionType = "03";
break;
case LOGIN:
actionType = "04";
break;
case LOGOUT:
actionType = "05";
break;
case MESSAGE:
actionType = "06";
break;
default:
actionType = "07";
break;
}
} // 获取访问真实IP
String internetIp = request.getHeader("x-forwarded-for");
if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
internetIp = request.getHeader("Proxy-Client-IP");
}
if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
internetIp = request.getHeader("WL-Proxy-Client-IP");
}
if (internetIp == null || internetIp.length() == 0 || "unknown".equalsIgnoreCase(internetIp)) {
internetIp = request.getRemoteAddr();
if (internetIp.equals("127.0.0.1") || internetIp.equals("0:0:0:0:0:0:0:1")) {
// 根据网卡取本机配置的IP
InetAddress inet = null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
internetIp = inet.getHostAddress();
} }
//对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (internetIp != null && internetIp.length() > 15) { // "***.***.***.***".length() = 15
if (internetIp.indexOf(",") > 0) {
internetIp = internetIp.substring(0, internetIp.indexOf(","));
}
} // 创建日志对象用于保存
BsUserLog4j log = new BsUserLog4j();
BsUserInfo user = JsonUtils.jsonToPojo(redisService.get(args[0].toString()), BsUserInfo.class) ; //用户登出
if(actionType == "04") {
//删除缓存中的token值
redisService.del(args[0].toString());
System.out.println("已删除缓存中token值");
}
//设置时间
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String actionTime=sdf.format(new Date()); // 设置log信息并保存数据库
log.setLogId(new BigDecimal(IDUtils.genId()));
log.setUsername(user.getUsername());
log.setActionType(actionType);
log.setActionTime(actionTime);
log.setActionDesc(actionDesc);
log.setInternetIp(internetIp); //添加日志到数据库
logService.addLog(log);
System.out.println("添加日志: " + log.toString()); //最后返回目标方法
return object;
}
}

在配置里里面配置有关aop的配置

<beans   xmlns:aop="http://www.springframework.org/schema/aop"  xsi:schemaLocation="http://www.springframework.org/schema/aop  http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" <beans>

<!-- 自动为@aspectJ切面bean创建代理,true表示使用CGLib来创建 -->
<aop:aspectj-autoproxy proxy-target-class="true" />

controller层代码

@LogAnnotation(actiondese="用户登录",actionvalue=Logtype.LOGIN)
@RequestMapping("/loginTest")
@ResponseBody
public CarResult loginTest(HttpServletResponse response,HttpServletRequest request, String name,String pas,String phoneNumer){}

其中还会遇到一些问题

1. error at ::0 formal unbound in pointcut

当出现这个错误的时候 表示你的通知方法得带上参数 比如

但是 request 不能通过参数传递进来 只能通过下面方式来获取

RequestAttributes requestAttributes =  RequestContextHolder.getRequestAttributes();
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) requestAttributes;
HttpServletRequest request = servletRequestAttributes.getRequest();

2.目标方法不执行

  这时候我们需要先执行目标方法,然后再讲目标方法通过返回值返回出去

使用aop切面编写日志模块的更多相关文章

  1. Logstash+ Kafka基于AOP 实时同步日志到es

    Logstash是一个开源数据收集引擎,具有实时管道功能.Logstash可以动态地将来自不同数据源的数据统一起来,并将数据标准化到你所选择的目的地,logstash丰富的插件(logstash-in ...

  2. SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务

    本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Asp ...

  3. 十:SpringBoot-配置AOP切面编程,解决日志记录业务

    SpringBoot-配置AOP切面编程,解决日志记录业务 1.AOP切面编程 1.1 AOP编程特点 1.2 AOP中术语和图解 2.SpringBoot整合AOP 2.1 核心依赖 2.2 编写日 ...

  4. Spring MVC通过AOP切面编程 来拦截controller 实现日志的写入

    首选需要参考的是:[参考]http://www.cnblogs.com/guokai870510826/p/5977948.html    http://www.cnblogs.com/guokai8 ...

  5. 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版

    欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...

  6. Spring Boot 2.0 教程 | AOP 切面统一打印请求日志

    欢迎关注微信公众号: 小哈学Java 文章首发于个人网站 https://www.exception.site/springboot/spring-boot-aop-web-request 本节中,您 ...

  7. Springboot项目使用aop切面保存详细日志到ELK日志平台

    上一篇讲过了将Springboot项目中logback日志插入到ELK日志平台,它只是个示例.这一篇来看一下实际使用中,我们应该怎样通过aop切面,拦截所有请求日志插入到ELK日志系统.同时,由于往往 ...

  8. Spring Boot 自定义注解,AOP 切面统一打印出入参请求日志

    其实,小哈在之前就出过一篇关于如何使用 AOP 切面统一打印请求日志的文章,那为什么还要再出一篇呢?没东西写了? 哈哈,当然不是!原因是当时的实现方案还是存在缺陷的,原因如下: 不够灵活,由于是以所有 ...

  9. Spring Boot 中使用自定义注解,AOP 切面打印出入参日志及Dubbo链路追踪透传traceId

    一.使用背景 开发排查系统问题用得最多的手段就是查看系统日志,在分布式环境中一般使用 ELK 来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,由于大量的其他用户/其他线程的日志也一起输出穿 ...

随机推荐

  1. linux 修改IP地址(设置为静态ip)和主机名

    主机名: server0.example.com ip地址: 172.25.0.11 网络掩码: 255.255.255.0 默认网关: 172.25.0.254 域名服务器:172.25.254.2 ...

  2. nyoj 209 + poj 2492 A Bug's Life (并查集)

    A Bug's Life 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 Background  Professor Hopper is researching th ...

  3. win10添加启动项目

    Win10启动文件夹一般位于C:\ProgramData\Microsoft\Windows\Start Menu(开始菜单)\Programs(程序)\StartUp(启动)目录,我们主要讲希望添加 ...

  4. Python算法——《算法图解》笔记

    算法目录 二分查找 大O表示法 选择排序 递归 快速排序,分而治之(D&C) 散列表——字典 广度优先搜索——BFS Dijkstra算法 贪婪算法 二分查找 # 要求list是有序表,num ...

  5. ehcache监控

    引入Maven依赖 <dependency> <groupId>org.terracotta.ehcachedx.com.javabi</groupId> < ...

  6. jquery浅复制和深复制区别

    jquery浅复制和深复制区别

  7. 为什么坚果云Markdown值得使用?

    值得使用说明是被认为有价值的,值得有两种意思的解释:1.有价值,有意义:2.价钱合适,合算:那么坚果云Markdown是否是人们值得使用的呢?下面就来看看坚果云Markdown到底是什么?为什么值得使 ...

  8. HDFS原理概念扫盲

    1.概述 hdfs文件系统主要设计为了存储大文件的文件系统:如果有个TB级别的文件,我们该怎么存储呢?分布式文件系统未出现的时候,一个文件只能存储在个服务器上,可想而知,单个服务器根本就存储不了这么大 ...

  9. node.js多进程架构

    node.js是单进程应用,要充分利用多核cpu的性能,就需要用到多进程架构. 作为web服务器,不能多个进程创建不同的socket文件描述符去accept网络请求, 有经验的同学知道,如果端口被占用 ...

  10. 前后端vue和django配置

    django pip源更换 虚拟环境配置 目录和日志配置 数据库配置 用户模块自定义 异常,响应配置 xadmin vue vue基础配置 vue高级配置 vue this问题和样式配置