记录使用AspectJ打印日志(SpringMVC项目)

记录使用AspectJ打印日志(SpringMVC项目)

前言

最近公司组织出题考试。小伙伴出题,然后我参与了一波。发现两个问题。
1、太久没用aop,发现切面写的没问题,但是日志不打印。
2、现在大家都用springboot,而我依然习惯用springmvc,这样一来,项目就比小伙伴们大了不知道多少,虽然我的框架是新搭建的空项目。

正文

1. 考题大意如下

找到下图标红controller其下面的所有包下类中的insert,update,delete开头的方法打印日志。
记录使用AspectJ打印日志(SpringMVC项目)

打印日志格式如下:
=请求内容=
请求地址:http://192.168.1.246:8080/insertUser
请求方式:POST
请求类方法:ResultEntity com.crcb.controller.LoginController.insertUser(UserEntity)
请求参数:user,{“password”:“2”,“username”:“1”}
请求CLASS_METHOD : com.crcb.controller.LoginController.insertUser
=请求内容=
--------------返回内容----------------
Response内容:{“data”:“用手机登录成功”,“retcode”:200,“retdesc”:“成功”}
--------------返回内容----------------

2. 解题如下:

1. SpringMVC项目集成AspectJ

1.1. 依赖文件

<!-- begin AspectJ -->
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>${org.aspectj-version}</version>
    </dependency>
    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>${org.aspectj-version}</version>
    </dependency>
    <!-- end AspectJ -->

1.2 配置文件
在springmvc的容器配置文件中加入以下两行代码:

<aop:aspectj-autoproxy proxy-target-class="true"/>
    <bean id="LogAspect" class="com.crcb.aop.LogAspect"></bean>

切记一定是springMvc容器的配置文件中开启aop,并注入日志对象。假如在spring容器的配置文件中加入会导致切面不生效!例如,我就有两个容器的配置文件如下图:一定要选springmvc-servlet.xml中配置。见前言、问题1。
记录使用AspectJ打印日志(SpringMVC项目)
1.3 附web.xml

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:/conf/applicationContext.xml</param-value>
  </context-param>
  <!-- 配置Spring2:配置Spring监听2 -->
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
  <!-- 创建分发Servlet -->
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:conf/springmvc-servlet.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
</web-app>

1.4 核心代码如下:
主要是切点表达式的使用

@Aspect
public class LogAspect {


    @Pointcut("execution(public * com.crcb.controller..insert*(..))")
    private void insert(){}

    @Pointcut("execution(public * com.crcb.controller..update*(..))")
    private void update(){}

    @Pointcut("execution(public * com.crcb.controller..delete*(..))")
    private void delete(){}

    //定义环绕通知:处理日志注入
    @Around("insert()||update()||delete()")
    private Object logAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object[] args = proceedingJoinPoint.getArgs();
        System.out.println("===============请求内容===============");
        String requestStr = JSONObject.toJSONString(args);
        System.out.println("请求类方法:"+proceedingJoinPoint.getSignature().toString());
        System.out.println("请求参数:user,"+requestStr);
        System.out.println("请求CLASS_METHOD:"+proceedingJoinPoint.getTarget().getClass().getName());
        System.out.println("===============请求内容===============");
        System.out.println("--------------返回内容----------------");
        Object result = proceedingJoinPoint.proceed();
        System.out.println("Response内容:" + JSONObject.toJSONString(result));
        System.out.println("--------------返回内容----------------");
        return result;
    }
}

1.5 源码地址,欢迎下载。