parent
							
								
									f688a44e77
								
							
						
					
					
						commit
						614d3fc273
					
				
				 12 changed files with 289 additions and 8 deletions
			
			
		| @ -0,0 +1,150 @@ | ||||
| package org.anyin.gitee.shiro.advisor; | ||||
| 
 | ||||
| import cn.hutool.json.JSONUtil; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import org.anyin.gitee.shiro.base.BusinessCodeEnum; | ||||
| import org.anyin.gitee.shiro.base.BusinessException; | ||||
| import org.anyin.gitee.shiro.base.Response; | ||||
| import org.anyin.gitee.shiro.utils.RequestIdUtils; | ||||
| import org.aspectj.lang.ProceedingJoinPoint; | ||||
| import org.aspectj.lang.annotation.Around; | ||||
| import org.aspectj.lang.annotation.Aspect; | ||||
| import org.slf4j.MDC; | ||||
| import org.springframework.core.annotation.Order; | ||||
| import org.springframework.util.StringUtils; | ||||
| import org.springframework.web.context.request.RequestContextHolder; | ||||
| import org.springframework.web.context.request.ServletRequestAttributes; | ||||
| import org.springframework.web.multipart.commons.CommonsMultipartFile; | ||||
| 
 | ||||
| import javax.servlet.http.HttpServletRequest; | ||||
| import javax.servlet.http.HttpServletResponse; | ||||
| import java.util.Optional; | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| @Aspect | ||||
| @Order | ||||
| @Slf4j | ||||
| public class ApiMessageAdvisor { | ||||
| 
 | ||||
| 
 | ||||
|     @Around("execution(public * org.anyin.gitee.shiro.controller..*Controller.*(..))") | ||||
|     public Object invokeAPI(ProceedingJoinPoint pjp) { | ||||
|         String apiName = this.getApiName(pjp); | ||||
|         String requestId = this.getRequestId(); | ||||
|         // 配置日志文件打印 REQUEST_ID
 | ||||
|         MDC.put("REQUEST_ID", requestId); | ||||
|         Object returnValue = null; | ||||
|         try{ | ||||
|             this.printRequestParam(apiName, pjp); | ||||
|             returnValue = pjp.proceed(); | ||||
|             this.handleRequestId(returnValue); | ||||
|         }catch (BusinessException ex){ | ||||
|             returnValue = this.handleBusinessException(apiName, ex); | ||||
|         }catch (Throwable ex){ | ||||
|             returnValue = this.handleSystemException(apiName, ex); | ||||
|         }finally { | ||||
|             this.printResponse(apiName, returnValue); | ||||
|             RequestIdUtils.removeRequestId(); | ||||
|             MDC.clear(); | ||||
|         } | ||||
|         return returnValue; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 处理系统异常 | ||||
|      * @param apiName 接口名称 | ||||
|      * @param ex 系统异常 | ||||
|      * @return 返回参数 | ||||
|      */ | ||||
|     private Response handleSystemException(String apiName, Throwable ex){ | ||||
|         log.error("@Meet unknown error when do " + apiName + ":" + ex.getMessage(), ex); | ||||
|         Response response = new Response(BusinessCodeEnum.UNKNOWN_ERROR.getCode(), BusinessCodeEnum.UNKNOWN_ERROR.getMsg()); | ||||
|         response.setRequestId(RequestIdUtils.getRequestId().toString()); | ||||
|         return response; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 处理业务异常 | ||||
|      * @param apiName 接口名称 | ||||
|      * @param ex 业务异常 | ||||
|      * @return 返回参数 | ||||
|      */ | ||||
|     private Response handleBusinessException(String apiName, BusinessException ex){ | ||||
|         log.error("@Meet error when do " + apiName + "[" + ex.getCode() + "]:" + ex.getMsg(), ex); | ||||
|         Response response = new Response(ex.getCode(), ex.getMsg()); | ||||
|         response.setRequestId(RequestIdUtils.getRequestId().toString()); | ||||
|         return response; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 填充RequestId | ||||
|      * @param returnValue 返回参数 | ||||
|      */ | ||||
|     private void handleRequestId(Object returnValue){ | ||||
|         if(returnValue instanceof Response){ | ||||
|             Response response = (Response)returnValue; | ||||
|             response.setRequestId(RequestIdUtils.getRequestId().toString()); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 打印响应参数信息 | ||||
|      * @param apiName 接口名称 | ||||
|      * @param returnValue 返回值 | ||||
|      */ | ||||
|     private void printResponse(String apiName, Object returnValue){ | ||||
|         if (log.isInfoEnabled()) { | ||||
|             log.info("@@{} done, response: {}", apiName, JSONUtil.toJsonStr(returnValue)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 打印请求参数信息 | ||||
|      * @param apiName 接口名称 | ||||
|      * @param pjp 切点 | ||||
|      */ | ||||
|     private void printRequestParam(String apiName, ProceedingJoinPoint pjp){ | ||||
|         Object[] args = pjp.getArgs(); | ||||
|         if(log.isInfoEnabled() && args != null&& args.length > 0){ | ||||
|             for(Object o : args) { | ||||
|                 if(!(o instanceof HttpServletRequest) && !(o instanceof HttpServletResponse) && !(o instanceof CommonsMultipartFile)) { | ||||
|                     log.info("@@{} started, request: {}", apiName, JSONUtil.toJsonStr(o)); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取RequestId | ||||
|      * 优先从header头获取,如果没有则自己生成 | ||||
|      * @return RequestId | ||||
|      */ | ||||
|     private String getRequestId(){ | ||||
|         UUID existUUID = RequestIdUtils.getRequestId(); | ||||
|         if(existUUID != null){ | ||||
|             return existUUID.toString(); | ||||
|         } | ||||
|         ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); | ||||
|         if(attributes == null || !StringUtils.hasText(attributes.getRequest().getHeader("x-request-id"))) { | ||||
|             RequestIdUtils.generateRequestId(); | ||||
|             return RequestIdUtils.getRequestId().toString(); | ||||
|         } | ||||
|         // 因为如果有网关,则一般会从网关传递过来,所以优先从header头获取
 | ||||
|         HttpServletRequest request = attributes.getRequest(); | ||||
|         String requestId = request.getHeader("x-request-id"); | ||||
|         UUID uuid = UUID.fromString(requestId); | ||||
|         RequestIdUtils.generateRequestId(uuid); | ||||
|         return requestId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * 获取当前接口对应的类名和方法名 | ||||
|      * @param pjp 切点 | ||||
|      * @return apiName | ||||
|      */ | ||||
|     private String getApiName(ProceedingJoinPoint pjp){ | ||||
|         String apiClassName = pjp.getTarget().getClass().getSimpleName(); | ||||
|         String methodName = pjp.getSignature().getName(); | ||||
|         return apiClassName.concat(":").concat(methodName); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,14 @@ | ||||
| package org.anyin.gitee.shiro.config; | ||||
| 
 | ||||
| import org.anyin.gitee.shiro.advisor.ApiMessageAdvisor; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| 
 | ||||
| @Configuration | ||||
| public class AppConfig { | ||||
| 
 | ||||
|     @Bean | ||||
|     public ApiMessageAdvisor apiMessageAdvisor(){ | ||||
|         return new ApiMessageAdvisor(); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,27 @@ | ||||
| package org.anyin.gitee.shiro.controller; | ||||
| 
 | ||||
| import org.anyin.gitee.shiro.base.BusinessCodeEnum; | ||||
| import org.anyin.gitee.shiro.base.Response; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
| 
 | ||||
| @RestController | ||||
| @RequestMapping("/log-test") | ||||
| public class LogTestController { | ||||
| 
 | ||||
|     @GetMapping("/success") | ||||
|     public Response<String> success(){ | ||||
|         return new Response<>("success"); | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping("/business-exception") | ||||
|     public Response<String> businessException(){ | ||||
|         throw BusinessCodeEnum.PWD_NOT_MATCH.getException(); | ||||
|     } | ||||
| 
 | ||||
|     @GetMapping("/system-exception") | ||||
|     public Response<String> systemException(){ | ||||
|         throw new NullPointerException("空指针异常"); | ||||
|     } | ||||
| } | ||||
| @ -0,0 +1,26 @@ | ||||
| package org.anyin.gitee.shiro.utils; | ||||
| 
 | ||||
| import java.util.UUID; | ||||
| 
 | ||||
| public class RequestIdUtils { | ||||
|     private static final ThreadLocal<UUID> requestIdHolder = new ThreadLocal<>(); | ||||
| 
 | ||||
|     public RequestIdUtils() { | ||||
|     } | ||||
| 
 | ||||
|     public static void generateRequestId() { | ||||
|         requestIdHolder.set(UUID.randomUUID()); | ||||
|     } | ||||
| 
 | ||||
|     public static void generateRequestId(UUID uuid) { | ||||
|         requestIdHolder.set(uuid); | ||||
|     } | ||||
| 
 | ||||
|     public static UUID getRequestId() { | ||||
|         return (UUID)requestIdHolder.get(); | ||||
|     } | ||||
| 
 | ||||
|     public static void removeRequestId() { | ||||
|         requestIdHolder.remove(); | ||||
|     } | ||||
| } | ||||
| @ -1,3 +1,9 @@ | ||||
| spring: | ||||
|   application: | ||||
|     name: shiro-to-token | ||||
|     name: shiro-to-token | ||||
| 
 | ||||
| logging: | ||||
|   level: | ||||
|     root: info | ||||
|   file: | ||||
|     path: ./logs/shiro-to-token.log | ||||
| @ -0,0 +1,34 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <configuration debug="false" scan="true" scanPeriod="1 seconds"> | ||||
| 
 | ||||
|     <contextName>logback</contextName> | ||||
|     <springProperty scope="context" name="level" source="logging.level.root"/> | ||||
|     <springProperty scope="context" name="path" source="logging.file.path"/> | ||||
| 
 | ||||
| 
 | ||||
|     <appender name="console" class="ch.qos.logback.core.ConsoleAppender"> | ||||
|         <Target>System.out</Target> | ||||
|        <filter class="ch.qos.logback.classic.filter.ThresholdFilter" > | ||||
|             <level>DEBUG</level> | ||||
|         </filter> | ||||
|         <encoder> | ||||
|             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{REQUEST_ID}] [%thread] [%-5level] [%logger{0}:%L] : %msg%n</pattern> | ||||
|         </encoder> | ||||
|     </appender> | ||||
| 
 | ||||
|     <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||||
|         <file>${path}</file> | ||||
|         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | ||||
|             <fileNamePattern>${path}.%d{yyyy-MM-dd}.zip</fileNamePattern> | ||||
|         </rollingPolicy> | ||||
|         <encoder> | ||||
|             <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{REQUEST_ID}] [%thread] [%-5level] [%logger{0}:%L] : %msg%n</pattern> | ||||
|         </encoder> | ||||
|     </appender> | ||||
| 
 | ||||
|     <root level="${level}"> | ||||
|         <appender-ref ref="console"/> | ||||
|         <appender-ref ref="file"/> | ||||
|     </root> | ||||
| 
 | ||||
| </configuration> | ||||
					Loading…
					
					
				
		Reference in new issue
	
	 陈景阳
						陈景阳