本文介绍 SpringBoot 使用 AOP 统一处理 Web 请求日志。
这里通过一个拦截器的示例介绍。主要看 HttpAspect.java 的代码
1、UserController.java
2、UserRepository.java
3、User.java
4、HttpAspect.java 拦截器
① 写法一、
注意:
@Aspect 表示该类是一个面向切面编程的类
@Component 表示将该类加入 Spring 容器
@Before("execution(public * com.liuyanzhao.blog.controller.UserController.*(..))") 表示在 UserController 类下的所有方法执行前执行。
@After与@Before相反
然后我们可以发起一个查询所有用户的请求和删除一个用户的请求,观察控制台
可以证明拦截器是有效的
② 写法二、
我们发现上面的 @Before 和 @After 后面的代码是一样的,重复了,本着不写重复代码的原则,我们要把它整理一下,所以 HttpAspect.java 可以改成这样
③ 写法三 (推荐)
注意 Logger 的包不要导错了,要导 org.slf4j.Logger; 下的
和方法一执行同样的操作,控制台效果图如下
我们发现这次的日志里会有时间,进程号,端口号,哪个类输出的日志等信息,更加强大,所以更为推荐使用。
将上面的 HttpAspect.java 修改一下,用于获取 Http 请求,并写入日志
发起一个请求,控制台效果图
一、导入依赖
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-aop</artifactId>
- </dependency>
二、代码示例
这里通过一个拦截器的示例介绍。主要看 HttpAspect.java 的代码
1、UserController.java
- package com.liuyanzhao.blog.controller;
- import com.liuyanzhao.blog.domain.User;
- import com.liuyanzhao.blog.repository.UserRepository;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
- import java.util.List;
- /**
- * @Author 言曌
- * @DATE 2017/10/29 上午10:33
- * @URL http://liuyanzhao.com
- */
- @RestController
- public class UserController {
- @Autowired
- private UserRepository userRepository;
- /**
- * 查询所有用户列表
- * @return
- */
- @GetMapping(value = "/users")
- public List<User> listUser() {
- System.out.println("List all user!");
- return userRepository.findAll();
- }
- /**
- * 删除一个用户
- * @param id
- */
- @DeleteMapping(value = "/users/{id}")
- public void deleteUser(@PathVariable("id") Integer id) {
- System.out.println("Delete a user!");
- userRepository.delete(id);
- }
- }
2、UserRepository.java
- package com.liuyanzhao.blog.repository;
- import com.liuyanzhao.blog.domain.User;
- import org.springframework.data.jpa.repository.JpaRepository;
- /**
- * @Author 言曌
- * @DATE 2017/10/29 上午10:35
- * @URL http://liuyanzhao.com
- */
- public interface UserRepository extends JpaRepository<User,Integer>{//表名和Id类型
- }
3、User.java
- package com.liuyanzhao.blog.domain;
- import javax.persistence.Entity;
- import javax.persistence.GeneratedValue;
- import javax.persistence.Id;
- import javax.validation.constraints.Min;
- @Entity
- public class User {
- @Id
- @GeneratedValue
- private Integer id;
- private String name;
- private String gender;
- private Integer age;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getGender() {
- return gender;
- }
- public void setGender(String gender) {
- this.gender = gender;
- }
- public Integer getAge() {
- return age;
- }
- public void setAge(Integer age) {
- this.age = age;
- }
- }
4、HttpAspect.java 拦截器
① 写法一、
- package com.liuyanzhao.blog.aspect;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.springframework.stereotype.Component;
- /**
- * @Author 言曌
- * @DATE 2017/10/30 下午7:03
- * @URL http://liuyanzhao.com
- */
- @Aspect
- @Component
- public class HttpAspect {
- //在UserController所有方法调用之前执行一次
- @Before("execution(public * com.liuyanzhao.blog.controller.UserController.*(..))")
- public void doBefore() {
- System.out.println("11111111");
- }
- //在UserController所有方法调用之后执行一次
- @After("execution(public * com.liuyanzhao.blog.controller.UserController.*(..))")
- public void doAfter() {
- System.out.println("222222222");
- }
- }
注意:
@Aspect 表示该类是一个面向切面编程的类
@Component 表示将该类加入 Spring 容器
@Before("execution(public * com.liuyanzhao.blog.controller.UserController.*(..))") 表示在 UserController 类下的所有方法执行前执行。
@After与@Before相反
然后我们可以发起一个查询所有用户的请求和删除一个用户的请求,观察控制台
可以证明拦截器是有效的
② 写法二、
我们发现上面的 @Before 和 @After 后面的代码是一样的,重复了,本着不写重复代码的原则,我们要把它整理一下,所以 HttpAspect.java 可以改成这样
- package com.liuyanzhao.blog.aspect;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- import org.springframework.stereotype.Component;
- /**
- * @Author 言曌
- * @DATE 2017/10/30 下午7:03
- * @URL http://liuyanzhao.com
- */
- @Aspect
- @Component
- public class HttpAspect {
- @Pointcut("execution(public * com.liuyanzhao.blog.controller.UserController.*(..))")
- public void log() { }
- //在UserController所有方法调用之前执行一次
- @Before("log()")
- public void doBefore() {
- System.out.println("11111111");
- }
- //在UserController所有方法调用之后执行一次
- @After("log()")
- public void doAfter() {
- System.out.println("222222222");
- }
- }
③ 写法三 (推荐)
- package com.liuyanzhao.blog.aspect;
- import org.aspectj.lang.annotation.After;
- import org.aspectj.lang.annotation.Aspect;
- import org.aspectj.lang.annotation.Before;
- import org.aspectj.lang.annotation.Pointcut;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
- /**
- * @Author 言曌
- * @DATE 2017/10/30 下午7:03
- * @URL http://liuyanzhao.com
- */
- @Aspect
- @Component
- public class HttpAspect {
- private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
- @Pointcut("execution(public * com.liuyanzhao.blog.controller.UserController.*(..))")
- public void log() { }
- //在UserController所有方法调用之前执行一次
- @Before("log()")
- public void doBefore() {
- logger.info("11111111111");
- }
- //在UserController所有方法调用之后执行一次
- @After("log()")
- public void doAfter() {
- logger.info("22222222222");
- }
- }
注意 Logger 的包不要导错了,要导 org.slf4j.Logger; 下的
和方法一执行同样的操作,控制台效果图如下
我们发现这次的日志里会有时间,进程号,端口号,哪个类输出的日志等信息,更加强大,所以更为推荐使用。
三、将 http 请求写入日志
将上面的 HttpAspect.java 修改一下,用于获取 Http 请求,并写入日志
- package com.liuyanzhao.blog.aspect;
- import org.aspectj.lang.JoinPoint;
- import org.aspectj.lang.annotation.*;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Component;
- import org.springframework.web.context.request.RequestContextHolder;
- import org.springframework.web.context.request.ServletRequestAttributes;
- import javax.servlet.http.HttpServletRequest;
- /**
- * @Author 言曌
- * @DATE 2017/10/30 下午7:03
- * @URL http://liuyanzhao.com
- */
- @Aspect
- @Component
- public class HttpAspect {
- private final static Logger logger = LoggerFactory.getLogger(HttpAspect.class);
- @Pointcut("execution(public * com.liuyanzhao.blog.controller.UserController.*(..))")
- public void log() { }
- //在UserController所有方法调用之前执行一次
- @Before("log()")
- public void doBefore(JoinPoint joinPoint) {
- ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
- HttpServletRequest request = attributes.getRequest();
- //url
- logger.info("url={}",request.getRequestURL());
- //method
- logger.info("method={}",request.getMethod());
- //ip
- logger.info("ip={}",request.getRemoteAddr());
- //类方法
- logger.info("class_method={}",joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
- //参数
- logger.info("args={}",joinPoint.getArgs());
- }
- //在UserController所有方法调用之后执行一次
- @After("log()")
- public void doAfter() {
- logger.info("22222222222");
- }
- //返回结果
- @AfterReturning(returning = "object",pointcut = "log()")
- public void doAfterReturning(Object object) {
- logger.info("response={}",object);
- }
- }
发起一个请求,控制台效果图
您可以选择一种方式赞助本站
支付宝扫一扫赞助
微信钱包扫描赞助
赏