Source code
https://github.com/HelloSummer5/GlobalLogDemo
Traditional Logging Method
Not elegant enough, not beautiful enough, will cause a lot of log code redundancy
@GetMapping("list") public Result listUser(){ log.info("======Get into Controller====="); List<User> userList = userService.listUser(); log.info("======userList:{}=====", userList); return ResponseFactory.build(userList); }
brief introduction
Usually there are two layers that need to be logged: the controller layer and the service layer. Log s in the controller layer print information using logs, while logs in the service layer record operation logs using databases.
Realization
- pom
<!-- AOP rely on --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-aop</artifactId> </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()); } }
- Class 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){ // Receive the request and record the content of the request ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); // Record the content of the request 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){ // Processing the request and returning the content log.info("RESPONSE : " + ret); log.info(">>>>>>>>>>>>>>>>>>>>>>>>>"); } }
Effect
Unimportant classes
- In this case, I like to return to the format with Result. See the specific code.
- Class User:
package com.example.demo.entity; import lombok.Data; public class User { private String name; private Integer age; }
- Service layer:
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("Zhang San"); zhangsan.setAge(18); userList.add(zhangsan); return userList; } }
- Result
package com.example.demo.common; import lombok.Data; /** * @ClassName Result * @Description service Layer begins to return to 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; }
- Return Format Factory Class:
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 { /** * Public Private Static Functions * @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; } /** * Specify Response Codes - Define Response Codes in @ResultEnum beforehand * <pre> * { * "code":{code} * "msg":{message} * } * </pre> * @param code * @return * @see ResultEnum */ public static Result build(int code) { Result json = commonBuild(code, ResultEnum.getMsg(code)); return json; } /** * Successful response * <p> * <pre> * { * "code":0, * "msg":"success." * } * </pre> * * @return */ public static Result build() { Result json = commonBuild(ResultEnum.SUCCESS.getCode(), null); return json; } /** * Successful response * <pre> * { * "code":{code} * "msg":{message} * } * </pre> * * @param data Data objects to be returned * @return * @see ResultEnum */ public static Result build(Object data) { Result json = commonBuild(ResultEnum.SUCCESS.getCode(), "Request successful"); json.setData(data); return json; } /** * Customize return code to build return data * * @param code * @return */ public static Result build(int code, Object data) { Result result = commonBuild(code, null); result.setData(data); return result; } /** * Customize return code to build return data * * @param code * @return */ public static Result build(int code, String msg) { Result result = commonBuild(code, msg); result.setData(null); return result; } /** * Customize return code to build return data * * @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; } /** * Customize return code to build return data * * @param code * @return */ public static Result build(int code, String msg, Object data) { Result result = commonBuild(code, msg); result.setData(data); return result; } /** * Custom return code, build return data * * @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,"unknown error"), SUCCESS(0,"Success"); 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; } }