使用aop切面编写日志模块
我们先自定义一个注解(一个有关自定义注解的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切面编写日志模块的更多相关文章
- Logstash+ Kafka基于AOP 实时同步日志到es
Logstash是一个开源数据收集引擎,具有实时管道功能.Logstash可以动态地将来自不同数据源的数据统一起来,并将数据标准化到你所选择的目的地,logstash丰富的插件(logstash-in ...
- SpringBoot2.0 基础案例(11):配置AOP切面编程,解决日志记录业务
本文源码 GitHub地址:知了一笑 https://github.com/cicadasmile/spring-boot-base 一.AOP切面编程 1.什么是AOP编程 在软件业,AOP为Asp ...
- 十:SpringBoot-配置AOP切面编程,解决日志记录业务
SpringBoot-配置AOP切面编程,解决日志记录业务 1.AOP切面编程 1.1 AOP编程特点 1.2 AOP中术语和图解 2.SpringBoot整合AOP 2.1 核心依赖 2.2 编写日 ...
- Spring MVC通过AOP切面编程 来拦截controller 实现日志的写入
首选需要参考的是:[参考]http://www.cnblogs.com/guokai870510826/p/5977948.html http://www.cnblogs.com/guokai8 ...
- 如何优雅地在 Spring Boot 中使用自定义注解,AOP 切面统一打印出入参日志 | 修订版
欢迎关注个人微信公众号: 小哈学Java, 文末分享阿里 P8 资深架构师吐血总结的 <Java 核心知识整理&面试.pdf>资源链接!! 个人网站: https://www.ex ...
- Spring Boot 2.0 教程 | AOP 切面统一打印请求日志
欢迎关注微信公众号: 小哈学Java 文章首发于个人网站 https://www.exception.site/springboot/spring-boot-aop-web-request 本节中,您 ...
- Springboot项目使用aop切面保存详细日志到ELK日志平台
上一篇讲过了将Springboot项目中logback日志插入到ELK日志平台,它只是个示例.这一篇来看一下实际使用中,我们应该怎样通过aop切面,拦截所有请求日志插入到ELK日志系统.同时,由于往往 ...
- Spring Boot 自定义注解,AOP 切面统一打印出入参请求日志
其实,小哈在之前就出过一篇关于如何使用 AOP 切面统一打印请求日志的文章,那为什么还要再出一篇呢?没东西写了? 哈哈,当然不是!原因是当时的实现方案还是存在缺陷的,原因如下: 不够灵活,由于是以所有 ...
- Spring Boot 中使用自定义注解,AOP 切面打印出入参日志及Dubbo链路追踪透传traceId
一.使用背景 开发排查系统问题用得最多的手段就是查看系统日志,在分布式环境中一般使用 ELK 来统一收集日志,但是在并发大时使用日志定位问题还是比较麻烦,由于大量的其他用户/其他线程的日志也一起输出穿 ...
随机推荐
- SqlServer2005 查询 第二讲 distinct
今天我们来说distinct关键字的用法. distinct - distinct:我们可以这样理解成[过滤重复值] - select distinct deptno from emp // -- 首 ...
- nyoj 14-会场安排问题 (贪心)
14-会场安排问题 内存限制:64MB 时间限制:3000ms Special Judge: No accepted:9 submit:15 题目描述: 学校的小礼堂每天都会有许多活动,有时间这些活动 ...
- npm报错:无法加载文件 D:\nodejs\node_global\webpack.ps1,因为在此系统上禁止运行脚本
npm报错 在 windows终端输入 vue init webpack app, 创建一个名为 app 的 Vue 项目时报错如下: 无法加载文件 D:\nodejs\node_global\web ...
- 自动安装 linux 系统
实现自动安装 centos 6 和 centos 7 实现自动安装 Linux 系统需要在虚拟机上安装三个服务:apache .tftp.dhcp 三个服务放在一台虚拟机上即可 一.DHCP 服务器的 ...
- django_3:url配置
浏览器url访问——url.py中正则匹配——转向对应的视图处理方法——在view.py中找到方法执行——在方法中一般会用到render渲染到.html文件——再用到.html url使用方式: 正则 ...
- PHP产生不重复随机数的5个方法总结
无论是Web应用,还是WAP或者移动应用,随机数都有其用武之地.在最近接触的几个小项目中,我也经常需要和随机数或者随机数组打交道,所以,对于PHP如何产生不重复随机数常用的几种方法小结一下 无论是We ...
- 关于element-ui级联菜单(城市三级联动菜单)和回显问题
https://segmentfault.com/a/1190000020458087 这是我写的,可以去看看,希望对你们有帮助!!!
- 缓冲&缓存&对象池概念的理解
一).缓冲 作用:缓解程序上下层之间的性能差异. 1).当上层组件的性能优于下层组件时加入缓冲机制可以减少上层组件对下 层组件的等待时间. 2).上层组件不需要等待下层组件接收全部数据,即可返回操作, ...
- pwnable.kr 第一天
1.FD 直接通过ssh连接上去,然后,看下源代码. #include <stdio.h> #include <stdlib.h> #include <string.h& ...
- 基于crypto++国产加密软件SM4的实现,顺带加了ase,base64
唔,美国压制得越狠,各种替代产品就越能活. 本文分享SM4的一种快速实现与集成方式. SM4(原名SMS4)是中华人民共和国政府采用的一种分组密码标准,由国家密码管理局于201 ...