From 53fff39a6c62fa1cd77bebe582f2b4a1df68b59c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 10 May 2019 18:47:29 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=90=8E=E7=AB=AF=EF=BC=9A=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2=20swagger=20bootstrap=20ui=20=EF=BC=8C=E4=B8=80?= =?UTF-8?q?=E4=B8=8B=E5=AD=90=E6=8E=A5=E5=8F=A3=E6=96=87=E6=A1=A3=E5=A5=BD?= =?UTF-8?q?=E7=9C=8B=E4=BA=86=E3=80=82=20-=20=E5=90=8E=E7=AB=AF=EF=BC=9A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20swagger=20AutoConfiguration=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E7=B1=BB=20-=20=E5=90=8E=E7=AB=AF=EF=BC=9A=E7=BB=9F?= =?UTF-8?q?=E4=B8=80=E8=AE=BF=E9=97=AE=E6=97=A5=E5=BF=97=E7=9A=84=E8=AE=B0?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/common-framework/pom.xml | 6 ++ .../framework/constant/MallConstants.java | 42 ++++++++ .../GlobalExceptionHandler.java | 3 +- .../common/framework/servlet/CorsFilter.java | 7 +- .../common/framework/util/HttpUtil.java | 4 +- .../common/framework/util/MallUtil.java | 53 ++++++++++ .../common/framework/vo/CommonResult.java | 2 +- common/mall-spring-boot/pom.xml | 11 +++ .../spring/boot/constant/RootRequestPath.java | 17 ---- .../swagger/SwaggerAutoConfiguration.java | 57 +++++++++++ .../boot/swagger/SwaggerProperties.java | 15 +++ .../boot/web/AdminMVCAutoConfiguration.java | 64 ++++++++++++ .../boot/web/AdminMVCConfiguration.java | 49 ---------- .../boot/web/UserMVCAutoConfiguration.java | 65 ++++++++++++ .../spring/boot/web/UserMVCConfiguration.java | 49 ---------- .../web/handler/GlobalExceptionHandler.java | 70 +++++++++++++ .../handler/GlobalResponseBodyHandler.java | 31 ++++++ .../web/interceptor/AccessLogInterceptor.java | 97 ++++++++++++++++++ .../main/resources/META-INF/spring.factories | 5 +- .../application/config/MVCConfiguration.java | 10 +- pay/pay-application/pom.xml | 10 +- .../mall/pay/application/PayApplication.java | 4 +- .../application/config/MVCConfiguration.java | 39 -------- .../config/SwaggerConfiguration.java | 36 ------- .../src/main/resources/application.yaml | 8 +- pom.xml | 14 +++ product/product-application/pom.xml | 10 +- .../application/ProductApplication.java | 4 +- .../application/config/MVCConfiguration.java | 42 -------- .../config/SwaggerConfiguration.java | 36 ------- .../src/main/resources/application.yaml | 8 +- .../main/resources/config/application.yaml | 2 + promotion/promotion-application/pom.xml | 15 ++- .../application/config/MVCConfiguration.java | 56 ----------- .../src/main/resources/application.yaml | 8 +- search/search-application/pom.xml | 9 +- .../search/application/SearchApplication.java | 2 + .../application/config/MVCConfiguration.java | 51 ---------- .../config/SwaggerConfiguration.java | 36 ------- .../src/main/resources/application.yaml | 6 ++ system/system-application/pom.xml | 5 +- .../admin/application/AdminApplication.java | 5 +- .../config/SwaggerConfiguration.java | 36 ------- .../controller/admins/AdminController.java | 4 +- .../src/main/resources/application-test.yaml | 3 + .../src/main/resources/application.yaml | 6 ++ .../AdminAccessLogInterceptor.java | 81 --------------- .../interceptor/AdminSecurityInterceptor.java | 8 +- .../mall/admin/api/AdminAccessLogService.java | 13 --- .../mall/admin/api/SystemLogService.java | 14 +++ .../mall/admin/api/dto/AccessLogAddDTO.java | 98 +++++++++++++++++++ .../admin/api/dto/AdminAccessLogAddDTO.java | 66 ------------- .../mall/admin/convert/AccessLogConvert.java | 17 ++++ .../admin/convert/AdminAccessLogConvert.java | 17 ---- .../mall/admin/dao/AccessLogMapper.java | 11 +++ .../mall/admin/dao/AdminAccessLogMapper.java | 11 --- .../mall/admin/dataobject/AccessLogDO.java | 84 ++++++++++++++++ .../admin/dataobject/AdminAccessLogDO.java | 55 ----------- ...iceImpl.java => SystemLogServiceImpl.java} | 23 ++--- .../main/resources/mapper/AccessLogMapper.xml | 20 ++++ .../resources/mapper/AdminAccessLogMapper.xml | 20 ---- user/user-application/pom.xml | 4 +- .../user/application/UserApplication.java | 3 +- .../config/SwaggerConfiguration.java | 36 ------- .../src/main/resources/application.yaml | 8 +- .../interceptor/UserAccessLogInterceptor.java | 84 ---------------- .../interceptor/UserSecurityInterceptor.java | 8 +- 67 files changed, 899 insertions(+), 894 deletions(-) create mode 100644 common/common-framework/src/main/java/cn/iocoder/common/framework/constant/MallConstants.java rename common/common-framework/src/main/java/cn/iocoder/common/framework/{config => exception}/GlobalExceptionHandler.java (96%) create mode 100644 common/common-framework/src/main/java/cn/iocoder/common/framework/util/MallUtil.java delete mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/constant/RootRequestPath.java create mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerAutoConfiguration.java create mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/swagger/SwaggerProperties.java create mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCAutoConfiguration.java delete mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/AdminMVCConfiguration.java create mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCAutoConfiguration.java delete mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/UserMVCConfiguration.java create mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalExceptionHandler.java create mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/handler/GlobalResponseBodyHandler.java create mode 100644 common/mall-spring-boot/src/main/java/cn/iocoder/mall/spring/boot/web/interceptor/AccessLogInterceptor.java delete mode 100644 pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/MVCConfiguration.java delete mode 100644 pay/pay-application/src/main/java/cn/iocoder/mall/pay/application/config/SwaggerConfiguration.java delete mode 100644 product/product-application/src/main/java/cn/iocoder/mall/product/application/config/MVCConfiguration.java delete mode 100644 product/product-application/src/main/java/cn/iocoder/mall/product/application/config/SwaggerConfiguration.java delete mode 100644 promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/config/MVCConfiguration.java delete mode 100644 search/search-application/src/main/java/cn/iocoder/mall/search/application/config/MVCConfiguration.java delete mode 100644 search/search-application/src/main/java/cn/iocoder/mall/search/application/config/SwaggerConfiguration.java delete mode 100644 system/system-application/src/main/java/cn/iocoder/mall/admin/application/config/SwaggerConfiguration.java delete mode 100644 system/system-sdk/src/main/java/cn/iocoder/mall/admin/sdk/interceptor/AdminAccessLogInterceptor.java delete mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/AdminAccessLogService.java create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/SystemLogService.java create mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AccessLogAddDTO.java delete mode 100644 system/system-service-api/src/main/java/cn/iocoder/mall/admin/api/dto/AdminAccessLogAddDTO.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AccessLogConvert.java delete mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/convert/AdminAccessLogConvert.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AccessLogMapper.java delete mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dao/AdminAccessLogMapper.java create mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AccessLogDO.java delete mode 100644 system/system-service-impl/src/main/java/cn/iocoder/mall/admin/dataobject/AdminAccessLogDO.java rename system/system-service-impl/src/main/java/cn/iocoder/mall/admin/service/{AdminAccessLogServiceImpl.java => SystemLogServiceImpl.java} (64%) create mode 100644 system/system-service-impl/src/main/resources/mapper/AccessLogMapper.xml delete mode 100644 system/system-service-impl/src/main/resources/mapper/AdminAccessLogMapper.xml delete mode 100644 user/user-application/src/main/java/cn/iocoder/mall/user/application/config/SwaggerConfiguration.java delete mode 100644 user/user-sdk/src/main/java/cn/iocoder/mall/user/sdk/interceptor/UserAccessLogInterceptor.java 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()); } } // 校验是否需要已授权