我们先自定义一个注解(一个有关自定义注解的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. 指定vue的v-model的类型

    作为一个菜鸟,兼只会依葫芦画瓢的搬砖it狗,并没有系统学习过vue. 在最近项目中,发现了一个奇怪的问题: 使用vant-ui 的field <van-field v-model="f ...

  2. 【并发编程】Java对并发编程的支持历史

    本博客系列是学习并发编程过程中的记录总结.由于文章比较多,写的时间也比较散,所以我整理了个目录贴(传送门),方便查阅. 并发编程系列博客传送门 本文转载,原文请点击链接 本章主要对Java并发(Con ...

  3. day 14 内置函数

    复习了解: \t   输出一个制表符,协助在输出文本时,垂直方向保持对齐 \n       换行符 print(r"\n ")  #  在字符串前面加r 不会改变字符串的内容 a ...

  4. HDFS原理概念扫盲

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

  5. SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".错误的解决方法

    1.今天新git下来的项目报错如下: SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".SLF4J: ...

  6. if判断语句的总结

    1.表达式:关系表达式或逻辑表达式: 2.表达式的运算结果应该是“真”或者“假”: 真:执行该语句:            假:跳过该语句,执行下一条语句: 3.“语句”可以是单语句也可以是复合语句: ...

  7. Chapter 07-Basic statistics(Part2 Frequency and contingency tables)

    这一部分使用在vcd包中的Arthritis数据集. > library(vcd) 载入需要的程辑包:MASS 载入需要的程辑包:grid 载入需要的程辑包:colorspace > he ...

  8. vue中computed(计算属性)和watch在实现父子组件props同步时的实际区分

    vue中computed和watch的对比是一个很有意思的话题. 看过官网教程以后,我们往往更倾向多使用computed.computed优点很多,却在某些时候不太适用. 今天我们就稍微讨论一下,当我 ...

  9. 带着canvas去流浪系列之八 碰撞

    [摘要] canvas动画-碰撞仿真 示例代码托管在:http://www.github.com/dashnowords/blogs 经过前面章节相对枯燥的练习,相信你已经能够上手canvas的原生A ...

  10. 是时候考虑让你的Spark跑在K8S上了

    [摘要] Spark社区在2.3版本开始,已经可以很好的支持跑着Kubernetes上了.这样对于统一资源池,提高整体资源利用率,降低运维成本(特别是技术栈归一)有着非常大的帮助.这些趋势是一个大数据 ...