diff --git a/common/common-framework/pom.xml b/common/common-framework/pom.xml
index 94ad59cb3..d7ec41bd7 100644
--- a/common/common-framework/pom.xml
+++ b/common/common-framework/pom.xml
@@ -90,6 +90,12 @@
compile
+
+ org.apache.skywalking
+ apm-toolkit-trace
+ 6.1.0
+
+
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/MallConstants.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/MallConstants.java
new file mode 100644
index 000000000..1ca49c508
--- /dev/null
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/constant/MallConstants.java
@@ -0,0 +1,42 @@
+package cn.iocoder.common.framework.constant;
+
+/**
+ * Mall 全局枚举
+ */
+public interface MallConstants {
+
+ // 全局请求路径枚举类,用于定义不同用户类型的根请求路径
+ /**
+ * 根路径 - 用户
+ */
+ String ROOT_PATH_USER = "/users";
+ /**
+ * 根路径 - 管理员
+ */
+ String ROOT_PATH_ADMIN = "/admins";
+
+ // 用户类型
+ /**
+ * 用户类型 - 用户
+ */
+ Integer USER_TYPE_USER = 1;
+ /**
+ * 用户类型 - 管理员
+ */
+ Integer USER_TYPE_ADMIN = 2;
+
+ // HTTP Request Attr
+ /**
+ * HTTP Request Attr - 用户编号
+ */
+ String REQUEST_ATTR_USER_ID_KEY = "mall_user_id";
+ /**
+ * HTTP Request Attr - 用户类型
+ */
+ String REQUEST_ATTR_USER_TYPE_KEY = "mall_user_type";
+ /**
+ * HTTP Request Attr - Controller 执行返回
+ */
+ String REQUEST_ATTR_COMMON_RESULT = "mall_common_result";
+
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/config/GlobalExceptionHandler.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/exception/GlobalExceptionHandler.java
similarity index 96%
rename from common/common-framework/src/main/java/cn/iocoder/common/framework/config/GlobalExceptionHandler.java
rename to common/common-framework/src/main/java/cn/iocoder/common/framework/exception/GlobalExceptionHandler.java
index 61909bbfb..f49d1872b 100644
--- a/common/common-framework/src/main/java/cn/iocoder/common/framework/config/GlobalExceptionHandler.java
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/exception/GlobalExceptionHandler.java
@@ -1,7 +1,6 @@
-package cn.iocoder.common.framework.config;
+package cn.iocoder.common.framework.exception;
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
-import cn.iocoder.common.framework.exception.ServiceException;
import cn.iocoder.common.framework.vo.CommonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/servlet/CorsFilter.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/servlet/CorsFilter.java
index 1080f4816..5db9df03e 100644
--- a/common/common-framework/src/main/java/cn/iocoder/common/framework/servlet/CorsFilter.java
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/servlet/CorsFilter.java
@@ -5,6 +5,11 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
+/**
+ * Cors 过滤器
+ *
+ * 未来使用 {@link org.springframework.web.filter.CorsFilter} 替换
+ */
public class CorsFilter implements Filter {
@Override
@@ -32,4 +37,4 @@ public class CorsFilter implements Filter {
public void destroy() {
}
-}
\ No newline at end of file
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/util/HttpUtil.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/util/HttpUtil.java
index c71bb9323..9251ef3da 100644
--- a/common/common-framework/src/main/java/cn/iocoder/common/framework/util/HttpUtil.java
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/util/HttpUtil.java
@@ -44,7 +44,7 @@ public class HttpUtil {
*/
public static final String DEFAULT_CHARACTER_ENCODING = "ISO-8859-1";
- public static String obtainAccess(HttpServletRequest request) {
+ public static String obtainAuthorization(HttpServletRequest request) {
String authorization = request.getHeader("Authorization");
if (!StringUtils.hasText(authorization)) {
return null;
@@ -316,4 +316,4 @@ public class HttpUtil {
return enc;
}
-}
\ No newline at end of file
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/util/MallUtil.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/util/MallUtil.java
new file mode 100644
index 000000000..99d97fa75
--- /dev/null
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/util/MallUtil.java
@@ -0,0 +1,53 @@
+package cn.iocoder.common.framework.util;
+
+import cn.iocoder.common.framework.constant.MallConstants;
+import cn.iocoder.common.framework.vo.CommonResult;
+import org.apache.skywalking.apm.toolkit.trace.TraceContext;
+
+import javax.servlet.ServletRequest;
+import java.util.UUID;
+
+public class MallUtil {
+
+ public static Integer getUserId(ServletRequest request) {
+ return (Integer) request.getAttribute(MallConstants.REQUEST_ATTR_USER_ID_KEY);
+ }
+
+ public static void setUserId(ServletRequest request, Integer userId) {
+ request.setAttribute(MallConstants.REQUEST_ATTR_USER_ID_KEY, userId);
+ }
+
+ public static Integer getUserType(ServletRequest request) {
+ return (Integer) request.getAttribute(MallConstants.REQUEST_ATTR_USER_TYPE_KEY);
+ }
+
+ public static void setUserType(ServletRequest request, Integer userType) {
+ request.setAttribute(MallConstants.REQUEST_ATTR_USER_TYPE_KEY, userType);
+ }
+
+ public static CommonResult getCommonResult(ServletRequest request) {
+ return (CommonResult) request.getAttribute(MallConstants.REQUEST_ATTR_COMMON_RESULT);
+ }
+
+ public static void setCommonResult(ServletRequest request, CommonResult result) {
+ request.setAttribute(MallConstants.REQUEST_ATTR_COMMON_RESULT, result);
+ }
+
+ /**
+ * 获得链路追踪编号
+ *
+ * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
+ *
+ * 默认情况下,我们使用 Apache SkyWalking 的 traceId 作为链路追踪编号。当然,可能会存在并未引入 Skywalking 的情况,此时使用 UUID 。
+ *
+ * @return 链路追踪编号
+ */
+ public static String getTraceId() {
+ String traceId = TraceContext.traceId();
+ if (StringUtil.hasText(traceId)) {
+ return traceId;
+ }
+ return UUID.randomUUID().toString();
+ }
+
+}
diff --git a/common/common-framework/src/main/java/cn/iocoder/common/framework/vo/CommonResult.java b/common/common-framework/src/main/java/cn/iocoder/common/framework/vo/CommonResult.java
index 630c7848e..c03e5db50 100644
--- a/common/common-framework/src/main/java/cn/iocoder/common/framework/vo/CommonResult.java
+++ b/common/common-framework/src/main/java/cn/iocoder/common/framework/vo/CommonResult.java
@@ -5,7 +5,7 @@ import org.springframework.util.Assert;
import java.io.Serializable;
-public class CommonResult implements Serializable {
+public final class CommonResult implements Serializable {
public static Integer CODE_SUCCESS = 0;
diff --git a/common/mall-spring-boot/pom.xml b/common/mall-spring-boot/pom.xml
index 0340ec1be..879a79fd9 100644
--- a/common/mall-spring-boot/pom.xml
+++ b/common/mall-spring-boot/pom.xml
@@ -47,6 +47,17 @@
true
+
+ io.springfox
+ springfox-swagger2
+ true
+
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ true
+
+
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/constant/RootRequestPath.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/constant/RootRequestPath.java
deleted file mode 100644
index 7111b70fe..000000000
--- a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/constant/RootRequestPath.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package cn.iocoder.mall.spring.boot.constant;
-
-/**
- * 全局请求路径枚举类,用于定义不同用户类型的根请求路径
- */
-public interface RootRequestPath {
-
- /**
- * 管理员
- */
- String ADMIN = "/admins";
- /**
- * 用户
- */
- String USER = "/users";
-
-}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerAutoConfiguration.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerAutoConfiguration.java
new file mode 100644
index 000000000..dd1748f4a
--- /dev/null
+++ b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerAutoConfiguration.java
@@ -0,0 +1,57 @@
+package cn.iocoder.mall.spring.boot.swagger;
+
+import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spring.web.plugins.Docket;
+import springfox.documentation.swagger2.annotations.EnableSwagger2;
+
+/**
+ * 简单的 Swagger2 自动配置类
+ *
+ * 较为完善的,可以了解 https://mvnrepository.com/artifact/com.spring4all/spring-boot-starter-swagger
+ */
+@Configuration
+@EnableSwagger2
+@EnableSwaggerBootstrapUI
+@ConditionalOnClass({Docket.class, ApiInfoBuilder.class})
+@ConditionalOnProperty(prefix = "swagger", value = "enable", matchIfMissing = true) // 允许使用 swagger.enable=false 禁用 Swagger
+@EnableConfigurationProperties(SwaggerProperties.class)
+public class SwaggerAutoConfiguration {
+
+ @Bean
+ @ConditionalOnMissingBean
+ public SwaggerProperties swaggerProperties() {
+ return new SwaggerProperties();
+ }
+
+ @Bean
+ public Docket createRestApi() {
+ SwaggerProperties properties = swaggerProperties();
+ // 创建 Docket 对象
+ return new Docket(DocumentationType.SWAGGER_2)
+ .apiInfo(apiInfo(properties))
+ .select()
+ .apis(RequestHandlerSelectors.basePackage(properties.getBasePackage()))
+ .paths(PathSelectors.any())
+ .build();
+ }
+
+ private ApiInfo apiInfo(SwaggerProperties properties) {
+ return new ApiInfoBuilder()
+ .title(properties.getTitle())
+ .description(properties.getDescription())
+ .version(properties.getVersion())
+ .build();
+ }
+
+}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerProperties.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerProperties.java
new file mode 100644
index 000000000..b0e1c960d
--- /dev/null
+++ b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerProperties.java
@@ -0,0 +1,15 @@
+package cn.iocoder.mall.spring.boot.swagger;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+@Data
+@ConfigurationProperties("swagger")
+public class SwaggerProperties {
+
+ private String title;
+ private String description;
+ private String version;
+ private String basePackage;
+
+}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCAutoConfiguration.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCAutoConfiguration.java
new file mode 100644
index 000000000..66811dc6e
--- /dev/null
+++ b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCAutoConfiguration.java
@@ -0,0 +1,64 @@
+package cn.iocoder.mall.spring.boot.web;
+
+import cn.iocoder.common.framework.constant.MallConstants;
+import cn.iocoder.common.framework.servlet.CorsFilter;
+import cn.iocoder.mall.spring.boot.web.interceptor.AccessLogInterceptor;
+import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
+import cn.iocoder.mall.spring.boot.web.handler.GlobalExceptionHandler;
+import cn.iocoder.mall.spring.boot.web.handler.GlobalResponseBodyHandler;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.DispatcherServlet;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) // TODO 芋艿,未来可能考虑 REACTIVE
+@ConditionalOnClass({DispatcherServlet.class, WebMvcConfigurer.class, // 有 Spring MVC 容器
+ AdminSecurityInterceptor.class, AccessLogInterceptor.class}) // 有引入 system-sdk
+public class AdminMVCAutoConfiguration implements WebMvcConfigurer {
+
+ @Bean
+// @ConditionalOnMissingBean(AccessLogInterceptor.class)
+ public AccessLogInterceptor adminAccessLogInterceptor() {
+ return new AccessLogInterceptor();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(AdminSecurityInterceptor.class)
+ public AdminSecurityInterceptor adminSecurityInterceptor() {
+ return new AdminSecurityInterceptor();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(GlobalResponseBodyHandler.class)
+ public GlobalResponseBodyHandler globalReturnValueHandler() {
+ return new GlobalResponseBodyHandler();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(GlobalResponseBodyHandler.class)
+ public GlobalExceptionHandler globalExceptionHandler() {
+ return new GlobalExceptionHandler();
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(adminAccessLogInterceptor()).addPathPatterns(MallConstants.ROOT_PATH_ADMIN + "/**");
+ registry.addInterceptor(adminSecurityInterceptor()).addPathPatterns(MallConstants.ROOT_PATH_ADMIN + "/**");
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public FilterRegistrationBean corsFilter() {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
+ registrationBean.setFilter(new CorsFilter());
+ registrationBean.addUrlPatterns("/*");
+ return registrationBean;
+ }
+
+}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCConfiguration.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCConfiguration.java
deleted file mode 100644
index 1e64ca1bc..000000000
--- a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCConfiguration.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package cn.iocoder.mall.spring.boot.web;
-
-import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor;
-import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
-import cn.iocoder.mall.spring.boot.constant.RootRequestPath;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.DispatcherServlet;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) // TODO 芋艿,未来可能考虑 REACTIVE
-@ConditionalOnClass({DispatcherServlet.class, WebMvcConfigurer.class, // 有 Spring MVC 容器
- AdminSecurityInterceptor.class, AdminAccessLogInterceptor.class}) // 有引入 system-sdk
-public class AdminMVCConfiguration implements WebMvcConfigurer {
-
- @Bean
- @ConditionalOnMissingBean(AdminSecurityInterceptor.class)
- public AdminSecurityInterceptor adminSecurityInterceptor() {
- return new AdminSecurityInterceptor();
- }
-
- @Bean
- @ConditionalOnMissingBean(AdminAccessLogInterceptor.class)
- public AdminAccessLogInterceptor adminAccessLogInterceptor() {
- return new AdminAccessLogInterceptor();
- }
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(adminAccessLogInterceptor()).addPathPatterns(RootRequestPath.ADMIN + "/**");
- registry.addInterceptor(adminSecurityInterceptor()).addPathPatterns(RootRequestPath.ADMIN + "/**");
- }
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping(RootRequestPath.USER + "/**")
- .allowedOrigins("*")
- .allowedMethods("*")
- .allowedHeaders("*")
- .allowCredentials(true).maxAge(1800);
- }
-
-}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCAutoConfiguration.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCAutoConfiguration.java
new file mode 100644
index 000000000..e64b73ba2
--- /dev/null
+++ b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCAutoConfiguration.java
@@ -0,0 +1,65 @@
+package cn.iocoder.mall.spring.boot.web;
+
+import cn.iocoder.common.framework.constant.MallConstants;
+import cn.iocoder.common.framework.servlet.CorsFilter;
+import cn.iocoder.mall.spring.boot.web.interceptor.AccessLogInterceptor;
+import cn.iocoder.mall.spring.boot.web.handler.GlobalExceptionHandler;
+import cn.iocoder.mall.spring.boot.web.handler.GlobalResponseBodyHandler;
+import cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.DispatcherServlet;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@Configuration
+@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) // TODO 芋艿,未来可能考虑 REACTIVE
+@ConditionalOnClass({DispatcherServlet.class, WebMvcConfigurer.class, // 有 Spring MVC 容器
+ UserSecurityInterceptor.class, // 有引入 user-sdk
+ AccessLogInterceptor.class}) // 有引入 system-sdk
+public class UserMVCAutoConfiguration implements WebMvcConfigurer {
+
+ @Bean
+// @ConditionalOnMissingBean(AccessLogInterceptor.class)
+ public AccessLogInterceptor userAccessLogInterceptor() {
+ return new AccessLogInterceptor();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(UserSecurityInterceptor.class)
+ public UserSecurityInterceptor userSecurityInterceptor() {
+ return new UserSecurityInterceptor();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(GlobalResponseBodyHandler.class)
+ public GlobalResponseBodyHandler globalReturnValueHandler() {
+ return new GlobalResponseBodyHandler();
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(GlobalExceptionHandler.class)
+ public GlobalExceptionHandler globalExceptionHandler() {
+ return new GlobalExceptionHandler();
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry) {
+ registry.addInterceptor(userAccessLogInterceptor()).addPathPatterns(MallConstants.ROOT_PATH_USER + "/**");
+ registry.addInterceptor(userSecurityInterceptor()).addPathPatterns(MallConstants.ROOT_PATH_USER + "/**");
+ }
+
+ @Bean
+ @ConditionalOnMissingBean
+ public FilterRegistrationBean corsFilter() {
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
+ registrationBean.setFilter(new CorsFilter());
+ registrationBean.addUrlPatterns("/*");
+ return registrationBean;
+ }
+
+}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCConfiguration.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCConfiguration.java
deleted file mode 100644
index 8db827006..000000000
--- a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCConfiguration.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package cn.iocoder.mall.spring.boot.web;
-
-import cn.iocoder.mall.spring.boot.constant.RootRequestPath;
-import cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor;
-import cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.DispatcherServlet;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@Configuration
-@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET) // TODO 芋艿,未来可能考虑 REACTIVE
-@ConditionalOnClass({DispatcherServlet.class, WebMvcConfigurer.class, // 有 Spring MVC 容器
- UserSecurityInterceptor.class, UserAccessLogInterceptor.class}) // 有引入 system-sdk
-public class UserMVCConfiguration implements WebMvcConfigurer {
-
- @Bean
- @ConditionalOnMissingBean(UserAccessLogInterceptor.class)
- public UserAccessLogInterceptor userAccessLogInterceptor() {
- return new UserAccessLogInterceptor();
- }
-
- @Bean
- @ConditionalOnMissingBean(UserSecurityInterceptor.class)
- public UserSecurityInterceptor userSecurityInterceptor() {
- return new UserSecurityInterceptor();
- }
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- registry.addInterceptor(userAccessLogInterceptor()).addPathPatterns(RootRequestPath.USER + "/**");
- registry.addInterceptor(userSecurityInterceptor()).addPathPatterns(RootRequestPath.USER + "/**");
- }
-
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping(RootRequestPath.USER + "/**")
- .allowedOrigins("*")
- .allowedMethods("*")
- .allowedHeaders("*")
- .allowCredentials(true).maxAge(1800);
- }
-
-}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalExceptionHandler.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalExceptionHandler.java
new file mode 100644
index 000000000..efbc51b04
--- /dev/null
+++ b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalExceptionHandler.java
@@ -0,0 +1,70 @@
+package cn.iocoder.mall.spring.boot.web.handler;
+
+import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
+import cn.iocoder.common.framework.exception.ServiceException;
+import cn.iocoder.common.framework.vo.CommonResult;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.web.bind.MissingServletRequestParameterException;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.ConstraintViolationException;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ // 逻辑异常
+ @ResponseBody
+ @ExceptionHandler(value = ServiceException.class)
+ public CommonResult serviceExceptionHandler(HttpServletRequest req, ServiceException ex) {
+ logger.debug("[serviceExceptionHandler]", ex);
+ return CommonResult.error(ex.getCode(), ex.getMessage());
+ }
+
+ // Spring MVC 参数不正确
+ @ResponseBody
+ @ExceptionHandler(value = MissingServletRequestParameterException.class)
+ public CommonResult missingServletRequestParameterExceptionHandler(HttpServletRequest req, MissingServletRequestParameterException ex) {
+ logger.warn("[missingServletRequestParameterExceptionHandler]", ex);
+ return CommonResult.error(SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getCode(), SysErrorCodeEnum.MISSING_REQUEST_PARAM_ERROR.getMessage() + ":" + ex.getMessage());
+ }
+
+ @ResponseBody
+ @ExceptionHandler(value = ConstraintViolationException.class)
+ public CommonResult constraintViolationExceptionHandler(HttpServletRequest req, ConstraintViolationException ex) {
+ logger.info("[constraintViolationExceptionHandler]", ex);
+ // TODO 芋艿,后续要想一个更好的方式。
+ // 拼接详细报错
+ StringBuilder detailMessage = new StringBuilder("\n\n详细错误如下:");
+ ex.getConstraintViolations().forEach(constraintViolation -> detailMessage.append("\n").append(constraintViolation.getMessage()));
+ return CommonResult.error(SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getCode(), SysErrorCodeEnum.VALIDATION_REQUEST_PARAM_ERROR.getMessage()
+ + detailMessage.toString());
+ }
+
+ @ResponseBody
+ @ExceptionHandler(value = Exception.class)
+ public CommonResult resultExceptionHandler(HttpServletRequest req, Exception e) {
+ logger.error("[resultExceptionHandler]", e);
+ // 返回
+ try {
+ addExceptionLog();
+ } catch (Throwable th) {
+ // TODO
+ }
+ return CommonResult.error(SysErrorCodeEnum.SYS_ERROR.getCode(), SysErrorCodeEnum.SYS_ERROR.getMessage());
+ }
+
+ // TODO 芋艿,应该还有其它的异常,需要进行翻译
+
+ @Async
+ public void addExceptionLog() {
+
+ }
+
+}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalResponseBodyHandler.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalResponseBodyHandler.java
new file mode 100644
index 000000000..8c5fd14c4
--- /dev/null
+++ b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalResponseBodyHandler.java
@@ -0,0 +1,31 @@
+package cn.iocoder.mall.spring.boot.web.handler;
+
+import cn.iocoder.common.framework.util.MallUtil;
+import cn.iocoder.common.framework.vo.CommonResult;
+import org.springframework.core.MethodParameter;
+import org.springframework.http.MediaType;
+import org.springframework.http.server.ServerHttpRequest;
+import org.springframework.http.server.ServerHttpResponse;
+import org.springframework.http.server.ServletServerHttpRequest;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
+
+@ControllerAdvice
+public class GlobalResponseBodyHandler implements ResponseBodyAdvice {
+
+ @Override
+ public boolean supports(MethodParameter returnType, Class converterType) {
+ if (returnType.getMethod() == null) {
+ return false;
+ }
+ return returnType.getMethod().getReturnType().isAssignableFrom(CommonResult.class);
+ }
+
+ @Override
+ public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType, Class selectedConverterType,
+ ServerHttpRequest request, ServerHttpResponse response) {
+ MallUtil.setCommonResult(((ServletServerHttpRequest) request).getServletRequest(), (CommonResult) body);
+ return body;
+ }
+
+}
diff --git a/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/interceptor/AccessLogInterceptor.java b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/interceptor/AccessLogInterceptor.java
new file mode 100644
index 000000000..3113847c2
--- /dev/null
+++ b/common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/interceptor/AccessLogInterceptor.java
@@ -0,0 +1,97 @@
+package cn.iocoder.mall.spring.boot.web.interceptor;
+
+import cn.iocoder.common.framework.util.HttpUtil;
+import cn.iocoder.common.framework.util.MallUtil;
+import cn.iocoder.common.framework.vo.CommonResult;
+import cn.iocoder.mall.admin.api.SystemLogService;
+import cn.iocoder.mall.admin.api.dto.AccessLogAddDTO;
+import com.alibaba.fastjson.JSON;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.apache.dubbo.config.annotation.Reference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+
+/**
+ * 访问日志拦截器
+ */
+@Component
+public class AccessLogInterceptor extends HandlerInterceptorAdapter {
+
+ private Logger logger = LoggerFactory.getLogger(getClass());
+
+ /**
+ * 开始时间
+ */
+ private static final ThreadLocal START_TIME = new ThreadLocal<>();
+
+ @Reference(validation = "true", version = "${dubbo.consumer.AdminAccessLogService.version:1.0.0}")
+ private SystemLogService adminAccessLogService;
+
+ @Value("${spring.application.name}")
+ private String applicationName;
+
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
+ // 记录当前时间
+ START_TIME.set(new Date());
+ return true;
+ }
+
+ @Override
+ public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
+ AccessLogAddDTO accessLog = new AccessLogAddDTO();
+ try {
+ // 设置用户编号
+ accessLog.setUserId(MallUtil.getUserId(request));
+ if (accessLog.getUserId() == null) {
+ accessLog.setUserId(AccessLogAddDTO.USER_ID_NULL);
+ }
+ accessLog.setUserType(MallUtil.getUserType(request));
+ // 设置访问结果
+ CommonResult result = MallUtil.getCommonResult(request);
+ Assert.isTrue(result != null, "result 必须非空");
+ accessLog.setErrorCode(result.getCode())
+ .setErrorMessage(result.getMessage());
+ // 设置其它字段
+ accessLog.setTraceId(MallUtil.getTraceId())
+ .setApplicationName(applicationName)
+ .setUri(request.getRequestURI()) // TODO 提升:如果想要优化,可以使用 Swagger 的 @ApiOperation 注解。
+ .setQueryString(HttpUtil.buildQueryString(request))
+ .setMethod(request.getMethod())
+ .setUserAgent(HttpUtil.getUserAgent(request))
+ .setIp(HttpUtil.getIp(request))
+ .setStartTime(START_TIME.get())
+ .setResponseTime((int) (System.currentTimeMillis() - accessLog.getStartTime().getTime())); // 默认响应时间设为 0
+ // 执行插入
+ addAccessLog(accessLog);
+ // TODO 提升:暂时不考虑 ELK 的方案。而是基于 MySQL 存储。如果访问日志比较多,需要定期归档。
+ } catch (Throwable th) {
+ logger.error("[afterCompletion][插入访问日志({}) 发生异常({})", JSON.toJSONString(accessLog), ExceptionUtils.getRootCauseMessage(th));
+ } finally {
+ clear();
+ }
+ }
+
+ @Async // 异步入库
+ public void addAccessLog(AccessLogAddDTO accessLog) {
+ try {
+ adminAccessLogService.addAccessLog(accessLog);
+ } catch (Throwable th) {
+ logger.error("[addAccessLog][插入访问日志({}) 发生异常({})", JSON.toJSONString(accessLog), ExceptionUtils.getRootCauseMessage(th));
+ }
+ }
+
+ private static void clear() {
+ START_TIME.remove();
+ }
+
+}
diff --git a/common/mall-spring-boot/src/main/resources/META-INF/spring.factories b/common/mall-spring-boot/src/main/resources/META-INF/spring.factories
index 282e9e45a..771427063 100644
--- a/common/mall-spring-boot/src/main/resources/META-INF/spring.factories
+++ b/common/mall-spring-boot/src/main/resources/META-INF/spring.factories
@@ -1,3 +1,4 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
- cn.iocoder.mall.spring.boot.web.AdminMVCConfiguration, \
- cn.iocoder.mall.spring.boot.web.UserMVCConfiguration
+ cn.iocoder.mall.spring.boot.web.AdminMVCAutoConfiguration, \
+ cn.iocoder.mall.spring.boot.web.UserMVCAutoConfiguration, \
+ cn.iocoder.mall.spring.boot.swagger.SwaggerAutoConfiguration
diff --git a/order/order-application/src/main/java/cn/iocoder/mall/order/application/config/MVCConfiguration.java b/order/order-application/src/main/java/cn/iocoder/mall/order/application/config/MVCConfiguration.java
index a6227a2e4..42f0c2560 100644
--- a/order/order-application/src/main/java/cn/iocoder/mall/order/application/config/MVCConfiguration.java
+++ b/order/order-application/src/main/java/cn/iocoder/mall/order/application/config/MVCConfiguration.java
@@ -1,6 +1,6 @@
package cn.iocoder.mall.order.application.config;
-import cn.iocoder.common.framework.config.GlobalExceptionHandler;
+import cn.iocoder.common.framework.exception.GlobalExceptionHandler;
import cn.iocoder.common.framework.servlet.CorsFilter;
import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
import cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor;
@@ -49,12 +49,4 @@ public class MVCConfiguration implements WebMvcConfigurer {
return registrationBean;
}
- // TODO 芋艿,允许跨域
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**")
- .allowedHeaders("*")
- .allowedMethods("*")
- .allowedOrigins("*");
- }
}
diff --git a/pay/pay-application/pom.xml b/pay/pay-application/pom.xml
index eb24ff5fe..49fdb7771 100644
--- a/pay/pay-application/pom.xml
+++ b/pay/pay-application/pom.xml
@@ -17,6 +17,11 @@
common-framework
1.0-SNAPSHOT
+
+ cn.iocoder.mall
+ mall-spring-boot
+ 1.0-SNAPSHOT
+
cn.iocoder.mall
pay-service-impl
@@ -63,8 +68,9 @@
springfox-swagger2
- io.springfox
- springfox-swagger-ui
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ true
diff --git a/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/PayApplication.java b/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/PayApplication.java
index 18b5ed807..fe85def26 100644
--- a/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/PayApplication.java
+++ b/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/PayApplication.java
@@ -2,12 +2,14 @@ package cn.iocoder.mall.pay.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.pay"})
+@EnableAsync(proxyTargetClass = true)
public class PayApplication {
public static void main(String[] args) {
SpringApplication.run(PayApplication.class, args);
}
-}
\ No newline at end of file
+}
diff --git a/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/MVCConfiguration.java b/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/MVCConfiguration.java
deleted file mode 100644
index 489a9c7b8..000000000
--- a/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/MVCConfiguration.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package cn.iocoder.mall.pay.application.config;
-
-import cn.iocoder.common.framework.config.GlobalExceptionHandler;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.web.servlet.config.annotation.CorsRegistry;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@EnableWebMvc
-@Configuration
-@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
-// AdminSecurityInterceptor.class
-})
-public class MVCConfiguration implements WebMvcConfigurer {
-
-// @Autowired
-// private UserSecurityInterceptor securityInterceptor;
-
-// @Autowired
-// private AdminSecurityInterceptor adminSecurityInterceptor;
-////
-// @Override
-// public void addInterceptors(InterceptorRegistry registry) {
-//// registry.addInterceptor(securityInterceptor).addPathPatterns("/user/**", "/admin/**"); // 只拦截我们定义的接口
-// registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**")
-// .excludePathPatterns("/admins/passport/login"); // 排除登陆接口
-// }
-
- // TODO 芋艿,允许跨域
- @Override
- public void addCorsMappings(CorsRegistry registry) {
- registry.addMapping("/**")
- .allowedHeaders("*")
- .allowedMethods("*")
- .allowedOrigins("*");
- }
-
-}
diff --git a/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/SwaggerConfiguration.java b/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/SwaggerConfiguration.java
deleted file mode 100644
index c638d8efe..000000000
--- a/pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/SwaggerConfiguration.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.mall.pay.application.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-@Configuration
-@EnableSwagger2 // TODO 生产环境时,禁用掉。
-public class SwaggerConfiguration {
-
- @Bean
- public Docket createRestApi() {
- return new Docket(DocumentationType.SWAGGER_2)
- .apiInfo(apiInfo())
- .select()
- .apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.pay.application.controller"))
- .paths(PathSelectors.any())
- .build();
- }
-
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("支付子系统")
- .description("支付子系统")
- .termsOfServiceUrl("http://www.iocoder.cn")
- .version("1.0.0")
- .build();
- }
-
-}
\ No newline at end of file
diff --git a/pay/pay-application/src/main/resources/application.yaml b/pay/pay-application/src/main/resources/application.yaml
index f939e8563..8b3774d8e 100644
--- a/pay/pay-application/src/main/resources/application.yaml
+++ b/pay/pay-application/src/main/resources/application.yaml
@@ -6,4 +6,10 @@ spring:
server:
port: 18084
servlet:
- context-path: /pay-api/
\ No newline at end of file
+ context-path: /pay-api/
+
+swagger:
+ title: 支付子系统
+ description: 支付子系统
+ version: 1.0.0
+ base-package: cn.iocoder.mall.pay.application.controller
diff --git a/pom.xml b/pom.xml
index 3f0032429..815a20695 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,7 @@
2.9.2
+ 1.9.3
2.0.0
2.0.1
27.0.1-jre
@@ -129,6 +130,11 @@
springfox-swagger-ui
${springfox-swagger.version}
+
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ ${swagger-bootstrap-ui.version}
+
org.mybatis.spring.boot
@@ -184,6 +190,14 @@
${qiniu.version}
+
+ javax.servlet
+ servlet-api
+
+ 2.5
+ true
+
+
diff --git a/product/product-application/pom.xml b/product/product-application/pom.xml
index 341895fe3..eca936e10 100644
--- a/product/product-application/pom.xml
+++ b/product/product-application/pom.xml
@@ -17,6 +17,11 @@
common-framework
1.0-SNAPSHOT
+
+ cn.iocoder.mall
+ mall-spring-boot
+ 1.0-SNAPSHOT
+
cn.iocoder.mall
product-service-api
@@ -60,11 +65,10 @@
springfox-swagger2
- io.springfox
- springfox-swagger-ui
+ com.github.xiaoymin
+ swagger-bootstrap-ui
-
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/ProductApplication.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/ProductApplication.java
index 19a1513e7..c3a9758c3 100644
--- a/product/product-application/src/main/java/cn/iocoder/mall/product/application/ProductApplication.java
+++ b/product/product-application/src/main/java/cn/iocoder/mall/product/application/ProductApplication.java
@@ -2,12 +2,14 @@ package cn.iocoder.mall.product.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.product"})
+@EnableAsync(proxyTargetClass = true)
public class ProductApplication {
public static void main(String[] args) {
SpringApplication.run(ProductApplication.class, args);
}
-}
\ No newline at end of file
+}
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java
deleted file mode 100644
index 0ef5dc96d..000000000
--- a/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package cn.iocoder.mall.product.application.config;
-
-import cn.iocoder.common.framework.config.GlobalExceptionHandler;
-import cn.iocoder.common.framework.servlet.CorsFilter;
-import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor;
-import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@EnableWebMvc
-@Configuration
-@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
- AdminSecurityInterceptor.class, AdminAccessLogInterceptor.class})
-public class MVCConfiguration implements WebMvcConfigurer {
-
- @Autowired
- private AdminSecurityInterceptor adminSecurityInterceptor;
- @Autowired
- private AdminAccessLogInterceptor adminAccessLogInterceptor;
-
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
-// registry.addInterceptor(securityInterceptor);
- registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
- registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
- }
-
- @Bean
- public FilterRegistrationBean corsFilter() {
- FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new CorsFilter());
- registrationBean.addUrlPatterns("/*");
- return registrationBean;
- }
-
-}
diff --git a/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/SwaggerConfiguration.java b/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/SwaggerConfiguration.java
deleted file mode 100644
index e5acbd02e..000000000
--- a/product/product-application/src/main/java/cn/iocoder/mall/product/application/config/SwaggerConfiguration.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.mall.product.application.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-@Configuration
-@EnableSwagger2
-public class SwaggerConfiguration {
-
- @Bean
- public Docket createRestApi() {
- return new Docket(DocumentationType.SWAGGER_2)
- .apiInfo(apiInfo())
- .select()
- .apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.product.application.controller"))
- .paths(PathSelectors.any())
- .build();
- }
-
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("商品子系统")
- .description("商品子系统")
- .termsOfServiceUrl("http://www.iocoder.cn")
- .version("1.0.0")
- .build();
- }
-
-}
\ No newline at end of file
diff --git a/product/product-application/src/main/resources/application.yaml b/product/product-application/src/main/resources/application.yaml
index d86f295cd..4718d8c3e 100644
--- a/product/product-application/src/main/resources/application.yaml
+++ b/product/product-application/src/main/resources/application.yaml
@@ -6,4 +6,10 @@ spring:
server:
port: 18081
servlet:
- context-path: /product-api/
\ No newline at end of file
+ context-path: /product-api/
+
+swagger:
+ title: 商品子系统
+ description: 商品子系统
+ version: 1.0.0
+ base-package: cn.iocoder.mall.product.application.controller
diff --git a/product/product-service-impl/src/main/resources/config/application.yaml b/product/product-service-impl/src/main/resources/config/application.yaml
index 27e328f55..d9dc2665d 100644
--- a/product/product-service-impl/src/main/resources/config/application.yaml
+++ b/product/product-service-impl/src/main/resources/config/application.yaml
@@ -31,6 +31,8 @@ dubbo:
version: 1.0.0
ProductSpuService:
version: 1.0.0
+ OAuth2Service:
+ version: 1.0.0
# rocketmq
rocketmq:
diff --git a/promotion/promotion-application/pom.xml b/promotion/promotion-application/pom.xml
index 0e7455a63..debb678aa 100644
--- a/promotion/promotion-application/pom.xml
+++ b/promotion/promotion-application/pom.xml
@@ -18,6 +18,11 @@
1.0-SNAPSHOT
+
+ cn.iocoder.mall
+ product-service-api
+ 1.0-SNAPSHOT
+
cn.iocoder.mall
promotion-service-api
@@ -59,14 +64,8 @@
springfox-swagger2
- io.springfox
- springfox-swagger-ui
-
-
- cn.iocoder.mall
- product-service-api
- 1.0-SNAPSHOT
- compile
+ com.github.xiaoymin
+ swagger-bootstrap-ui
diff --git a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java b/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java
deleted file mode 100644
index 9295e9998..000000000
--- a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java
+++ /dev/null
@@ -1,56 +0,0 @@
-package cn.iocoder.mall.promotion.application.config;
-
-import cn.iocoder.common.framework.config.GlobalExceptionHandler;
-import cn.iocoder.common.framework.servlet.CorsFilter;
-import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor;
-import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
-import cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor;
-import cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@EnableWebMvc
-@Configuration
-@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
- AdminSecurityInterceptor.class, UserAccessLogInterceptor.class,
- UserSecurityInterceptor.class, AdminAccessLogInterceptor.class,
-})
-public class MVCConfiguration implements WebMvcConfigurer {
-
-// @Autowired
-// private UserSecurityInterceptor securityInterceptor;
-
- @Autowired
- private UserSecurityInterceptor userSecurityInterceptor;
- @Autowired
- private UserAccessLogInterceptor userAccessLogInterceptor;
- @Autowired
- private AdminSecurityInterceptor adminSecurityInterceptor;
- @Autowired
- private AdminAccessLogInterceptor adminAccessLogInterceptor;
-//
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
- // 用户
- registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**");
- registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口
- // 管理员
-// registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
- registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
- }
-
- @Bean
- public FilterRegistrationBean corsFilter() {
- FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new CorsFilter());
- registrationBean.addUrlPatterns("/*");
- return registrationBean;
- }
-
-}
diff --git a/promotion/promotion-application/src/main/resources/application.yaml b/promotion/promotion-application/src/main/resources/application.yaml
index 3c095eebb..e6d66102e 100644
--- a/promotion/promotion-application/src/main/resources/application.yaml
+++ b/promotion/promotion-application/src/main/resources/application.yaml
@@ -6,4 +6,10 @@ spring:
server:
port: 18085
servlet:
- context-path: /promotion-api/
\ No newline at end of file
+ context-path: /promotion-api/
+
+swagger:
+ title: 营销子系统
+ description: 营销子系统
+ version: 1.0.0
+ base-package: cn.iocoder.mall.promotion.application.controller
diff --git a/search/search-application/pom.xml b/search/search-application/pom.xml
index 90555f81d..540a03aa4 100644
--- a/search/search-application/pom.xml
+++ b/search/search-application/pom.xml
@@ -17,6 +17,11 @@
common-framework
1.0-SNAPSHOT
+
+ cn.iocoder.mall
+ mall-spring-boot
+ 1.0-SNAPSHOT
+
cn.iocoder.mall
user-sdk
@@ -48,8 +53,8 @@
springfox-swagger2
- io.springfox
- springfox-swagger-ui
+ com.github.xiaoymin
+ swagger-bootstrap-ui
diff --git a/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java b/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java
index a9df02936..228823e29 100644
--- a/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java
+++ b/search/search-application/src/main/java/cn/iocoder/mall/search/application/SearchApplication.java
@@ -2,8 +2,10 @@ package cn.iocoder.mall.search.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.search"})
+@EnableAsync(proxyTargetClass = true)
public class SearchApplication {
public static void main(String[] args) {
diff --git a/search/search-application/src/main/java/cn/iocoder/mall/search/application/config/MVCConfiguration.java b/search/search-application/src/main/java/cn/iocoder/mall/search/application/config/MVCConfiguration.java
deleted file mode 100644
index 3de69b226..000000000
--- a/search/search-application/src/main/java/cn/iocoder/mall/search/application/config/MVCConfiguration.java
+++ /dev/null
@@ -1,51 +0,0 @@
-package cn.iocoder.mall.search.application.config;
-
-import cn.iocoder.common.framework.config.GlobalExceptionHandler;
-import cn.iocoder.common.framework.servlet.CorsFilter;
-import org.springframework.boot.web.servlet.FilterRegistrationBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.context.annotation.Import;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
-import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
-
-@EnableWebMvc
-@Configuration
-@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
-// AdminSecurityInterceptor.class, UserAccessLogInterceptor.class,
-// UserSecurityInterceptor.class, AdminAccessLogInterceptor.class,
-})
-public class MVCConfiguration implements WebMvcConfigurer {
-
-// @Autowired
-// private UserSecurityInterceptor securityInterceptor;
-
-// @Autowired
-// private UserSecurityInterceptor userSecurityInterceptor;
-// @Autowired
-// private UserAccessLogInterceptor userAccessLogInterceptor;
-// @Autowired
-// private AdminSecurityInterceptor adminSecurityInterceptor;
-// @Autowired
-// private AdminAccessLogInterceptor adminAccessLogInterceptor;
-//
- @Override
- public void addInterceptors(InterceptorRegistry registry) {
-// // 用户
-// registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**");
-// registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口
-// // 管理员
-// registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
-// registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
- }
-
- @Bean
- public FilterRegistrationBean corsFilter() {
- FilterRegistrationBean registrationBean = new FilterRegistrationBean<>();
- registrationBean.setFilter(new CorsFilter());
- registrationBean.addUrlPatterns("/*");
- return registrationBean;
- }
-
-}
diff --git a/search/search-application/src/main/java/cn/iocoder/mall/search/application/config/SwaggerConfiguration.java b/search/search-application/src/main/java/cn/iocoder/mall/search/application/config/SwaggerConfiguration.java
deleted file mode 100644
index 260c1f4c2..000000000
--- a/search/search-application/src/main/java/cn/iocoder/mall/search/application/config/SwaggerConfiguration.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.mall.search.application.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-@Configuration
-@EnableSwagger2 // TODO 生产环境时,禁用掉。
-public class SwaggerConfiguration {
-
- @Bean
- public Docket createRestApi() {
- return new Docket(DocumentationType.SWAGGER_2)
- .apiInfo(apiInfo())
- .select()
- .apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.search.application.controller"))
- .paths(PathSelectors.any())
- .build();
- }
-
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("搜索子系统")
- .description("搜索子系统")
- .termsOfServiceUrl("http://www.iocoder.cn")
- .version("1.0.0")
- .build();
- }
-
-}
diff --git a/search/search-application/src/main/resources/application.yaml b/search/search-application/src/main/resources/application.yaml
index 3ace875fe..7d6ac2715 100644
--- a/search/search-application/src/main/resources/application.yaml
+++ b/search/search-application/src/main/resources/application.yaml
@@ -7,3 +7,9 @@ server:
port: 18086
servlet:
context-path: /search-api/
+
+swagger:
+ title: 搜索子系统
+ description: 搜索子系统
+ version: 1.0.0
+ base-package: cn.iocoder.mall.search.application.controller
diff --git a/system/system-application/pom.xml b/system/system-application/pom.xml
index af0ef92ba..6301ab829 100644
--- a/system/system-application/pom.xml
+++ b/system/system-application/pom.xml
@@ -50,8 +50,9 @@
springfox-swagger2
- io.springfox
- springfox-swagger-ui
+ com.github.xiaoymin
+ swagger-bootstrap-ui
+ true
diff --git a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/AdminApplication.java b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/AdminApplication.java
index dbb7835ba..e83b27520 100644
--- a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/AdminApplication.java
+++ b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/AdminApplication.java
@@ -3,9 +3,10 @@ package cn.iocoder.mall.admin.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.admin"})
-//@EnableAdminServer
+@EnableAsync(proxyTargetClass = true)
public class AdminApplication {
public static void main(String[] args) {
@@ -19,4 +20,4 @@ public class AdminApplication {
// System.out.println(); // TODO 后面去掉,这里是临时的
}
-}
\ No newline at end of file
+}
diff --git a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/config/SwaggerConfiguration.java b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/config/SwaggerConfiguration.java
deleted file mode 100644
index adee77e1c..000000000
--- a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/config/SwaggerConfiguration.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.mall.admin.application.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-@Configuration
-@EnableSwagger2 // TODO 生产环境时,禁用掉。
-public class SwaggerConfiguration {
-
- @Bean
- public Docket createRestApi() {
- return new Docket(DocumentationType.SWAGGER_2)
- .apiInfo(apiInfo())
- .select()
- .apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.admin.application.controller"))
- .paths(PathSelectors.any())
- .build();
- }
-
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("管理员子系统")
- .description("管理员子系统")
- .termsOfServiceUrl("http://www.iocoder.cn")
- .version("1.0.0")
- .build();
- }
-
-}
\ No newline at end of file
diff --git a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java
index 98b0c1a09..0b3b46ff4 100644
--- a/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java
+++ b/system/system-application/src/main/java/cn/iocoder/mall/admin/application/controller/admins/AdminController.java
@@ -18,7 +18,7 @@ import cn.iocoder.mall.admin.application.vo.AdminPageVO;
import cn.iocoder.mall.admin.application.vo.AdminRoleVO;
import cn.iocoder.mall.admin.application.vo.AdminVO;
import cn.iocoder.mall.admin.sdk.context.AdminSecurityContextHolder;
-import cn.iocoder.mall.spring.boot.constant.RootRequestPath;
+import cn.iocoder.common.framework.constant.MallConstants;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
@@ -30,7 +30,7 @@ import java.util.*;
import java.util.stream.Collectors;
@RestController
-@RequestMapping(RootRequestPath.ADMIN + "/admin")
+@RequestMapping(MallConstants.ROOT_PATH_ADMIN + "/admin")
@Api("管理员模块")
public class AdminController {
diff --git a/system/system-application/src/main/resources/application-test.yaml b/system/system-application/src/main/resources/application-test.yaml
index a5868258e..c7ab7fb7c 100644
--- a/system/system-application/src/main/resources/application-test.yaml
+++ b/system/system-application/src/main/resources/application-test.yaml
@@ -13,3 +13,6 @@ management:
include: "*"
server:
port: 19083 # 配置独立端口。而该端口,不使用 nginx 对外暴露,从而不配置安全认证。也就是说,内网环境可访问,外网环境不可访问。当然,这么做的前提是,认为内网安全。
+
+swagger:
+ enable: true # 暂时不去掉
diff --git a/system/system-application/src/main/resources/application.yaml b/system/system-application/src/main/resources/application.yaml
index 64e0fd5e4..839f5d058 100644
--- a/system/system-application/src/main/resources/application.yaml
+++ b/system/system-application/src/main/resources/application.yaml
@@ -17,3 +17,9 @@ qiniu:
access-key: YldfyUC7OewoWM63TPYTairqnq8GMJvNek9EGoID
secret-key: zZ7Q8wwZRyaklVvkyLmVydA4WygOBqtc_gTYzalS
bucket: onemall
+
+swagger:
+ title: 管理员子系统
+ description: 管理员子系统
+ version: 1.0.0
+ base-package: cn.iocoder.mall.admin.application.controller
diff --git a/system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminAccessLogInterceptor.java b/system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminAccessLogInterceptor.java
deleted file mode 100644
index cb7d3d58a..000000000
--- a/system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminAccessLogInterceptor.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package cn.iocoder.mall.admin.sdk.interceptor;
-
-import cn.iocoder.common.framework.util.HttpUtil;
-import cn.iocoder.mall.admin.api.AdminAccessLogService;
-import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
-import com.alibaba.fastjson.JSON;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.dubbo.config.annotation.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.Date;
-
-/**
- * 访问日志拦截器
- */
-@Component
-public class AdminAccessLogInterceptor extends HandlerInterceptorAdapter {
-
- private Logger logger = LoggerFactory.getLogger(getClass());
-
- /**
- * 开始时间
- */
- private static final ThreadLocal START_TIME = new ThreadLocal<>();
- /**
- * 管理员编号
- */
- private static final ThreadLocal ADMIN_ID = new ThreadLocal<>();
-
- @Reference(validation = "true", version = "${dubbo.consumer.AdminAccessLogService.version:1.0.0}")
- private AdminAccessLogService adminAccessLogService;
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
- // 记录当前时间
- START_TIME.set(new Date());
- return true;
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
- if (adminAccessLogService == null) {
- throw new IllegalStateException("AdminAccessLogService 服务未引入成功");
- }
- AdminAccessLogAddDTO accessLog = new AdminAccessLogAddDTO();
- try {
- accessLog.setAdminId(ADMIN_ID.get());
- if (accessLog.getAdminId() == null) {
- accessLog.setAdminId(AdminAccessLogAddDTO.ADMIN_ID_NULL);
- }
- accessLog.setUri(request.getRequestURI()); // TODO 提升:如果想要优化,可以使用 Swagger 的 @ApiOperation 注解。
- accessLog.setQueryString(HttpUtil.buildQueryString(request));
- accessLog.setMethod(request.getMethod());
- accessLog.setUserAgent(HttpUtil.getUserAgent(request));
- accessLog.setIp(HttpUtil.getIp(request));
- accessLog.setStartTime(START_TIME.get());
- accessLog.setResponseTime((int) (System.currentTimeMillis() - accessLog.getStartTime().getTime()));// 默认响应时间设为0
- adminAccessLogService.addAdminAccessLog(accessLog);
- // TODO 提升:暂时不考虑 ELK 的方案。而是基于 MySQL 存储。如果访问日志比较多,需要定期归档。
- } catch (Throwable th) {
- logger.error("[afterCompletion][插入管理员访问日志({}) 发生异常({})", JSON.toJSONString(accessLog), ExceptionUtils.getRootCauseMessage(th));
- } finally {
- clear();
- }
- }
-
- public static void setAdminId(Integer adminId) {
- ADMIN_ID.set(adminId);
- }
-
- public static void clear() {
- START_TIME.remove();
- ADMIN_ID.remove();
- }
-
-}
diff --git a/system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java b/system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java
index d28c2d220..3578f878b 100644
--- a/system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java
+++ b/system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminSecurityInterceptor.java
@@ -1,7 +1,9 @@
package cn.iocoder.mall.admin.sdk.interceptor;
+import cn.iocoder.common.framework.constant.MallConstants;
import cn.iocoder.common.framework.exception.ServiceException;
import cn.iocoder.common.framework.util.HttpUtil;
+import cn.iocoder.common.framework.util.MallUtil;
import cn.iocoder.common.framework.vo.CommonResult;
import cn.iocoder.mall.admin.api.OAuth2Service;
import cn.iocoder.mall.admin.api.bo.OAuth2AuthenticationBO;
@@ -39,8 +41,10 @@ public class AdminSecurityInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ // 设置当前访问的用户类型。注意,即使未登陆,我们也认为是管理员
+ MallUtil.setUserType(request, MallConstants.USER_TYPE_ADMIN);
// 校验访问令牌是否正确。若正确,返回授权信息
- String accessToken = HttpUtil.obtainAccess(request);
+ String accessToken = HttpUtil.obtainAuthorization(request);
OAuth2AuthenticationBO authentication = null;
if (accessToken != null) {
CommonResult result = oauth2Service.checkToken(accessToken);
@@ -60,7 +64,7 @@ public class AdminSecurityInterceptor extends HandlerInterceptorAdapter {
// AdminSecurityInterceptor 执行后,会移除 AdminSecurityContext 信息,这就导致 AdminAccessLogInterceptor 无法获得管理员编号
// 因此,这里需要进行记录
if (authentication.getAdminId() != null) {
- AdminAccessLogInterceptor.setAdminId(authentication.getAdminId());
+ MallUtil.setUserId(request, authentication.getAdminId());
}
} else {
String url = request.getRequestURI();
diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminAccessLogService.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminAccessLogService.java
deleted file mode 100644
index 0b22c1819..000000000
--- a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminAccessLogService.java
+++ /dev/null
@@ -1,13 +0,0 @@
-package cn.iocoder.mall.admin.api;
-
-import cn.iocoder.common.framework.vo.CommonResult;
-import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
-
-/**
- * 管理员访问日志 Service 接口
- */
-public interface AdminAccessLogService {
-
- CommonResult addAdminAccessLog(AdminAccessLogAddDTO adminAccessLogAddDTO);
-
-}
diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SystemLogService.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SystemLogService.java
new file mode 100644
index 000000000..90109f0cb
--- /dev/null
+++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SystemLogService.java
@@ -0,0 +1,14 @@
+package cn.iocoder.mall.admin.api;
+
+import cn.iocoder.mall.admin.api.dto.AccessLogAddDTO;
+
+/**
+ * 系统日志 Service 接口
+ *
+ * 例如说,访问日志、错误日志、操作日志等等
+ */
+public interface SystemLogService {
+
+ void addAccessLog(AccessLogAddDTO accessLogAddDTO);
+
+}
diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AccessLogAddDTO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AccessLogAddDTO.java
new file mode 100644
index 000000000..00d12e0b6
--- /dev/null
+++ b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AccessLogAddDTO.java
@@ -0,0 +1,98 @@
+package cn.iocoder.mall.admin.api.dto;
+
+
+import cn.iocoder.common.framework.vo.CommonResult;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 访问日志添加 DTO
+ */
+@Data
+@Accessors(chain = true)
+public class AccessLogAddDTO implements Serializable {
+
+ /**
+ * 用户编号 - 空
+ */
+ public static final Integer USER_ID_NULL = 0;
+ /**
+ * 链路追踪编号
+ *
+ * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
+ */
+ @NotNull(message = "链路追踪编号不能为空")
+ private String traceId;
+ /**
+ * 用户编号.
+ *
+ * 当管理员为空时,该值为 {@link #USER_ID_NULL}
+ */
+ @NotNull(message = "用户编号不能为空")
+ private Integer userId;
+ /**
+ * 用户类型
+ */
+ @NotNull(message = "用户类型不能为空")
+ private Integer userType;
+ /**
+ * 应用名
+ *
+ * 目前读取 spring.application.name
+ */
+ @NotNull(message = "应用名不能为空")
+ private String applicationName;
+ /**
+ * 访问地址
+ */
+ @NotNull(message = "访问地址不能为空")
+ private String uri;
+ /**
+ * 参数
+ */
+ @NotNull(message = "请求参数不能为空")
+ private String queryString;
+ /**
+ * http 方法
+ */
+ @NotNull(message = "http 请求方法不能为空")
+ private String method;
+ /**
+ * User Agent
+ */
+ @NotNull(message = "User-Agent 不能为空")
+ private String userAgent;
+ /**
+ * ip
+ */
+ @NotNull(message = "ip 不能为空")
+ private String ip;
+ /**
+ * 请求时间
+ */
+ @NotNull(message = "请求时间不能为空")
+ private Date startTime;
+ /**
+ * 响应时长 -- 毫秒级
+ */
+ @NotNull(message = "响应时长不能为空")
+ private Integer responseTime;
+ /**
+ * 错误码
+ *
+ * 目前的结果,是使用 {@link CommonResult#getCode()} 属性
+ */
+ @NotNull(message = "错误码不能为空")
+ private Integer errorCode;
+ /**
+ * 错误提示
+ *
+ * 目前的结果,是使用 {@link CommonResult#getMessage()} 属性
+ */
+ private String errorMessage;
+
+}
diff --git a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AdminAccessLogAddDTO.java b/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AdminAccessLogAddDTO.java
deleted file mode 100644
index 684fe0736..000000000
--- a/system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AdminAccessLogAddDTO.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package cn.iocoder.mall.admin.api.dto;
-
-
-import lombok.Data;
-import lombok.experimental.Accessors;
-
-import javax.validation.constraints.NotNull;
-import java.io.Serializable;
-import java.util.Date;
-
-/**
- * 管理员访问日志添加 DTO
- */
-@Data
-@Accessors(chain = true)
-public class AdminAccessLogAddDTO implements Serializable {
-
- /**
- * 管理员编号 - 空
- */
- public static final Integer ADMIN_ID_NULL = 0;
-
- /**
- * 管理员编号.
- *
- * 当管理员为空时,该值为0
- */
- @NotNull(message = "管理员编号不能为空")
- private Integer adminId;
- /**
- * 访问地址
- */
- @NotNull(message = "访问地址不能为空")
- private String uri;
- /**
- * 参数
- */
- @NotNull(message = "请求参数不能为空")
- private String queryString;
- /**
- * http 方法
- */
- @NotNull(message = "http 请求方法不能为空")
- private String method;
- /**
- * User Agent
- */
- @NotNull(message = "User-Agent 不能为空")
- private String userAgent;
- /**
- * ip
- */
- @NotNull(message = "ip 不能为空")
- private String ip;
- /**
- * 请求时间
- */
- @NotNull(message = "请求时间不能为空")
- private Date startTime;
- /**
- * 响应时长 -- 毫秒级
- */
- @NotNull(message = "响应时长不能为空")
- private Integer responseTime;
-
-}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AccessLogConvert.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AccessLogConvert.java
new file mode 100644
index 000000000..910876d7f
--- /dev/null
+++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AccessLogConvert.java
@@ -0,0 +1,17 @@
+package cn.iocoder.mall.admin.convert;
+
+import cn.iocoder.mall.admin.api.dto.AccessLogAddDTO;
+import cn.iocoder.mall.admin.dataobject.AccessLogDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mappings;
+import org.mapstruct.factory.Mappers;
+
+@Mapper
+public interface AccessLogConvert {
+
+ AccessLogConvert INSTANCE = Mappers.getMapper(AccessLogConvert.class);
+
+ @Mappings({})
+ AccessLogDO convert(AccessLogAddDTO accessLogAddDTO);
+
+}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AdminAccessLogConvert.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AdminAccessLogConvert.java
deleted file mode 100644
index a7816e6c7..000000000
--- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AdminAccessLogConvert.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package cn.iocoder.mall.admin.convert;
-
-import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
-import cn.iocoder.mall.admin.dataobject.AdminAccessLogDO;
-import org.mapstruct.Mapper;
-import org.mapstruct.Mappings;
-import org.mapstruct.factory.Mappers;
-
-@Mapper
-public interface AdminAccessLogConvert {
-
- AdminAccessLogConvert INSTANCE = Mappers.getMapper(AdminAccessLogConvert.class);
-
- @Mappings({})
- AdminAccessLogDO convert(AdminAccessLogAddDTO adminAccessLogAddDTO);
-
-}
\ No newline at end of file
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AccessLogMapper.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AccessLogMapper.java
new file mode 100644
index 000000000..947e79c9c
--- /dev/null
+++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AccessLogMapper.java
@@ -0,0 +1,11 @@
+package cn.iocoder.mall.admin.dao;
+
+import cn.iocoder.mall.admin.dataobject.AccessLogDO;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface AccessLogMapper {
+
+ void insert(AccessLogDO entity);
+
+}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminAccessLogMapper.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminAccessLogMapper.java
deleted file mode 100644
index 58cd8f525..000000000
--- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminAccessLogMapper.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cn.iocoder.mall.admin.dao;
-
-import cn.iocoder.mall.admin.dataobject.AdminAccessLogDO;
-import org.springframework.stereotype.Repository;
-
-@Repository
-public interface AdminAccessLogMapper {
-
- void insert(AdminAccessLogDO entity);
-
-}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AccessLogDO.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AccessLogDO.java
new file mode 100644
index 000000000..a16fbab0f
--- /dev/null
+++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AccessLogDO.java
@@ -0,0 +1,84 @@
+package cn.iocoder.mall.admin.dataobject;
+
+import cn.iocoder.common.framework.dataobject.DeletableDO;
+import cn.iocoder.common.framework.vo.CommonResult;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+import java.util.Date;
+
+/**
+ * 管理员访问日志 DO
+ */
+@Data
+@Accessors(chain = true)
+public class AccessLogDO extends DeletableDO {
+
+ /**
+ * 编号
+ */
+ private Integer id;
+ /**
+ * 链路追踪编号
+ *
+ * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
+ */
+ private String traceId;
+ /**
+ * 用户编号.
+ *
+ * 当管理员为空时,该值为 {@link cn.iocoder.mall.admin.api.dto.AccessLogAddDTO#USER_ID_NULL}
+ */
+ private Integer userId;
+ /**
+ * 用户类型
+ */
+ private Integer userType;
+ /**
+ * 应用名
+ *
+ * 目前读取 spring.application.name
+ */
+ private String applicationName;
+ /**
+ * 访问地址
+ */
+ private String uri;
+ /**
+ * 参数
+ */
+ private String queryString;
+ /**
+ * http 方法
+ */
+ private String method;
+ /**
+ * userAgent
+ */
+ private String userAgent;
+ /**
+ * ip
+ */
+ private String ip;
+ /**
+ * 请求时间
+ */
+ private Date startTime;
+ /**
+ * 响应时长 -- 毫秒级
+ */
+ private Integer responseTime;
+ /**
+ * 错误码
+ *
+ * 目前的结果,是使用 {@link CommonResult#getCode()} 属性
+ */
+ private Integer errorCode;
+ /**
+ * 错误提示
+ *
+ * 目前的结果,是使用 {@link CommonResult#getMessage()} 属性
+ */
+ private String errorMessage;
+
+}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminAccessLogDO.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminAccessLogDO.java
deleted file mode 100644
index 96ab67b7a..000000000
--- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminAccessLogDO.java
+++ /dev/null
@@ -1,55 +0,0 @@
-package cn.iocoder.mall.admin.dataobject;
-
-import cn.iocoder.common.framework.dataobject.DeletableDO;
-import lombok.Data;
-import lombok.experimental.Accessors;
-
-import java.util.Date;
-
-/**
- * 管理员访问日志 DO
- */
-@Data
-@Accessors(chain = true)
-public class AdminAccessLogDO extends DeletableDO {
-
- /**
- * 编号
- */
- private Integer id;
- /**
- * 管理员编号.
- *
- * 当管理员为空时,该值为0
- */
- private Integer adminId;
- /**
- * 访问地址
- */
- private String uri;
- /**
- * 参数
- */
- private String queryString;
- /**
- * http 方法
- */
- private String method;
- /**
- * userAgent
- */
- private String userAgent;
- /**
- * ip
- */
- private String ip;
- /**
- * 请求时间
- */
- private Date startTime;
- /**
- * 响应时长 -- 毫秒级
- */
- private Integer responseTime;
-
-}
diff --git a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminAccessLogServiceImpl.java b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SystemLogServiceImpl.java
similarity index 64%
rename from system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminAccessLogServiceImpl.java
rename to system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SystemLogServiceImpl.java
index 9d30d1fbb..a3e75c98e 100644
--- a/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/AdminAccessLogServiceImpl.java
+++ b/system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/SystemLogServiceImpl.java
@@ -1,12 +1,11 @@
package cn.iocoder.mall.admin.service;
import cn.iocoder.common.framework.util.StringUtil;
-import cn.iocoder.common.framework.vo.CommonResult;
-import cn.iocoder.mall.admin.api.AdminAccessLogService;
-import cn.iocoder.mall.admin.api.dto.AdminAccessLogAddDTO;
-import cn.iocoder.mall.admin.convert.AdminAccessLogConvert;
-import cn.iocoder.mall.admin.dao.AdminAccessLogMapper;
-import cn.iocoder.mall.admin.dataobject.AdminAccessLogDO;
+import cn.iocoder.mall.admin.api.SystemLogService;
+import cn.iocoder.mall.admin.api.dto.AccessLogAddDTO;
+import cn.iocoder.mall.admin.convert.AccessLogConvert;
+import cn.iocoder.mall.admin.dao.AccessLogMapper;
+import cn.iocoder.mall.admin.dataobject.AccessLogDO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -14,7 +13,7 @@ import java.util.Date;
@Service
@org.apache.dubbo.config.annotation.Service(validation = "true", version = "${dubbo.provider.AdminAccessLogService.version}")
-public class AdminAccessLogServiceImpl implements AdminAccessLogService {
+public class SystemLogServiceImpl implements SystemLogService {
/**
* 请求参数最大长度。
@@ -30,12 +29,12 @@ public class AdminAccessLogServiceImpl implements AdminAccessLogService {
private static final Integer USER_AGENT_MAX_LENGTH = 1024;
@Autowired
- private AdminAccessLogMapper adminAccessLogMapper;
+ private AccessLogMapper accessLogMapper;
@Override
- public CommonResult addAdminAccessLog(AdminAccessLogAddDTO adminAccessLogAddDTO) {
+ public void addAccessLog(AccessLogAddDTO adminAccessLogAddDTO) {
// 创建 AdminAccessLogDO
- AdminAccessLogDO accessLog = AdminAccessLogConvert.INSTANCE.convert(adminAccessLogAddDTO);
+ AccessLogDO accessLog = AccessLogConvert.INSTANCE.convert(adminAccessLogAddDTO);
accessLog.setCreateTime(new Date());
// 截取最大长度
if (accessLog.getUri().length() > URI_MAX_LENGTH) {
@@ -48,9 +47,7 @@ public class AdminAccessLogServiceImpl implements AdminAccessLogService {
accessLog.setUserAgent(StringUtil.substring(accessLog.getUserAgent(), USER_AGENT_MAX_LENGTH));
}
// 插入
- adminAccessLogMapper.insert(accessLog);
- // 返回成功
- return CommonResult.success(true);
+ accessLogMapper.insert(accessLog);
}
}
diff --git a/system/system-service-impl/src/main/resources/mapper/AccessLogMapper.xml b/system/system-service-impl/src/main/resources/mapper/AccessLogMapper.xml
new file mode 100644
index 000000000..8da990a11
--- /dev/null
+++ b/system/system-service-impl/src/main/resources/mapper/AccessLogMapper.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+ INSERT INTO access_log (
+ trace_id, user_id, user_type, uri, query_string, method, user_agent,
+ ip, start_time, response_time, error_code, error_message, create_time
+ ) VALUES (
+ #{traceId}, #{userId}, #{userType}, #{uri}, #{queryString}, #{method}, #{userAgent},
+ #{ip}, #{startTime}, #{responseTime}, #{errorCode}, #{errorMessage}, #{createTime}
+ )
+
+
+
diff --git a/system/system-service-impl/src/main/resources/mapper/AdminAccessLogMapper.xml b/system/system-service-impl/src/main/resources/mapper/AdminAccessLogMapper.xml
deleted file mode 100644
index 4afa93f7c..000000000
--- a/system/system-service-impl/src/main/resources/mapper/AdminAccessLogMapper.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-
-
-
-
-
-
-
-
-
-
- INSERT INTO admin_access_log (
- admin_id, uri, query_string, method, user_agent,
- ip, start_time, response_time, create_time
- ) VALUES (
- #{adminId}, #{uri}, #{queryString}, #{method}, #{userAgent},
- #{ip}, #{startTime}, #{responseTime}, #{createTime}
- )
-
-
-
\ No newline at end of file
diff --git a/user/user-application/pom.xml b/user/user-application/pom.xml
index 9729b5055..90cf867e1 100644
--- a/user/user-application/pom.xml
+++ b/user/user-application/pom.xml
@@ -74,8 +74,8 @@
springfox-swagger2
- io.springfox
- springfox-swagger-ui
+ com.github.xiaoymin
+ swagger-bootstrap-ui
diff --git a/user/user-application/src/main/java/cn/iocoder/mall/user/application/UserApplication.java b/user/user-application/src/main/java/cn/iocoder/mall/user/application/UserApplication.java
index 65d42497e..665799e44 100644
--- a/user/user-application/src/main/java/cn/iocoder/mall/user/application/UserApplication.java
+++ b/user/user-application/src/main/java/cn/iocoder/mall/user/application/UserApplication.java
@@ -2,9 +2,10 @@ package cn.iocoder.mall.user.application;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.web.servlet.config.annotation.EnableWebMvc;
+import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication(scanBasePackages = {"cn.iocoder.mall.user"})
+@EnableAsync(proxyTargetClass = true)
public class UserApplication {
public static void main(String[] args) {
diff --git a/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/SwaggerConfiguration.java b/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/SwaggerConfiguration.java
deleted file mode 100644
index d68e15763..000000000
--- a/user/user-application/src/main/java/cn/iocoder/mall/user/application/config/SwaggerConfiguration.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package cn.iocoder.mall.user.application.config;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-@Configuration
-@EnableSwagger2
-public class SwaggerConfiguration {
-
- @Bean
- public Docket createRestApi() {
- return new Docket(DocumentationType.SWAGGER_2)
- .apiInfo(apiInfo())
- .select()
- .apis(RequestHandlerSelectors.basePackage("cn.iocoder.mall.user.application.controller"))
- .paths(PathSelectors.any())
- .build();
- }
-
- private ApiInfo apiInfo() {
- return new ApiInfoBuilder()
- .title("用户子系统")
- .description("用户子系统")
- .termsOfServiceUrl("http://www.iocoder.cn")
- .version("1.0.0")
- .build();
- }
-
-}
\ No newline at end of file
diff --git a/user/user-application/src/main/resources/application.yaml b/user/user-application/src/main/resources/application.yaml
index 557069933..286272043 100644
--- a/user/user-application/src/main/resources/application.yaml
+++ b/user/user-application/src/main/resources/application.yaml
@@ -6,4 +6,10 @@ spring:
server:
port: 18082
servlet:
- context-path: /user-api/
\ No newline at end of file
+ context-path: /user-api/
+
+swagger:
+ title: 用户子系统
+ description: 用户子系统
+ version: 1.0.0
+ base-package: cn.iocoder.mall.user.application.controller
diff --git a/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java b/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java
deleted file mode 100644
index 42a8dd464..000000000
--- a/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java
+++ /dev/null
@@ -1,84 +0,0 @@
-package cn.iocoder.mall.user.sdk.interceptor;
-
-import cn.iocoder.common.framework.util.HttpUtil;
-import cn.iocoder.mall.user.api.UserAccessLogService;
-import cn.iocoder.mall.user.api.dto.UserAccessLogAddDTO;
-import com.alibaba.fastjson.JSON;
-import org.apache.commons.lang3.exception.ExceptionUtils;
-import org.apache.dubbo.config.annotation.Reference;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpMethod;
-import org.springframework.stereotype.Component;
-import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import java.util.Date;
-
-/**
- * 访问日志拦截器
- */
-@Component
-public class UserAccessLogInterceptor extends HandlerInterceptorAdapter {
-
- private Logger logger = LoggerFactory.getLogger(getClass());
-
- /**
- * 开始时间
- */
- private static final ThreadLocal START_TIME = new ThreadLocal<>();
- /**
- * 管理员编号
- */
- private static final ThreadLocal USER_ID = new ThreadLocal<>();
-
- @Reference(validation = "true", version = "${dubbo.provider.UserAccessLogService.version:1.0.0}")
- private UserAccessLogService userAccessLogService;
-
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
- // TODO 芋艿,临时拿来处理 vue axios options 请求的问题。
- if (HttpMethod.OPTIONS.matches(request.getMethod())) {
-
- return false; // 通过这样的方式,让前端知道允许的 header 等等。
- }
- // 记录当前时间
- START_TIME.set(new Date());
- return true;
- }
-
- @Override
- public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
- UserAccessLogAddDTO accessLog = new UserAccessLogAddDTO();
- try {
- accessLog.setUserId(USER_ID.get());
- if (accessLog.getUserId() == null) {
- accessLog.setUserId(UserAccessLogAddDTO.USER_ID_NULL);
- }
- accessLog.setUri(request.getRequestURI()); // TODO 提升:如果想要优化,可以使用 Swagger 的 @ApiOperation 注解。
- accessLog.setQueryString(HttpUtil.buildQueryString(request));
- accessLog.setMethod(request.getMethod());
- accessLog.setUserAgent(HttpUtil.getUserAgent(request));
- accessLog.setIp(HttpUtil.getIp(request));
- accessLog.setStartTime(START_TIME.get());
- accessLog.setResponseTime((int) (System.currentTimeMillis() - accessLog.getStartTime().getTime()));// 默认响应时间设为0
- userAccessLogService.addUserAccessLog(accessLog);
- // TODO 提升:暂时不考虑 ELK 的方案。而是基于 MySQL 存储。如果访问日志比较多,需要定期归档。
- } catch (Throwable th) {
- logger.error("[afterCompletion][插入管理员访问日志({}) 发生异常({})", JSON.toJSONString(accessLog), ExceptionUtils.getRootCauseMessage(th));
- } finally {
- clear();
- }
- }
-
- public static void setUserId(Integer userId) {
- USER_ID.set(userId);
- }
-
- public static void clear() {
- START_TIME.remove();
- USER_ID.remove();
- }
-
-}
diff --git a/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserSecurityInterceptor.java b/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserSecurityInterceptor.java
index 4deb50eff..9404aa9bf 100644
--- a/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserSecurityInterceptor.java
+++ b/user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserSecurityInterceptor.java
@@ -1,7 +1,9 @@
package cn.iocoder.mall.user.sdk.interceptor;
+import cn.iocoder.common.framework.constant.MallConstants;
import cn.iocoder.common.framework.exception.ServiceException;
import cn.iocoder.common.framework.util.HttpUtil;
+import cn.iocoder.common.framework.util.MallUtil;
import cn.iocoder.mall.user.api.OAuth2Service;
import cn.iocoder.mall.user.api.bo.OAuth2AuthenticationBO;
import cn.iocoder.mall.user.sdk.annotation.PermitAll;
@@ -26,8 +28,10 @@ public class UserSecurityInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+ // 设置当前访问的用户类型。注意,即使未登陆,我们也认为是用户
+ MallUtil.setUserType(request, MallConstants.USER_TYPE_USER);
// 校验访问令牌是否正确。若正确,返回授权信息
- String accessToken = HttpUtil.obtainAccess(request);
+ String accessToken = HttpUtil.obtainAuthorization(request);
OAuth2AuthenticationBO authentication = null;
if (accessToken != null) {
authentication = oauth2Service.checkToken(accessToken); // TODO 芋艿,如果访问的地址无需登录,这里也不用抛异常
@@ -39,7 +43,7 @@ public class UserSecurityInterceptor extends HandlerInterceptorAdapter {
// AdminSecurityInterceptor 执行后,会移除 AdminSecurityContext 信息,这就导致 AdminAccessLogInterceptor 无法获得管理员编号
// 因此,这里需要进行记录
if (authentication.getUserId() != null) {
- UserAccessLogInterceptor.setUserId(authentication.getUserId());
+ MallUtil.setUserId(request, authentication.getUserId());
}
}
// 校验是否需要已授权