feat(REQ-2516): 通过 MDC 兼容应用使用了异步(如 Completable)导致的无法正确传递 header 以及 pkg 参数的问题

This commit is contained in:
wangli 2024-06-25 09:56:51 +08:00
parent ddf1bbcd9d
commit a3d8646249
4 changed files with 66 additions and 13 deletions

View File

@ -10,7 +10,9 @@ import cn.axzo.framework.autoconfigure.web.exception.support.GlobalExceptionHand
import cn.axzo.framework.domain.web.result.Result;
import cn.axzo.framework.web.exception.BasicRecordExceptionHandler;
import cn.axzo.framework.web.feign.FeignRecordExceptionInterceptor;
import cn.axzo.framework.web.filter.BasicRecordExceptionFilter;
import feign.RequestInterceptor;
import org.slf4j.MDC;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
@ -25,6 +27,7 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.common.exceptions.OAuth2Exception;
import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
@ -200,5 +203,11 @@ public class ExceptionHandlerAutoConfiguration implements WebMvcConfigurer {
public BasicRecordExceptionHandler basicRecordExceptionHandler() {
return new BasicRecordExceptionHandler();
}
@Bean
@ConditionalOnClass(MDC.class)
public OncePerRequestFilter oncePerRequestFilter() {
return new BasicRecordExceptionFilter();
}
}
}

View File

@ -58,8 +58,10 @@ public final class BasicRecordExceptionHandler implements PriorityOrdered {
@ExceptionHandler(value = Throwable.class)
public ApiResult<?> globalException(HttpServletRequest request, HttpServletResponse response, Throwable e) throws Throwable {
String headerValue;
if (StringUtils.hasText(recordExceptionHeaderName) && Objects.nonNull(headerValue = request.getHeader(recordExceptionHeaderName))) {
String headerValue = request.getHeader(recordExceptionHeaderName);
if (!StringUtils.hasText(headerValue)) {
headerValue = MDC.get(recordExceptionHeaderName);
}
log.debug("recordException HeaderName: {}", headerValue);
if (Boolean.parseBoolean(headerValue)) {
ApiResult error = ApiResult.err(500, "discovery server internal error");
@ -68,8 +70,6 @@ public final class BasicRecordExceptionHandler implements PriorityOrdered {
error.setData(rebuildThrowable(e, request));
return error;
}
throw e;
}
// 重新抛出
throw e;
}
@ -96,8 +96,10 @@ public final class BasicRecordExceptionHandler implements PriorityOrdered {
}
String[] parameterValues = request.getParameterValues(MICRO_SERVER_RECORD_ERROR_GET_PARAM_NAME);
List<String> filterPackageNames = Lists.newArrayList(MICRO_SERVER_RECORD_ERROR_FILTER_PACKAGE_VALUE);
if(Objects.nonNull(parameterValues) && parameterValues.length > 0) {
if (Objects.nonNull(parameterValues) && parameterValues.length > 0) {
filterPackageNames = Arrays.asList(parameterValues);
} else if (StringUtils.hasText(MDC.get(MICRO_SERVER_RECORD_ERROR_GET_PARAM_NAME))) {
filterPackageNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray(MDC.get(MICRO_SERVER_RECORD_ERROR_GET_PARAM_NAME)));
}
for (StackTraceElement e : elements) {
if (StringUtils.hasText(e.getClassName())) {

View File

@ -43,7 +43,7 @@ public class FeignRecordExceptionInterceptor implements RequestInterceptor {
template.header(MICRO_SERVER_RECORD_ERROR_HEADER_NAME, originalRequest.getHeader(MICRO_SERVER_RECORD_ERROR_HEADER_NAME));
}
public HttpServletRequest getOriginalRequest() {
public static HttpServletRequest getOriginalRequest() {
try {
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
return attributes.getRequest();

View File

@ -0,0 +1,42 @@
package cn.axzo.framework.web.filter;
import cn.axzo.framework.validator.constraints.UTF8;
import com.google.common.collect.Lists;
import jdk.nashorn.internal.runtime.JSONFunctions;
import org.slf4j.MDC;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import static cn.axzo.framework.web.exception.BasicRecordExceptionHandler.MICRO_SERVER_RECORD_ERROR_GET_PARAM_NAME;
import static cn.axzo.framework.web.exception.BasicRecordExceptionHandler.MICRO_SERVER_RECORD_ERROR_HEADER_NAME;
/**
* TODO
*
* @author wangli
* @since 2024/6/25 09:40
*/
public class BasicRecordExceptionFilter extends OncePerRequestFilter implements PriorityOrdered {
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String[] packageNames = request.getParameterValues(MICRO_SERVER_RECORD_ERROR_GET_PARAM_NAME);
MDC.put(MICRO_SERVER_RECORD_ERROR_GET_PARAM_NAME, StringUtils.arrayToCommaDelimitedString(packageNames));
// 需要传递外部传入的标识
MDC.put(MICRO_SERVER_RECORD_ERROR_HEADER_NAME, request.getHeader(MICRO_SERVER_RECORD_ERROR_HEADER_NAME));
}
}