【SpringBoot】SpringBoot+AOP全局打印日志(附源码)

源码

https://github.com/HelloSummer5/GlobalLogDemo

传统打日志方式

不够优雅不够美观,会造成许多日志代码冗余

@GetMapping("list")
public Result listUser(){
    log.info("======进入Controller=====");
    List<User> userList = userService.listUser();
    log.info("======userList:{}=====", userList);
    return ResponseFactory.build(userList);
}

简介

通常有两层需要加日志:controller层和service层。controller层的日志使用Log打印信息,service层的日志使用数据库记录操作日志。

实现

  • pom

 <dependency>
     <groupId>org.springframework.bootgroupId>
     <artifactId>spring-boot-starter-aopartifactId>
 dependency>
  • Controller:
package com.example.demo.controller;

import com.example.demo.common.ResponseFactory;
import com.example.demo.common.Result;
import com.example.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RestController
public class TestController {

    @Autowired
    private UserService userService;

    @GetMapping("list")
    public Result listUser(){
        return ResponseFactory.build(userService.listUser());
    }
}
  • Aspect类
package com.example.demo.common.aspect;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Arrays;

@Slf4j
@Aspect
@Component
public class LogAspect {

    @Pointcut("execution(public * com.example.demo.controller..*.*(..))")
    public void log(){}

    @Before("log()")
    public void doBefore(JoinPoint joinPoint){
        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        // 记录下请求内容
        log.info("<<<<<<<<<<<<<<<<<<<<<<<<");
        log.info("URL : " + request.getRequestURL().toString());
        log.info("HTTP_METHOD : " + request.getMethod());
        log.info("IP : " + request.getRemoteAddr());
        log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        log.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));

    }

    @AfterReturning(returning = "ret", pointcut = "log()")
    public void doAfterReturning(Object ret){
        // 处理完请求,返回内容
        log.info("RESPONSE : " + ret);
        log.info(">>>>>>>>>>>>>>>>>>>>>>>>>");
    }
}

效果

在这里插入图片描述

不重要的类

  • 在这我都喜欢用Result统一返回格式,具体代码见吧。
  • User类:
package com.example.demo.entity;

import lombok.Data;

public class User {
    private String name;
    private Integer age;
}
  • Service层:
package com.example.demo.service.impl;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName UserServiceImpl
 * @Description TODO
 * @Auth wujinjuan
 * @Date 2019/8/7 10:25
 * @Version 1.0
 **/
@Slf4j
@Service
public class UserServiceImpl implements UserService {

    @Override
    public List<User> listUser() {
        List<User> userList = new ArrayList<>();
        User zhangsan = new User();
        zhangsan.setName("张三");
        zhangsan.setAge(18);
        userList.add(zhangsan);
        return userList;
    }

}
  • Result
package com.example.demo.common;

import lombok.Data;

/**
 * @ClassName Result
 * @Description service层开始返回Result
 * @Auth wujinjuan
 * @Date 2019/6/19 11:25 AM
 * @Version 1.0
 **/
@Data
public class Result {

    private int code;

    private int count = 0;

    private String msg;

    private Object data;

}

  • 返回格式工厂类:
package com.example.demo.common;

import com.example.demo.common.enums.ResultEnum;

/**
 * @ClassName ResponseFactory
 * @Description
 * @Auth wujinjuan
 * @Date 2019/6/19 11:25 AM
 * @Version 1.0
 **/
public class ResponseFactory {
    /**
     * 公共私有静态函数
     * @param code
     * @return
     */
    private static Result commonBuild(int code, String errmsg) {
        Result result = new Result();
        result.setCode(code);
        if (errmsg == null || errmsg.trim().length() == 0) {
            result.setMsg(ResultEnum.getMsg(code));
        } else {
            result.setMsg(errmsg);
        }
        return result;
    }

    /**
     * 指定响应码-需预先在 @ResultEnum 里定义响应码
     * 
     *     {
     *         "code":{code}
     *         "msg":{message}
     *     }
     * 
* @param code * @return * @see ResultEnum */
public static Result build(int code) { Result json = commonBuild(code, ResultEnum.getMsg(code)); return json; } /** * 成功响应 *

*

     * {
     *     "code":0,
     *     "msg":"success."
     * }
     * 
* * @return */
public static Result build() { Result json = commonBuild(ResultEnum.SUCCESS.getCode(), null); return json; } /** * 成功响应 *
     *     {
     *         "code":{code}
     *         "msg":{message}
     *     }
     * 
* * @param data 需要返回的数据对象 * @return * @see ResultEnum */
public static Result build(Object data) { Result json = commonBuild(ResultEnum.SUCCESS.getCode(), "请求成功"); json.setData(data); return json; } /** * 自定义返回码code,构建返回数据 * * @param code * @return */ public static Result build(int code, Object data) { Result result = commonBuild(code, null); result.setData(data); return result; } /** * 自定义返回码code,构建返回数据 * * @param code * @return */ public static Result build(int code, String msg) { Result result = commonBuild(code, msg); result.setData(null); return result; } /** * 自定义返回码code,构建返回数据 * * @param code * @param count * @param obj * @return */ public static Result build(int code, int count, Object obj) { Result result = commonBuild(code, null); result.setCount(count); result.setData(obj); return result; } /** * 自定义返回码code,构建返回数据 * * @param code * @return */ public static Result build(int code, String msg, Object data) { Result result = commonBuild(code, msg); result.setData(data); return result; } /** * 自定义返回码code,构建返回数据 * * @param code * @return */ public static Result build(int code, int count, String msg, Object data) { Result result = commonBuild(code, msg); result.setData(data); result.setCount(count); return result; } }
  • ResultEnum:
package com.example.demo.common.enums;

public enum ResultEnum {

    UNKOWN_ERROR(-1,"未知错误"),
    SUCCESS(0,"成功");

    private Integer code;
    private String msg;

    ResultEnum(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Integer getCode() {
        return code;
    }

    public String getMsg() {
        return msg;
    }

    public static String getMsg(int code) {
        for (ResultEnum ele : values()) {
            if(ele.getCode().equals(code)) return ele.getMsg();
        }
        return null;
    }
}

你可能感兴趣的:(Java,SpringBoot)