Commit dd827731 authored by liaozan's avatar liaozan 🏀

Move WebCommonAutoConfiguration configurations

parent 079b20a9
package com.schbrain.common.web;
import com.schbrain.common.web.support.authentication.AuthenticationInterceptor;
import com.schbrain.common.web.support.authentication.Authenticator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author liaozan
* @since 2023-05-08
*/
@Configuration(proxyBeanMethods = false)
public class AuthenticationConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(Authenticator.class)
public AuthenticationInterceptor defaultAuthenticationInterceptor(Authenticator authenticator) {
return new AuthenticationInterceptor(authenticator);
}
}
\ No newline at end of file
package com.schbrain.common.web;
import com.schbrain.common.web.exception.*;
import com.schbrain.common.web.properties.WebProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author liaozan
* @since 2023-05-08
*/
@Configuration(proxyBeanMethods = false)
public class ExceptionHandingConfiguration {
@Bean
@ConditionalOnMissingBean
public GlobalExceptionHandler defaultGlobalExceptionHandler() {
return new DefaultGlobalExceptionHandler();
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(GlobalExceptionHandler.class)
public ExceptionHandlerWebMcvConfigurer defaultExceptionHandlerWebMcvConfigurer(WebProperties webProperties, GlobalExceptionHandler exceptionHandler) {
return new ExceptionHandlerWebMcvConfigurer(webProperties, exceptionHandler);
}
}
\ No newline at end of file
package com.schbrain.common.web;
import com.schbrain.common.web.log.RequestLoggingFilter;
import com.schbrain.common.web.properties.WebProperties;
import com.schbrain.common.web.servlet.CharacterEncodingServletContextInitializer;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.web.servlet.filter.OrderedRequestContextFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.filter.RequestContextFilter;
/**
* @author liaozan
* @since 2023-05-08
*/
@Configuration(proxyBeanMethods = false)
public class ServletComponentConfiguration {
@Bean
@ConditionalOnMissingBean
public CharacterEncodingServletContextInitializer characterEncodingServletContextInitializer(WebProperties webProperties) {
return new CharacterEncodingServletContextInitializer(webProperties.getEncoding());
}
@Bean
@ConditionalOnMissingBean
public RequestContextFilter requestContextFilter() {
OrderedRequestContextFilter requestContextFilter = new OrderedRequestContextFilter();
requestContextFilter.setThreadContextInheritable(true);
return requestContextFilter;
}
@Bean
@ConditionalOnMissingBean
public RequestLoggingFilter requestLoggingFilter(WebProperties properties) {
return new RequestLoggingFilter(properties);
}
}
\ No newline at end of file
package com.schbrain.common.web; package com.schbrain.common.web;
import com.schbrain.common.web.argument.BodyParamArgumentResolverWebMvcConfigurer; import com.schbrain.common.web.argument.BodyParamArgumentResolverWebMvcConfigurer;
import com.schbrain.common.web.exception.*;
import com.schbrain.common.web.log.RequestLoggingFilter;
import com.schbrain.common.web.properties.WebProperties; import com.schbrain.common.web.properties.WebProperties;
import com.schbrain.common.web.result.ResponseBodyHandler; import com.schbrain.common.web.result.ResponseBodyHandler;
import com.schbrain.common.web.servlet.*; import com.schbrain.common.web.servlet.AllowAnyOriginWithoutCredentialsCorsConfigurer;
import com.schbrain.common.web.support.authentication.AuthenticationInterceptor; import com.schbrain.common.web.servlet.TraceIdInitializeServletListener;
import com.schbrain.common.web.support.authentication.Authenticator;
import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigurationPackages; import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
import org.springframework.boot.autoconfigure.condition.*; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.client.RestTemplateBuilder; import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.*;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.client.RestTemplate; import org.springframework.web.client.RestTemplate;
import java.util.List; import java.util.List;
...@@ -26,29 +24,11 @@ import java.util.List; ...@@ -26,29 +24,11 @@ import java.util.List;
* @since 2021/11/19 * @since 2021/11/19
*/ */
@AutoConfiguration @AutoConfiguration
@ConditionalOnWebApplication @ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(WebProperties.class) @EnableConfigurationProperties(WebProperties.class)
@Import({AuthenticationConfiguration.class, ExceptionHandingConfiguration.class, ServletComponentConfiguration.class})
public class WebCommonAutoConfiguration { public class WebCommonAutoConfiguration {
@Bean
@ConditionalOnMissingBean
@ConditionalOnBean(Authenticator.class)
public AuthenticationInterceptor defaultAuthenticationInterceptor(Authenticator authenticator) {
return new AuthenticationInterceptor(authenticator);
}
@Bean
@ConditionalOnMissingBean
public GlobalExceptionHandler defaultGlobalExceptionHandler() {
return new DefaultGlobalExceptionHandler();
}
@Bean
@ConditionalOnMissingBean
public ExceptionHandlerWebMcvConfigurer defaultExceptionHandlerWebMcvConfigurer(WebProperties webProperties, GlobalExceptionHandler exceptionHandler) {
return new ExceptionHandlerWebMcvConfigurer(webProperties, exceptionHandler);
}
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public BodyParamArgumentResolverWebMvcConfigurer defaultBodyParamArgumentResolverWebMvcConfigurer() { public BodyParamArgumentResolverWebMvcConfigurer defaultBodyParamArgumentResolverWebMvcConfigurer() {
...@@ -81,20 +61,8 @@ public class WebCommonAutoConfiguration { ...@@ -81,20 +61,8 @@ public class WebCommonAutoConfiguration {
@Bean @Bean
@ConditionalOnMissingBean @ConditionalOnMissingBean
public CharacterEncodingServletContextInitializer characterEncodingServletContextInitializer(WebProperties webProperties) { public AllowAnyOriginWithoutCredentialsCorsConfigurer allowAnyOriginWithoutCredentialsCorsConfigurer() {
return new CharacterEncodingServletContextInitializer(webProperties.getEncoding()); return new AllowAnyOriginWithoutCredentialsCorsConfigurer();
}
@Bean
@ConditionalOnMissingBean
public RequestLoggingFilter requestLoggingFilter(WebProperties properties) {
return new RequestLoggingFilter(properties);
}
@Bean
@ConditionalOnMissingBean
public AllowAllCorsConfigurer allowAllCorsConfigurer() {
return new AllowAllCorsConfigurer();
} }
} }
\ No newline at end of file
...@@ -7,14 +7,14 @@ import com.schbrain.common.web.annotation.BodyParam; ...@@ -7,14 +7,14 @@ import com.schbrain.common.web.annotation.BodyParam;
import lombok.Setter; import lombok.Setter;
import org.springframework.core.MethodParameter; import org.springframework.core.MethodParameter;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.web.context.request.NativeWebRequest; import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver; import org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import static com.schbrain.common.web.utils.ContentCachingServletUtils.wrapRequestIfRequired;
import static org.springframework.web.context.request.RequestAttributes.SCOPE_REQUEST;
/** /**
* @author liaozan * @author liaozan
...@@ -23,7 +23,7 @@ import java.io.InputStream; ...@@ -23,7 +23,7 @@ import java.io.InputStream;
@Setter @Setter
public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver { public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArgumentResolver {
private static final String METHOD_BODY_CACHE_KEY = BodyParamMethodArgumentResolver.class.getName() + ".bodyParamCache"; private static final String REQUEST_BODY_CACHE = BodyParamMethodArgumentResolver.class.getName() + ".requestBodyCache";
private ObjectMapper objectMapper; private ObjectMapper objectMapper;
...@@ -48,10 +48,9 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg ...@@ -48,10 +48,9 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg
} }
@Override @Override
@Nullable
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception { protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
JsonNode paramNode = getParamNode(request); JsonNode requestBody = getRequestBody(request);
JsonNode parameterValue = paramNode.get(name); JsonNode parameterValue = requestBody.get(name);
if (parameterValue == null || parameterValue.isNull()) { if (parameterValue == null || parameterValue.isNull()) {
return null; return null;
} }
...@@ -59,16 +58,14 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg ...@@ -59,16 +58,14 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg
return objectMapper.convertValue(parameterValue, parameterType); return objectMapper.convertValue(parameterValue, parameterType);
} }
private JsonNode getParamNode(NativeWebRequest nativeWebRequest) throws IOException { private JsonNode getRequestBody(NativeWebRequest nativeWebRequest) throws IOException {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class); JsonNode requestBody = (JsonNode) nativeWebRequest.getAttribute(REQUEST_BODY_CACHE, SCOPE_REQUEST);
Assert.state(request != null, "request must not be null"); if (requestBody == null) {
JsonNode paramNode = (JsonNode) request.getAttribute(METHOD_BODY_CACHE_KEY); HttpServletRequest request = wrapRequestIfRequired(nativeWebRequest.getNativeRequest(HttpServletRequest.class));
if (paramNode == null) { requestBody = objectMapper.readTree(request.getInputStream());
InputStream inputStream = StreamUtils.nonClosing(request.getInputStream()); nativeWebRequest.setAttribute(REQUEST_BODY_CACHE, requestBody, SCOPE_REQUEST);
paramNode = objectMapper.readTree(inputStream);
request.setAttribute(METHOD_BODY_CACHE_KEY, paramNode);
} }
return paramNode; return requestBody;
} }
} }
\ No newline at end of file
package com.schbrain.common.web.log; package com.schbrain.common.web.log;
import cn.hutool.core.text.StrPool; import cn.hutool.core.text.CharPool;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import com.schbrain.common.web.properties.WebProperties; import com.schbrain.common.web.properties.WebProperties;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -19,6 +19,8 @@ import javax.servlet.http.HttpServletResponse; ...@@ -19,6 +19,8 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import static com.schbrain.common.web.utils.ContentCachingServletUtils.wrapRequestIfRequired;
/** /**
* 请求日志拦截器 * 请求日志拦截器
*/ */
...@@ -44,6 +46,7 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere ...@@ -44,6 +46,7 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere
} }
request = wrapRequestIfRequired(request); request = wrapRequestIfRequired(request);
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
try { try {
chain.doFilter(request, response); chain.doFilter(request, response);
...@@ -67,7 +70,7 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere ...@@ -67,7 +70,7 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere
String queryString = request.getQueryString(); String queryString = request.getQueryString();
String body = getRequestBody(request); String body = getRequestBody(request);
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append("requestUri: ").append(method).append(StrPool.C_SPACE).append(requestUri); builder.append("requestUri: ").append(method).append(CharPool.SPACE).append(requestUri);
if (StringUtils.hasText(queryString)) { if (StringUtils.hasText(queryString)) {
builder.append(", queryString: ").append(queryString); builder.append(", queryString: ").append(queryString);
} }
...@@ -98,12 +101,4 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere ...@@ -98,12 +101,4 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere
} }
} }
protected HttpServletRequest wrapRequestIfRequired(HttpServletRequest request) {
if (request instanceof ContentCachingRequestWrapper) {
return request;
} else {
return new ContentCachingRequestWrapper(request);
}
}
} }
\ No newline at end of file
...@@ -10,7 +10,7 @@ import java.time.Duration; ...@@ -10,7 +10,7 @@ import java.time.Duration;
* @author liaozan * @author liaozan
* @since 2022/11/19 * @since 2022/11/19
*/ */
public class AllowAllCorsConfigurer implements WebMvcConfigurer { public class AllowAnyOriginWithoutCredentialsCorsConfigurer implements WebMvcConfigurer {
@Override @Override
public void addCorsMappings(CorsRegistry registry) { public void addCorsMappings(CorsRegistry registry) {
......
package com.schbrain.common.web.servlet; package com.schbrain.common.web.servlet;
import com.schbrain.common.util.TraceIdUtils; import com.schbrain.common.util.TraceIdUtils;
import org.springframework.web.context.request.RequestContextListener;
import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
/** /**
* @author liaozan * @author liaozan
* @since 2021/12/8 * @since 2021/12/8
*/ */
public class TraceIdInitializeServletListener extends RequestContextListener { public class TraceIdInitializeServletListener implements ServletRequestListener {
@Override @Override
public void requestInitialized(ServletRequestEvent event) { public void requestInitialized(ServletRequestEvent event) {
super.requestInitialized(event);
// Make sure the traceId is initialized // Make sure the traceId is initialized
TraceIdUtils.get(); TraceIdUtils.get();
} }
@Override @Override
public void requestDestroyed(ServletRequestEvent event) { public void requestDestroyed(ServletRequestEvent event) {
super.requestDestroyed(event);
// Make sure the traceId can be cleared // Make sure the traceId can be cleared
TraceIdUtils.clear(); TraceIdUtils.clear();
} }
......
...@@ -6,6 +6,7 @@ import com.schbrain.common.web.result.ResponseDTO; ...@@ -6,6 +6,7 @@ import com.schbrain.common.web.result.ResponseDTO;
import com.schbrain.common.web.support.BaseHandlerInterceptor; import com.schbrain.common.web.support.BaseHandlerInterceptor;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.HandlerMethod;
...@@ -22,7 +23,7 @@ import static com.schbrain.common.constants.ResponseCodeConstants.LOGIN_REQUIRED ...@@ -22,7 +23,7 @@ import static com.schbrain.common.constants.ResponseCodeConstants.LOGIN_REQUIRED
*/ */
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
public class AuthenticationInterceptor extends BaseHandlerInterceptor { public class AuthenticationInterceptor extends BaseHandlerInterceptor implements Ordered {
private Authenticator authenticator; private Authenticator authenticator;
...@@ -31,6 +32,11 @@ public class AuthenticationInterceptor extends BaseHandlerInterceptor { ...@@ -31,6 +32,11 @@ public class AuthenticationInterceptor extends BaseHandlerInterceptor {
this.authenticator = authenticator; this.authenticator = authenticator;
} }
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
@Override @Override
protected boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler) { protected boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod handler) {
boolean validated = authenticator.validate(request, response, handler); boolean validated = authenticator.validate(request, response, handler);
......
package com.schbrain.common.web.utils;
import org.springframework.util.Assert;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @author liaozan
* @since 2023-05-08
*/
public class ContentCachingServletUtils {
/**
* Make request content cacheable to avoid stream closed error after inputStream closed
*/
public static HttpServletRequest wrapRequestIfRequired(HttpServletRequest request) {
Assert.notNull(request, "request must not be null");
if (request instanceof ContentCachingRequestWrapper) {
return request;
} else {
return new ContentCachingRequestWrapper(request);
}
}
/**
* Make response content cacheable to avoid stream closed error after outputStream closed
*/
public static HttpServletResponse wrapResponseIfRequired(HttpServletResponse response) {
Assert.notNull(response, "response must not be null");
if (response instanceof ContentCachingResponseWrapper) {
return response;
} else {
return new ContentCachingResponseWrapper(response);
}
}
}
\ No newline at end of file
...@@ -42,6 +42,7 @@ public class DefaultPropertiesEnvironmentPostProcessor extends LoggerAwareEnviro ...@@ -42,6 +42,7 @@ public class DefaultPropertiesEnvironmentPostProcessor extends LoggerAwareEnviro
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Map<String, Object> defaultProperties = new HashMap<>(); Map<String, Object> defaultProperties = new HashMap<>();
// management // management
defaultProperties.put("management.trace.http.enabled", false);
defaultProperties.put("management.endpoints.web.exposure.include", "*"); defaultProperties.put("management.endpoints.web.exposure.include", "*");
defaultProperties.put("management.endpoints.enabled-by-default", true); defaultProperties.put("management.endpoints.enabled-by-default", true);
defaultProperties.put("management.endpoint.health.show-details", Show.ALWAYS); defaultProperties.put("management.endpoint.health.show-details", Show.ALWAYS);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment