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

太过爱你忘了你带给我的痛 2021-11-05 14:26 437阅读 0赞

源码

https://github.com/HelloSummer5/GlobalLogDemo

传统打日志方式

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

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

简介

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

实现

  • pom


    org.springframework.boot
    spring-boot-starter-aop
  • 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 {

    1. @Autowired
    2. private UserService userService;
    3. @GetMapping("list")
    4. public Result listUser(){
    5. return ResponseFactory.build(userService.listUser());
    6. }

    }

  • 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 {

    1. @Pointcut("execution(public * com.example.demo.controller..*.*(..))")
    2. public void log(){ }
    3. @Before("log()")
    4. public void doBefore(JoinPoint joinPoint){
    5. // 接收到请求,记录请求内容
    6. ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    7. HttpServletRequest request = attributes.getRequest();
    8. // 记录下请求内容
    9. log.info("<<<<<<<<<<<<<<<<<<<<<<<<");
    10. log.info("URL : " + request.getRequestURL().toString());
    11. log.info("HTTP_METHOD : " + request.getMethod());
    12. log.info("IP : " + request.getRemoteAddr());
    13. log.info("CLASS_METHOD : " + joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
    14. log.info("ARGS : " + Arrays.toString(joinPoint.getArgs()));
    15. }
    16. @AfterReturning(returning = "ret", pointcut = "log()")
    17. public void doAfterReturning(Object ret){
    18. // 处理完请求,返回内容
    19. log.info("RESPONSE : " + ret);
    20. log.info(">>>>>>>>>>>>>>>>>>>>>>>>>");
    21. }

    }

效果

在这里插入图片描述

不重要的类

  • 在这我都喜欢用Result统一返回格式,具体代码见吧。
  • User类:

    package com.example.demo.entity;

    import lombok.Data;

    public class User {

    1. private String name;
    2. 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 {

    1. @Override
    2. public List<User> listUser() {
    3. List<User> userList = new ArrayList<>();
    4. User zhangsan = new User();
    5. zhangsan.setName("张三");
    6. zhangsan.setAge(18);
    7. userList.add(zhangsan);
    8. return userList;
    9. }

    }

  • 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 {

    1. private int code;
    2. private int count = 0;
    3. private String msg;
    4. 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 {

    1. /** * 公共私有静态函数 * @param code * @return */
    2. private static Result commonBuild(int code, String errmsg) {
    3. Result result = new Result();
    4. result.setCode(code);
    5. if (errmsg == null || errmsg.trim().length() == 0) {
    6. result.setMsg(ResultEnum.getMsg(code));
    7. } else {
    8. result.setMsg(errmsg);
    9. }
    10. return result;
    11. }
    12. /** * 指定响应码-需预先在 @ResultEnum 里定义响应码 * <pre> * { * "code":{code} * "msg":{message} * } * </pre> * @param code * @return * @see ResultEnum */
    13. public static Result build(int code) {
    14. Result json = commonBuild(code, ResultEnum.getMsg(code));
    15. return json;
    16. }
    17. /** * 成功响应 * <p> * <pre> * { * "code":0, * "msg":"success." * } * </pre> * * @return */
    18. public static Result build() {
    19. Result json = commonBuild(ResultEnum.SUCCESS.getCode(), null);
    20. return json;
    21. }
    22. /** * 成功响应 * <pre> * { * "code":{code} * "msg":{message} * } * </pre> * * @param data 需要返回的数据对象 * @return * @see ResultEnum */
    23. public static Result build(Object data) {
    24. Result json = commonBuild(ResultEnum.SUCCESS.getCode(), "请求成功");
    25. json.setData(data);
    26. return json;
    27. }
    28. /** * 自定义返回码code,构建返回数据 * * @param code * @return */
    29. public static Result build(int code, Object data) {
    30. Result result = commonBuild(code, null);
    31. result.setData(data);
    32. return result;
    33. }
    34. /** * 自定义返回码code,构建返回数据 * * @param code * @return */
    35. public static Result build(int code, String msg) {
    36. Result result = commonBuild(code, msg);
    37. result.setData(null);
    38. return result;
    39. }
    40. /** * 自定义返回码code,构建返回数据 * * @param code * @param count * @param obj * @return */
    41. public static Result build(int code, int count, Object obj) {
    42. Result result = commonBuild(code, null);
    43. result.setCount(count);
    44. result.setData(obj);
    45. return result;
    46. }
    47. /** * 自定义返回码code,构建返回数据 * * @param code * @return */
    48. public static Result build(int code, String msg, Object data) {
    49. Result result = commonBuild(code, msg);
    50. result.setData(data);
    51. return result;
    52. }
    53. /** * 自定义返回码code,构建返回数据 * * @param code * @return */
    54. public static Result build(int code, int count, String msg, Object data) {
    55. Result result = commonBuild(code, msg);
    56. result.setData(data);
    57. result.setCount(count);
    58. return result;
    59. }

    }

  • ResultEnum:

    package com.example.demo.common.enums;

    public enum ResultEnum {

    1. UNKOWN_ERROR(-1,"未知错误"),
    2. SUCCESS(0,"成功");
    3. private Integer code;
    4. private String msg;
    5. ResultEnum(Integer code, String msg) {
    6. this.code = code;
    7. this.msg = msg;
    8. }
    9. public Integer getCode() {
    10. return code;
    11. }
    12. public String getMsg() {
    13. return msg;
    14. }
    15. public static String getMsg(int code) {
    16. for (ResultEnum ele : values()) {
    17. if(ele.getCode().equals(code)) return ele.getMsg();
    18. }
    19. return null;
    20. }

    }

发表评论

表情:
评论列表 (有 0 条评论,437人围观)

还没有评论,来说两句吧...

相关阅读