Relaxed项目是一个基础的通用脚手架,旨在为项目快速开发提供一系列的基础能力,方便使用者根据项目需求快速进行功能拓展。
-
Github地址: https://github.com/xiaoashuo/relaxed
| 模块概要 | 模块路径 |
|---|---|
| 缓存模块 | relaxed-spring-boot-starter-cache |
| 数据权限 | relaxed-spring-boot-starter-datascope |
| 钉钉通知 | relaxed-spring-boot-starter-dingtalk |
| 通用下载 | relaxed-spring-boot-starter-download |
| excel模块 | relaxed-spring-boot-starter-easyexcel |
| 异常处理 | relaxed-spring-boot-starter-exception |
| 任务模块 | relaxed-spring-boot-starter-job |
| 日志模块 | relaxed-spring-boot-starter-log |
| 邮件模块 | relaxed-spring-boot-starter-mail |
| 对象存储 | relaxed-spring-boot-starter-oss |
| 通讯加密 | relaxed-spring-boot-starter-secret |
| SFTP | relaxed-spring-boot-starter-sftp |
| 企业微信通知 | relaxed-spring-boot-starter-wechat |
| Web模块 | relaxed-spring-boot-starter-web |
git clone https://github.com/xiaoashuo/relaxed.gitmvn install此处以日志模块为示例
<!--引入对应坐标--> <dependency> <groupId>cn.lovecyy</groupId> <artifactId>relaxed-spring-boot-starter-log</artifactId> <version>${revision}</version> </dependency>@Slf4j @Component public class AccessLogHandle implements AccessLogHandler<AccessLog> { public static final String TRACE_ID = "traceId"; @Override public AccessLog beforeRequest(HttpServletRequest request, LogAccessRule logAccessRule) { AccessLog paramMap = new AccessLog(); Object matchingPatternAttr = request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); String matchingPattern = matchingPatternAttr == null ? "" : String.valueOf(matchingPatternAttr); String uri = URLUtil.getPath(request.getRequestURI()); paramMap.setTraceId(MDC.get(TRACE_ID)); paramMap.setUri(uri); paramMap.setMethod(request.getMethod()); paramMap.setIp(IpUtils.getIpAddr(request)); paramMap.setMatchingPattern(matchingPattern); paramMap.setUserAgent(request.getHeader("user-agent")); paramMap.setCreatedTime(LocalDateTime.now()); return paramMap; } @Override public void afterRequest(AccessLog buildParam, HttpServletRequest request, HttpServletResponse response, Long executionTime, Throwable myThrowable, LogAccessRule logAccessRule) { buildParam.setUpdatedTime(LocalDateTime.now()); buildParam.setTime(executionTime); buildParam.setHttpStatus(response.getStatus()); buildParam.setErrorMsg(Optional.ofNullable(myThrowable).map(Throwable::getMessage).orElse("")); LogAccessRule.RecordOption recordOption = logAccessRule.getRecordOption(); LogAccessRule.FieldFilter fieldFilter = logAccessRule.getFieldFilter(); // 记录请求 if (recordOption.isIncludeRequest()) { String matchRequestKey = fieldFilter.getMatchRequestKey(); // 获取普通参数 String params = getParams(request, matchRequestKey, fieldFilter.getReplaceText()); buildParam.setReqParams(params); // 非文件上传请求,记录body,用户改密时不记录body // TODO 使用注解控制此次请求是否记录body,更方便个性化定制 if (!isMultipartContent(request)) { buildParam.setReqBody(getRequestBody(request, matchRequestKey, fieldFilter.getReplaceText())); } } // 记录响应 if (recordOption.isIncludeResponse()) { String matchResponseKey = fieldFilter.getMatchResponseKey(); buildParam.setResult(getResponseBody(request, response, matchResponseKey, fieldFilter.getReplaceText())); } String header = getHeader(request, "Accept", "Content-Type"); log.info("\n请求头:\n{}\n请求记录:\n{}", header, convertToAccessLogStr(buildParam)); } /** * 判断是否是multipart/form-data请求 * @param request 请求信息 * @return 是否是multipart/form-data请求 */ public boolean isMultipartContent(HttpServletRequest request) { // 获取Content-Type String contentType = request.getContentType(); return (contentType != null) && (contentType.toLowerCase().startsWith("multipart/")); } public String convertToAccessLogStr(AccessLog accessLog) { String LINE_SEPARATOR = System.lineSeparator(); StringBuilder reqInfo = new StringBuilder().append("traceId:").append(accessLog.getTraceId()) .append(LINE_SEPARATOR).append("userId:").append(accessLog.getUserId()).append(LINE_SEPARATOR) .append("userName:").append(accessLog.getUsername()).append(LINE_SEPARATOR).append("uri:") .append(accessLog.getUri()).append(LINE_SEPARATOR).append("matchingPattern:") .append(accessLog.getMatchingPattern()).append(LINE_SEPARATOR).append("method:") .append(accessLog.getMethod()).append(LINE_SEPARATOR).append("userAgent:") .append(accessLog.getUserAgent()).append(LINE_SEPARATOR).append("reqParams:") .append(accessLog.getReqParams()).append(LINE_SEPARATOR).append("reqBody:") .append(accessLog.getReqBody()).append(LINE_SEPARATOR).append("httpStatus:") .append(accessLog.getHttpStatus()).append(LINE_SEPARATOR).append("result:") .append(accessLog.getResult()).append(LINE_SEPARATOR).append("errorMsg:") .append(accessLog.getErrorMsg()).append(LINE_SEPARATOR).append("time:").append(accessLog.getTime()) .append(LINE_SEPARATOR).append("createdTime:").append(accessLog.getCreatedTime()) .append(LINE_SEPARATOR); return reqInfo.toString(); } }relaxed: log: access: enabled: true #过滤器顺序(可选) order: -10 #url规则列表(可选) urlRules: #匹配路径 - urlPattern: /test/log/**/form #日志选项 recordOption: #是否忽略 默认为false ignore: false #记录请求 默认true includeRequest: true #记录响应 默认true includeResponse: true #字段级别过滤规则 #此示例过滤请求username 响应password #请求参数:{"username":"zs","password":"12"} #响应参数:{"username":"zs","password":"12"} fieldFilter: #匹配请求参数路径名,多个以,分隔。 matchRequestKey: username,password #匹配响应参数路径名,多个以,分隔 matchResponseKey: password #替换文本 若内容为空 则不替换 replaceText: none