spring boot AOP 统一日志处理

it2022-05-05  87

目录

 

使用日志框架logback

一, 在 resources 下创建文件 logback-spring.xml

二,创建日志封装类

三,创建统一日志处理切面 WebLogAspect.java

四,这里有俩个工具类注意

五,不同环境日志输出不同配置如下:

开发环境配置:application-dev.properties

测试环境配置:application-test.properties

生成环境配置;application-prod.properties


使用日志框架logback

一, 在 resources 下创建文件 logback-spring.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration> <configuration> <include resource="org/springframework/boot/logging/logback/defaults.xml"/> <include resource="org/springframework/boot/logging/logback/console-appender.xml"/> <!--应用名称--> <property name="APP_NAME" value="base"/> <!--日志文件保存路径--> <property name="LOG_FILE_PATH" value="${LOG_FILE:-${LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}}/logs}"/> <contextName>${APP_NAME}</contextName> <!--每天记录日志到文件appender--> <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> <fileNamePattern>${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log</fileNamePattern> <maxHistory>30</maxHistory> </rollingPolicy> <encoder> <pattern>${FILE_LOG_PATTERN}</pattern> </encoder> </appender> <!--输出到logstash的appender--> <appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender"> <destination>localhost:4560</destination> <encoder charset="UTF-8" class="net.logstash.logback.encoder.LogstashEncoder"/> </appender> <root level="INFO"> <appender-ref ref="CONSOLE"/> <appender-ref ref="FILE"/> <appender-ref ref="LOGSTASH"/> </root> </configuration>

二,创建日志封装类

package com.autotest.baseweb.config.aspect; /** * Controller层的日志封装类 * Created by macro on 2018/4/26. */ public class WebLog { /** * 操作描述 */ private String description; /** * 操作用户 */ private String username; /** * 操作时间 */ private Long startTime; /** * 消耗时间 */ private Integer spendTime; /** * 根路径 */ private String basePath; /** * URI */ private String uri; /** * URL */ private String url; /** * 请求类型 */ private String method; /** * IP地址 */ private String ip; private Object parameter; private Object result; public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public Long getStartTime() { return startTime; } public void setStartTime(Long startTime) { this.startTime = startTime; } public Integer getSpendTime() { return spendTime; } public void setSpendTime(Integer spendTime) { this.spendTime = spendTime; } public String getBasePath() { return basePath; } public void setBasePath(String basePath) { this.basePath = basePath; } public String getUri() { return uri; } public void setUri(String uri) { this.uri = uri; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getMethod() { return method; } public void setMethod(String method) { this.method = method; } public String getIp() { return ip; } public void setIp(String ip) { this.ip = ip; } public Object getParameter() { return parameter; } public void setParameter(Object parameter) { this.parameter = parameter; } public Object getResult() { return result; } public void setResult(Object result) { this.result = result; } }

三,创建统一日志处理切面 WebLogAspect.java

package com.ingenue.ingenue.aspect; import com.ingenue.ingenue.bean.WebLog; import com.ingenue.ingenue.util.JsonUtil; import com.ingenue.ingenue.util.RequestUtil; import io.swagger.annotations.ApiOperation; import net.logstash.logback.marker.Markers; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.annotation.*; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 统一日志处理切面 * Created by macro on 2018/4/26. */ @Aspect @Component @Order(1) public class WebLogAspect { private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class); private ThreadLocal<Long> startTime = new ThreadLocal<>(); @Pointcut("execution(public * com.ingenue.ingenue.controller.*.*(..))") public void webLog() { } @Before("webLog()") public void doBefore(JoinPoint joinPoint) throws Throwable { startTime.set(System.currentTimeMillis()); } @AfterReturning(value = "webLog()", returning = "ret") public void doAfterReturning(Object ret) throws Throwable { } @Around("webLog()") public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable { //获取当前请求对象 ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //记录请求信息(通过logstash传入elasticsearch) WebLog webLog = new WebLog(); Object result = joinPoint.proceed(); Signature signature = joinPoint.getSignature(); MethodSignature methodSignature = (MethodSignature) signature; Method method = methodSignature.getMethod(); if (method.isAnnotationPresent(ApiOperation.class)) { ApiOperation log = method.getAnnotation(ApiOperation.class); webLog.setDescription(log.value()); } long endTime = System.currentTimeMillis(); webLog.setBasePath(RequestUtil.getBasePath(request)); webLog.setIp(request.getRemoteUser()); webLog.setMethod(request.getMethod()); webLog.setParameter(getParameter(method, joinPoint.getArgs())); webLog.setResult(result); webLog.setSpendTime((int) (endTime - startTime.get())); webLog.setStartTime(startTime.get()); webLog.setUri(request.getRequestURI()); webLog.setUrl(request.getRequestURL().toString()); Map<String,Object> logMap = new HashMap<>(); logMap.put("url",webLog.getUrl()); logMap.put("method",webLog.getMethod()); logMap.put("parameter",webLog.getParameter()); logMap.put("spendTime",webLog.getSpendTime()); logMap.put("description",webLog.getDescription()); // LOGGER.info("{}", JsonUtil.objectToJson(webLog)); LOGGER.info(Markers.appendEntries(logMap), JsonUtil.objectToJson(webLog)); return result; } /** * 根据方法和传入的参数获取请求参数 */ private Object getParameter(Method method, Object[] args) { List<Object> argList = new ArrayList<>(); Parameter[] parameters = method.getParameters(); for (int i = 0; i < parameters.length; i++) { RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); if (requestBody != null) { argList.add(args[i]); } RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); if (requestParam != null) { Map<String, Object> map = new HashMap<>(); String key = parameters[i].getName(); if (!StringUtils.isEmpty(requestParam.value())) { key = requestParam.value(); } map.put(key, args[i]); argList.add(map); } } if (argList.size() == 0) { return null; } else if (argList.size() == 1) { return argList.get(0); } else { return argList; } } }

四,这里有俩个工具类注意

package com.ingenue.ingenue.util; import javax.servlet.http.HttpServletRequest; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; /** * request工具类 * Created by macro on 2018/4/26. */ public class RequestUtil { /** * 移除request指定参数 */ public String removeParam(HttpServletRequest request, String paramName) { String queryString = ""; Enumeration keys = request.getParameterNames(); while (keys.hasMoreElements()) { String key = (String) keys.nextElement(); if (key.equals(paramName)) { continue; } if ("".equals(queryString)) { queryString = key + "=" + request.getParameter(key); } else { queryString += "&" + key + "=" + request.getParameter(key); } } return queryString; } /** * 获取请求basePath */ public static String getBasePath(HttpServletRequest request) { StringBuffer basePath = new StringBuffer(); String scheme = request.getScheme(); String domain = request.getServerName(); int port = request.getServerPort(); basePath.append(scheme); basePath.append("://"); basePath.append(domain); if("http".equalsIgnoreCase(scheme) && 80 != port) { basePath.append(":").append(String.valueOf(port)); } else if("https".equalsIgnoreCase(scheme) && port != 443) { basePath.append(":").append(String.valueOf(port)); } return basePath.toString(); } /** * 请求中参数转Map<String, String>,for支付宝异步回调,平时建议直接使用request.getParameterMap(),返回Map<String, String[]> */ public static Map<String, String> getParameterMap(HttpServletRequest request) { Map<String, String> result = new HashMap<>(); Enumeration parameterNames = request.getParameterNames(); while (parameterNames.hasMoreElements()) { String parameterName = (String) parameterNames.nextElement(); result.put(parameterName, request.getParameter(parameterName)); } return result; } } package com.ingenue.ingenue.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; /** * Jackson json序列化和反序列化工具类 * Created by macro on 2018/4/26. */ public class JsonUtil { // 定义jackson对象 private static final ObjectMapper MAPPER = new ObjectMapper(); /** * 将对象转换成json字符串。 */ public static String objectToJson(Object data) { try { String string = MAPPER.writeValueAsString(data); return string; } catch (JsonProcessingException e) { e.printStackTrace(); } return null; } /** * 将json结果集转化为对象 * * @param jsonData json数据 * @param beanType 对象中的object类型 */ public static <T> T jsonToPojo(String jsonData, Class<T> beanType) { try { T t = MAPPER.readValue(jsonData, beanType); return t; } catch (Exception e) { e.printStackTrace(); } return null; } /** * 将json数据转换成pojo对象list */ public static <T>List<T> jsonToList(String jsonData, Class<T> beanType) { JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, beanType); try { List<T> list = MAPPER.readValue(jsonData, javaType); return list; } catch (Exception e) { e.printStackTrace(); } return null; } }

五,不同环境日志输出不同配置如下:

开发环境配置:application-dev.properties

#日志级别 logging.level.com.ingenue.ingenue=debug #路径 logging.path=./logs logging.file=ingenue.log

测试环境配置:application-test.properties

#日志级别 logging.level.com.ingenue.ingenue=debug #路径 logging.path=home/admin/logs logging.file=ingenue.log

生成环境配置;application-prod.properties

#日志级别 logging.level.com.ingenue.ingenue=info #路径 logging.path=home/admin/logs logging.file=ingenue.log

 


最新回复(0)