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;
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.result.ResponseBodyHandler;
import com.schbrain.common.web.servlet.*;
import com.schbrain.common.web.support.authentication.AuthenticationInterceptor;
import com.schbrain.common.web.support.authentication.Authenticator;
import com.schbrain.common.web.servlet.AllowAnyOriginWithoutCredentialsCorsConfigurer;
import com.schbrain.common.web.servlet.TraceIdInitializeServletListener;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
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.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.List;
......@@ -26,29 +24,11 @@ import java.util.List;
* @since 2021/11/19
*/
@AutoConfiguration
@ConditionalOnWebApplication
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(WebProperties.class)
@Import({AuthenticationConfiguration.class, ExceptionHandingConfiguration.class, ServletComponentConfiguration.class})
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
@ConditionalOnMissingBean
public BodyParamArgumentResolverWebMvcConfigurer defaultBodyParamArgumentResolverWebMvcConfigurer() {
......@@ -81,20 +61,8 @@ public class WebCommonAutoConfiguration {
@Bean
@ConditionalOnMissingBean
public CharacterEncodingServletContextInitializer characterEncodingServletContextInitializer(WebProperties webProperties) {
return new CharacterEncodingServletContextInitializer(webProperties.getEncoding());
}
@Bean
@ConditionalOnMissingBean
public RequestLoggingFilter requestLoggingFilter(WebProperties properties) {
return new RequestLoggingFilter(properties);
}
@Bean
@ConditionalOnMissingBean
public AllowAllCorsConfigurer allowAllCorsConfigurer() {
return new AllowAllCorsConfigurer();
public AllowAnyOriginWithoutCredentialsCorsConfigurer allowAnyOriginWithoutCredentialsCorsConfigurer() {
return new AllowAnyOriginWithoutCredentialsCorsConfigurer();
}
}
\ No newline at end of file
......@@ -7,14 +7,14 @@ import com.schbrain.common.web.annotation.BodyParam;
import lombok.Setter;
import org.springframework.core.MethodParameter;
import org.springframework.util.Assert;
import org.springframework.util.StreamUtils;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.annotation.AbstractNamedValueMethodArgumentResolver;
import javax.annotation.Nullable;
import javax.servlet.http.HttpServletRequest;
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
......@@ -23,7 +23,7 @@ import java.io.InputStream;
@Setter
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;
......@@ -48,10 +48,9 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg
}
@Override
@Nullable
protected Object resolveName(String name, MethodParameter parameter, NativeWebRequest request) throws Exception {
JsonNode paramNode = getParamNode(request);
JsonNode parameterValue = paramNode.get(name);
JsonNode requestBody = getRequestBody(request);
JsonNode parameterValue = requestBody.get(name);
if (parameterValue == null || parameterValue.isNull()) {
return null;
}
......@@ -59,16 +58,14 @@ public class BodyParamMethodArgumentResolver extends AbstractNamedValueMethodArg
return objectMapper.convertValue(parameterValue, parameterType);
}
private JsonNode getParamNode(NativeWebRequest nativeWebRequest) throws IOException {
HttpServletRequest request = nativeWebRequest.getNativeRequest(HttpServletRequest.class);
Assert.state(request != null, "request must not be null");
JsonNode paramNode = (JsonNode) request.getAttribute(METHOD_BODY_CACHE_KEY);
if (paramNode == null) {
InputStream inputStream = StreamUtils.nonClosing(request.getInputStream());
paramNode = objectMapper.readTree(inputStream);
request.setAttribute(METHOD_BODY_CACHE_KEY, paramNode);
private JsonNode getRequestBody(NativeWebRequest nativeWebRequest) throws IOException {
JsonNode requestBody = (JsonNode) nativeWebRequest.getAttribute(REQUEST_BODY_CACHE, SCOPE_REQUEST);
if (requestBody == null) {
HttpServletRequest request = wrapRequestIfRequired(nativeWebRequest.getNativeRequest(HttpServletRequest.class));
requestBody = objectMapper.readTree(request.getInputStream());
nativeWebRequest.setAttribute(REQUEST_BODY_CACHE, requestBody, SCOPE_REQUEST);
}
return paramNode;
return requestBody;
}
}
\ No newline at end of file
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 com.schbrain.common.web.properties.WebProperties;
import lombok.extern.slf4j.Slf4j;
......@@ -19,6 +19,8 @@ import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import static com.schbrain.common.web.utils.ContentCachingServletUtils.wrapRequestIfRequired;
/**
* 请求日志拦截器
*/
......@@ -44,6 +46,7 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere
}
request = wrapRequestIfRequired(request);
long startTime = System.currentTimeMillis();
try {
chain.doFilter(request, response);
......@@ -67,7 +70,7 @@ public class RequestLoggingFilter extends OncePerRequestFilter implements Ordere
String queryString = request.getQueryString();
String body = getRequestBody(request);
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)) {
builder.append(", queryString: ").append(queryString);
}
......@@ -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;
* @author liaozan
* @since 2022/11/19
*/
public class AllowAllCorsConfigurer implements WebMvcConfigurer {
public class AllowAnyOriginWithoutCredentialsCorsConfigurer implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
......
package com.schbrain.common.web.servlet;
import com.schbrain.common.util.TraceIdUtils;
import org.springframework.web.context.request.RequestContextListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
/**
* @author liaozan
* @since 2021/12/8
*/
public class TraceIdInitializeServletListener extends RequestContextListener {
public class TraceIdInitializeServletListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent event) {
super.requestInitialized(event);
// Make sure the traceId is initialized
TraceIdUtils.get();
}
@Override
public void requestDestroyed(ServletRequestEvent event) {
super.requestDestroyed(event);
// Make sure the traceId can be cleared
TraceIdUtils.clear();
}
......
......@@ -6,6 +6,7 @@ import com.schbrain.common.web.result.ResponseDTO;
import com.schbrain.common.web.support.BaseHandlerInterceptor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType;
import org.springframework.util.Assert;
import org.springframework.web.method.HandlerMethod;
......@@ -22,7 +23,7 @@ import static com.schbrain.common.constants.ResponseCodeConstants.LOGIN_REQUIRED
*/
@Data
@EqualsAndHashCode(callSuper = true)
public class AuthenticationInterceptor extends BaseHandlerInterceptor {
public class AuthenticationInterceptor extends BaseHandlerInterceptor implements Ordered {
private Authenticator authenticator;
......@@ -31,6 +32,11 @@ public class AuthenticationInterceptor extends BaseHandlerInterceptor {
this.authenticator = authenticator;
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
@Override
protected boolean preHandle(HttpServletRequest request, HttpServletResponse response, HandlerMethod 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
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
Map<String, Object> defaultProperties = new HashMap<>();
// management
defaultProperties.put("management.trace.http.enabled", false);
defaultProperties.put("management.endpoints.web.exposure.include", "*");
defaultProperties.put("management.endpoints.enabled-by-default", true);
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