Compare commits
No commits in common. "8683437d64dfa1a7d51d8628c7789a757d5fa425" and "d1f96e5e411d314db946d78056b1062ed5e53f27" have entirely different histories.
8683437d64
...
d1f96e5e41
@ -25,13 +25,4 @@ public interface IPageReq {
|
||||
default List<String> getSort() {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
/**
|
||||
* 部分分页不需要查询count,支持指定是否查询count
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
default Boolean isSearchCount() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,15 +7,11 @@ import lombok.NoArgsConstructor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 如果作为接口调用的参数使用。建议使用{@link PageReqV2}。支持builder 模式构建参数,对参数构造更友好。
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
@Deprecated
|
||||
public class PageReq implements IPageReq {
|
||||
public class PageReq implements IPageReq{
|
||||
Integer page;
|
||||
Integer pageSize;
|
||||
List<String> sort;
|
||||
|
||||
@ -1,47 +0,0 @@
|
||||
package cn.axzo.foundation.page;
|
||||
|
||||
import cn.axzo.foundation.dao.support.wrapper.CriteriaField;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 默认分页请求基类:
|
||||
* 1、支持builder方式构建参数。
|
||||
* 2、默认分页大小为1000。
|
||||
* 3、支持指定不分页。searchCount = false
|
||||
*/
|
||||
@Data
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PageReqV2 implements IPageReq {
|
||||
private static final Integer DEFAULT_PAGE_SIZE_V2 = 1000;
|
||||
@CriteriaField(ignore = true)
|
||||
Integer page;
|
||||
@CriteriaField(ignore = true)
|
||||
Integer pageSize;
|
||||
@CriteriaField(ignore = true)
|
||||
Boolean searchCount;
|
||||
@CriteriaField(ignore = true)
|
||||
List<String> sort;
|
||||
|
||||
@Override
|
||||
public Integer getPage() {
|
||||
return page == null || page < 1 ? 1 : page;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getPageSize() {
|
||||
return pageSize == null || pageSize < 1 ? DEFAULT_PAGE_SIZE_V2 : pageSize;
|
||||
}
|
||||
|
||||
public Boolean isSearchCount() {
|
||||
// 只要不明确指定 searchCount = false,都要查count信息
|
||||
return BooleanUtils.isNotFalse(searchCount);
|
||||
}
|
||||
}
|
||||
@ -1,7 +1,6 @@
|
||||
package cn.axzo.foundation.util;
|
||||
|
||||
import cn.axzo.foundation.page.IPageReq;
|
||||
import cn.axzo.foundation.page.PageReqV2;
|
||||
import cn.axzo.foundation.page.PageResp;
|
||||
import com.google.common.collect.Lists;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
@ -11,40 +10,6 @@ import java.util.function.Function;
|
||||
|
||||
public class PageUtils {
|
||||
|
||||
/**
|
||||
* <pre>
|
||||
* 快捷拉取所有分页数据,默认从第一页开始拉取,直到返回的记录行数小于 预期的行数
|
||||
* 分页大小 为 pageReq.getPageSize(),可通过该参数调整。
|
||||
* </pre>
|
||||
* XXX: 注意,判断数据查询的完成条件,是 当前也页的记录行数 小于 分页大小,所以对于会破坏查询条件的请求参数,该方法不保证会返回所有数据
|
||||
*
|
||||
*
|
||||
* <pre>
|
||||
* 示例代码:
|
||||
* import cn.axzo.foundation.util.PageUtils;
|
||||
* // case 1. nodeUserService定义了以下方法:
|
||||
* PageResp<OrgNodeUserDTO> list(ListOrgNodeUserReq req); // ListOrgNodeUserReq extends PageReqV2
|
||||
* // 获取所有分页数据
|
||||
* List<OrgNodeUserDTO> nodeUsers = PageUtil.drainAll(req, nodeUserService::list);
|
||||
*
|
||||
* // case 2. nodeUserApi定义了以下方法
|
||||
* ApiResult<PageResp<OrgNodeUserDTO>> list(ListOrgNodeUserReq req); // ListOrgNodeUserReq extends PageReqV2
|
||||
* List<OrgNodeUserDTO> nodeUsers = PageUtil.drainAll(req, r -> nodeUserApi.list(r).getData());
|
||||
* </pre>
|
||||
*
|
||||
* @param pageReq
|
||||
* @param function
|
||||
* @param <T>
|
||||
* @param <R>
|
||||
* @return
|
||||
*/
|
||||
public static <T, R extends PageReqV2> List<T> drainAll(R pageReq, Function<R, PageResp<T>> function) {
|
||||
return PageUtils.drainAll(pageNumber -> {
|
||||
pageReq.setPage(pageNumber);
|
||||
return function.apply(pageReq);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 将所有的数据通过page接口写入到list. 并返回
|
||||
* function中需要参数为新的pageNum, 默认从第一页开始加载. 直到返回的记录行数小于 预期的行数
|
||||
|
||||
@ -2,7 +2,6 @@ package cn.axzo.foundation.util;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.MDC;
|
||||
|
||||
@UtilityClass
|
||||
@ -13,35 +12,27 @@ public class TraceUtils {
|
||||
*/
|
||||
public static final String TRACE_ID_IN_MDC = "TraceId";
|
||||
|
||||
/**
|
||||
* 老服务用的是 ctxLogId,这里兼容一下老服务
|
||||
*/
|
||||
public static final String TRACE_ID_CTX_LOG_ID = "ctxLogId";
|
||||
|
||||
public String getOrCreateTraceId() {
|
||||
String res = getTraceId();
|
||||
String res = MDC.get(TRACE_ID);
|
||||
if (Strings.isNullOrEmpty(res)) {
|
||||
res = UUIDBuilder.generateShortUuid();
|
||||
MDC.put(TRACE_ID, res);
|
||||
MDC.put(TRACE_ID_IN_MDC, res);
|
||||
MDC.put(TRACE_ID_CTX_LOG_ID, res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public String getTraceId() {
|
||||
return StringUtils.firstNonBlank(MDC.get(TRACE_ID_CTX_LOG_ID), MDC.get(TRACE_ID));
|
||||
return MDC.get(TRACE_ID);
|
||||
}
|
||||
|
||||
public void putTraceId(String traceId) {
|
||||
MDC.put(TRACE_ID, traceId);
|
||||
MDC.put(TRACE_ID_IN_MDC, traceId);
|
||||
MDC.put(TRACE_ID_CTX_LOG_ID, traceId);
|
||||
}
|
||||
|
||||
public void removeTraceId() {
|
||||
MDC.remove(TRACE_ID);
|
||||
MDC.remove(TRACE_ID_IN_MDC);
|
||||
MDC.remove(TRACE_ID_CTX_LOG_ID);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,7 +7,6 @@ import cn.axzo.foundation.util.PageUtils;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.core.metadata.OrderItem;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.apache.commons.lang3.BooleanUtils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
@ -35,7 +34,6 @@ public class PageConverter {
|
||||
= new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(current, pageSize);
|
||||
List<OrderItem> orderItems = MybatisPlusConverterUtils.convertOrderItems(page.getSort(), entityClz);
|
||||
myBatisPage.setOrders(orderItems);
|
||||
myBatisPage.setSearchCount(BooleanUtils.isNotFalse(page.isSearchCount()));
|
||||
|
||||
return myBatisPage;
|
||||
}
|
||||
|
||||
@ -2,7 +2,6 @@ package cn.axzo.foundation.web.support.interceptors;
|
||||
|
||||
import cn.axzo.foundation.util.TraceUtils;
|
||||
import com.google.common.base.Strings;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -15,7 +14,7 @@ public class TraceInterceptor implements HandlerInterceptor {
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
String upstreamTraceId = StringUtils.firstNonBlank(request.getHeader(TraceUtils.TRACE_ID_CTX_LOG_ID), request.getHeader(TraceUtils.TRACE_ID));
|
||||
String upstreamTraceId = request.getHeader(TraceUtils.TRACE_ID);
|
||||
if (!Strings.isNullOrEmpty(upstreamTraceId)) {
|
||||
// 优先使用上游的 traceId
|
||||
TraceUtils.putTraceId(upstreamTraceId);
|
||||
@ -23,7 +22,6 @@ public class TraceInterceptor implements HandlerInterceptor {
|
||||
|
||||
String traceId = TraceUtils.getOrCreateTraceId();
|
||||
request.setAttribute(TraceUtils.TRACE_ID_IN_MDC, traceId);
|
||||
request.setAttribute(TraceUtils.TRACE_ID_CTX_LOG_ID, traceId);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -27,14 +27,10 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 统一打印日志(支持忽略此aop, 采用@IgnoreRequestLog注解)<br>
|
||||
* @Deprecated 改类不会处理 @RequestMapping没有在controller上定义的情况。<br>
|
||||
* 建议使用{@link RequestLogV2Aspect}
|
||||
* @see RequestLogV2Aspect
|
||||
* 统一打印日志(支持忽略此aop, 采用@IgnoreRequestLog注解)
|
||||
**/
|
||||
@Aspect
|
||||
@Slf4j
|
||||
@Deprecated
|
||||
public class RequestLogAspect {
|
||||
private final static Integer DEFAULT_LOG_SIZE = 2048;
|
||||
private Integer logSize;
|
||||
|
||||
@ -1,144 +0,0 @@
|
||||
package cn.axzo.foundation.web.support.log;
|
||||
|
||||
import cn.axzo.foundation.exception.BusinessException;
|
||||
import cn.axzo.foundation.result.ApiResult;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.google.common.base.Stopwatch;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import lombok.Builder;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 统一打印日志(支持忽略此aop, 采用@IgnoreRequestLog注解)
|
||||
**/
|
||||
@Aspect
|
||||
@Slf4j
|
||||
public class RequestLogV2Aspect {
|
||||
private final static Integer DEFAULT_LOG_SIZE = 2048;
|
||||
private Integer logSize;
|
||||
|
||||
@Builder
|
||||
public RequestLogV2Aspect(Integer logSize) {
|
||||
this.logSize = Optional.ofNullable(logSize).orElse(DEFAULT_LOG_SIZE);
|
||||
}
|
||||
|
||||
private static Set<Class<?>> EXCLUDE_CLASSES = ImmutableSet.of(ServletRequest.class, ServletResponse.class,
|
||||
MultipartFile.class, BindingResult.class);
|
||||
|
||||
@Around("@within(restController)||@annotation(restController)")
|
||||
public Object doAround(ProceedingJoinPoint joinPoint, RestController restController) throws Throwable {
|
||||
//避免拦截非http请求. 如feign
|
||||
if (RequestContextHolder.getRequestAttributes() == null) {
|
||||
return joinPoint.proceed();
|
||||
}
|
||||
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
|
||||
if (request != null) {
|
||||
//用于在AbstractExceptionHandler中为dumpRequest, AbstractExceptionHandler无法直接获取body
|
||||
request.setAttribute("params", this.getUserArgs(joinPoint.getArgs()));
|
||||
}
|
||||
|
||||
IgnoreRequestLog annotation = AnnotationUtils.findAnnotation(((MethodSignature) joinPoint.getSignature()).getMethod(),
|
||||
IgnoreRequestLog.class);
|
||||
|
||||
// 获取注解中的ignoreTypes
|
||||
ImmutableSet<IgnoreRequestLog.IgnoreType> ignoreTypes = Optional.ofNullable(annotation)
|
||||
.map(a -> ImmutableSet.copyOf(a.types())).orElse(ImmutableSet.of());
|
||||
|
||||
Stopwatch stopwatch = Stopwatch.createStarted();
|
||||
String requestLog = buildRequestLog(joinPoint, ignoreTypes);
|
||||
|
||||
String userSession = StringUtils.EMPTY;
|
||||
String employeeSession = StringUtils.EMPTY;
|
||||
|
||||
String appClient = StringUtils.EMPTY;
|
||||
|
||||
|
||||
Object proceed;
|
||||
try {
|
||||
proceed = joinPoint.proceed(joinPoint.getArgs());
|
||||
} catch (BusinessException e) {
|
||||
//stein会收集error级别的异常并告警. 对BizException. 不期望收到告警邮件. 因此将BizException对应的日志级别调整为warn
|
||||
log.warn("api log, process error, caught BizException, url = {}, params = {}, userSession = {}, employeeSession = {}, appClient = {}, time cost = {} ms, BizException:",
|
||||
request.getRequestURI(), requestLog, userSession, employeeSession, appClient, stopwatch.elapsed(TimeUnit.MILLISECONDS), e);
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
log.error("api log, process error, uncaught exception, url = {}, params = {}, userSession = {}, employeeSession = {}, appClient = {}, time cost = {} ms, exception:",
|
||||
request.getRequestURI(), requestLog, userSession, employeeSession, appClient, stopwatch.elapsed(TimeUnit.MILLISECONDS), e);
|
||||
throw e;
|
||||
} catch (Error error) {
|
||||
log.error("api log, process error, uncaught error, url = {}, params = {}, userSession = {}, employeeSession = {}, appClient = {}, time cost = {} ms, error:",
|
||||
request.getRequestURI(), requestLog, userSession, employeeSession, appClient, stopwatch.elapsed(TimeUnit.MILLISECONDS), error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// 如果该接口定义的类型不是SILENT的, 则打印日志
|
||||
if (!ignoreTypes.contains(IgnoreRequestLog.IgnoreType.ALL)) {
|
||||
String responseLog;
|
||||
try {
|
||||
responseLog = buildResponseLog(proceed, ignoreTypes);
|
||||
} catch (Exception ex) {
|
||||
log.error("api log, process error, resp serialize error, url = {}, params = {}, userSession = {}, employeeSession = {}, appClient = {}, time cost = {} ms, error:",
|
||||
request.getRequestURI(), requestLog, userSession, employeeSession, appClient, stopwatch.elapsed(TimeUnit.MILLISECONDS), ex);
|
||||
throw ex;
|
||||
}
|
||||
log.info("api log, url = {}, params = {}, userSession = {}, employeeSession = {}, appClient = {}, result = {}, time cost = {} ms",
|
||||
request.getRequestURI(),
|
||||
StringUtils.left(requestLog, logSize),
|
||||
userSession,
|
||||
employeeSession,
|
||||
appClient,
|
||||
responseLog,
|
||||
stopwatch.elapsed(TimeUnit.MILLISECONDS));
|
||||
}
|
||||
|
||||
return proceed;
|
||||
}
|
||||
|
||||
private String buildRequestLog(ProceedingJoinPoint joinPoint, Set<IgnoreRequestLog.IgnoreType> ignoreTypes) {
|
||||
if (ignoreTypes.contains(IgnoreRequestLog.IgnoreType.REQUEST)) {
|
||||
return "IGNORED";
|
||||
}
|
||||
return JSONObject.toJSONString(this.getUserArgs(joinPoint.getArgs()));
|
||||
}
|
||||
|
||||
private String buildResponseLog(Object proceed, Set<IgnoreRequestLog.IgnoreType> ignoreTypes) {
|
||||
if (proceed == null || !(ApiResult.class.isAssignableFrom(proceed.getClass()))) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
if (ignoreTypes.contains(IgnoreRequestLog.IgnoreType.RESPONSE)) {
|
||||
return "IGNORED";
|
||||
}
|
||||
return StringUtils.left(JSONObject.toJSONString(proceed), logSize);
|
||||
}
|
||||
|
||||
protected List<Object> getUserArgs(Object[] args) {
|
||||
return Arrays.stream(args)
|
||||
.filter((p) ->
|
||||
Objects.nonNull(p) && EXCLUDE_CLASSES.stream().noneMatch(clz -> clz.isAssignableFrom(p.getClass()))
|
||||
|
||||
).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user