Commit 98761ef1d3ea070d1b547d556c27da06c880a5dc

Authored by 芋道源码
Committed by Gitee
2 parents 1a17e5ec cf4a27f4

!44 增加 yudao-user-server 服务

Merge pull request !44 from 芋道源码/feature/user-admin-server
Showing 56 changed files with 1691 additions and 26 deletions
@@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@
11 <module>yudao-dependencies</module> 11 <module>yudao-dependencies</module>
12 <module>yudao-framework</module> 12 <module>yudao-framework</module>
13 <module>yudao-admin-server</module> 13 <module>yudao-admin-server</module>
  14 + <module>yudao-user-server</module>
14 </modules> 15 </modules>
15 16
16 <name>${artifactId}</name> 17 <name>${artifactId}</name>
@@ -18,7 +19,7 @@ @@ -18,7 +19,7 @@
18 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 19 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
19 20
20 <properties> 21 <properties>
21 - <revision>1.0.0</revision> 22 + <revision>1.1.0-snapshot</revision>
22 <!-- Maven 相关 --> 23 <!-- Maven 相关 -->
23 <java.version>1.8</java.version> 24 <java.version>1.8</java.version>
24 <maven.compiler.source>${java.version}</maven.compiler.source> 25 <maven.compiler.source>${java.version}</maven.compiler.source>
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.framework.security;
  2 +
  3 +import cn.iocoder.yudao.framework.web.config.WebProperties;
  4 +import org.springframework.beans.factory.annotation.Value;
  5 +import org.springframework.context.annotation.Bean;
  6 +import org.springframework.context.annotation.Configuration;
  7 +import org.springframework.security.config.Customizer;
  8 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  9 +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
  10 +
  11 +import javax.annotation.Resource;
  12 +
  13 +@Configuration
  14 +public class SecurityConfiguration {
  15 +
  16 + @Resource
  17 + private WebProperties webProperties;
  18 +
  19 + @Value("${spring.boot.admin.context-path:''}")
  20 + private String adminSeverContextPath;
  21 +
  22 + @Bean
  23 + public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
  24 + return registry -> {
  25 + // 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去
  26 + registry.antMatchers(api("/system/captcha/**")).anonymous();
  27 + // Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去
  28 + registry.antMatchers(adminSeverContextPath).anonymous()
  29 + .antMatchers(adminSeverContextPath + "/**").anonymous();
  30 + // 短信回调 API
  31 + registry.antMatchers(api("/system/sms/callback/**")).anonymous();
  32 + };
  33 + }
  34 +
  35 + private String api(String url) {
  36 + return webProperties.getApiPrefix() + url;
  37 + }
  38 +
  39 +}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java
@@ -32,10 +32,9 @@ public class InfApiAccessLogServiceImpl implements InfApiAccessLogService { @@ -32,10 +32,9 @@ public class InfApiAccessLogServiceImpl implements InfApiAccessLogService {
32 @Override 32 @Override
33 @Async 33 @Async
34 public Future<Boolean> createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) { 34 public Future<Boolean> createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) {
35 - // 插入  
36 InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO); 35 InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO);
37 int insert = apiAccessLogMapper.insert(apiAccessLog); 36 int insert = apiAccessLogMapper.insert(apiAccessLog);
38 - return new AsyncResult<>(insert == 1); 37 + return new AsyncResult<>(insert > 1);
39 } 38 }
40 39
41 @Override 40 @Override
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java
@@ -167,7 +167,7 @@ public class SysUserController { @@ -167,7 +167,7 @@ public class SysUserController {
167 @PreAuthorize("@ss.hasPermission('system:user:import')") 167 @PreAuthorize("@ss.hasPermission('system:user:import')")
168 public CommonResult<SysUserImportRespVO> importExcel(@RequestParam("file") MultipartFile file, 168 public CommonResult<SysUserImportRespVO> importExcel(@RequestParam("file") MultipartFile file,
169 @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { 169 @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception {
170 - List<SysUserImportExcelVO> list = ExcelUtils.raed(file, SysUserImportExcelVO.class); 170 + List<SysUserImportExcelVO> list = ExcelUtils.read(file, SysUserImportExcelVO.class);
171 return success(userService.importUsers(list, updateSupport)); 171 return success(userService.importUsers(list, updateSupport));
172 } 172 }
173 173
yudao-admin-ui/src/views/system/role/index.vue
@@ -66,7 +66,7 @@ @@ -66,7 +66,7 @@
66 </el-table-column> 66 </el-table-column>
67 </el-table> 67 </el-table>
68 68
69 - <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" 69 + <pagination v-show="total>0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
70 @pagination="getList"/> 70 @pagination="getList"/>
71 71
72 <!-- 添加或修改角色配置对话框 --> 72 <!-- 添加或修改角色配置对话框 -->
yudao-dependencies/pom.xml
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url> 14 <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
15 15
16 <properties> 16 <properties>
17 - <revision>1.0.0</revision> 17 + <revision>1.1.0-snapshot</revision>
18 <!-- 统一依赖管理 --> 18 <!-- 统一依赖管理 -->
19 <spring.boot.version>2.4.5</spring.boot.version> 19 <spring.boot.version>2.4.5</spring.boot.version>
20 <!-- Web 相关 --> 20 <!-- Web 相关 -->
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
@@ -39,7 +39,7 @@ public class ExcelUtils { @@ -39,7 +39,7 @@ public class ExcelUtils {
39 response.setContentType("application/vnd.ms-excel;charset=UTF-8"); 39 response.setContentType("application/vnd.ms-excel;charset=UTF-8");
40 } 40 }
41 41
42 - public static <T> List<T> raed(MultipartFile file, Class<T> head) throws IOException { 42 + public static <T> List<T> read(MultipartFile file, Class<T> head) throws IOException {
43 return EasyExcel.read(file.getInputStream(), head, null) 43 return EasyExcel.read(file.getInputStream(), head, null)
44 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 44 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
45 .doReadAllSync(); 45 .doReadAllSync();
yudao-framework/yudao-spring-boot-starter-security/pom.xml
@@ -19,7 +19,12 @@ @@ -19,7 +19,12 @@
19 <dependency> 19 <dependency>
20 <groupId>cn.iocoder.boot</groupId> 20 <groupId>cn.iocoder.boot</groupId>
21 <artifactId>yudao-common</artifactId> 21 <artifactId>yudao-common</artifactId>
22 - <version>${revision}</version> 22 + </dependency>
  23 +
  24 + <!-- Spring 核心 -->
  25 + <dependency>
  26 + <groupId>org.springframework.boot</groupId>
  27 + <artifactId>spring-boot-starter-aop</artifactId>
23 </dependency> 28 </dependency>
24 29
25 <!-- Web 相关 --> 30 <!-- Web 相关 -->
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java
1 package cn.iocoder.yudao.framework.security.config; 1 package cn.iocoder.yudao.framework.security.config;
2 2
  3 +import cn.iocoder.yudao.framework.security.core.aop.PreAuthenticatedAspect;
3 import cn.iocoder.yudao.framework.security.core.filter.JwtAuthenticationTokenFilter; 4 import cn.iocoder.yudao.framework.security.core.filter.JwtAuthenticationTokenFilter;
4 import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl; 5 import cn.iocoder.yudao.framework.security.core.handler.AccessDeniedHandlerImpl;
5 import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl; 6 import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl;
@@ -33,6 +34,14 @@ public class YudaoSecurityAutoConfiguration { @@ -33,6 +34,14 @@ public class YudaoSecurityAutoConfiguration {
33 private SecurityProperties securityProperties; 34 private SecurityProperties securityProperties;
34 35
35 /** 36 /**
  37 + * 处理用户未登陆拦截的切面的 Bean
  38 + */
  39 + @Bean
  40 + public PreAuthenticatedAspect preAuthenticatedAspect() {
  41 + return new PreAuthenticatedAspect();
  42 + }
  43 +
  44 + /**
36 * 认证失败处理类 Bean 45 * 认证失败处理类 Bean
37 */ 46 */
38 @Bean 47 @Bean
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java
@@ -14,10 +14,12 @@ import org.springframework.context.annotation.Bean; @@ -14,10 +14,12 @@ import org.springframework.context.annotation.Bean;
14 import org.springframework.context.annotation.Configuration; 14 import org.springframework.context.annotation.Configuration;
15 import org.springframework.http.HttpMethod; 15 import org.springframework.http.HttpMethod;
16 import org.springframework.security.authentication.AuthenticationManager; 16 import org.springframework.security.authentication.AuthenticationManager;
  17 +import org.springframework.security.config.Customizer;
17 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 18 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
18 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; 19 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
19 import org.springframework.security.config.annotation.web.builders.HttpSecurity; 20 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
20 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 21 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  22 +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
21 import org.springframework.security.config.http.SessionCreationPolicy; 23 import org.springframework.security.config.http.SessionCreationPolicy;
22 import org.springframework.security.core.userdetails.UserDetailsService; 24 import org.springframework.security.core.userdetails.UserDetailsService;
23 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 25 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
@@ -41,9 +43,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -41,9 +43,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
41 @Resource 43 @Resource
42 private WebProperties webProperties; 44 private WebProperties webProperties;
43 45
44 - @Value("${spring.boot.admin.context-path:''}")  
45 - private String adminSeverContextPath;  
46 -  
47 /** 46 /**
48 * 自定义用户【认证】逻辑 47 * 自定义用户【认证】逻辑
49 */ 48 */
@@ -74,6 +73,13 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -74,6 +73,13 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
74 */ 73 */
75 @Resource 74 @Resource
76 private JwtAuthenticationTokenFilter authenticationTokenFilter; 75 private JwtAuthenticationTokenFilter authenticationTokenFilter;
  76 + /**
  77 + * 自定义的权限映射 Bean
  78 + *
  79 + * @see #configure(HttpSecurity)
  80 + */
  81 + @Resource
  82 + private Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer;
77 83
78 /** 84 /**
79 * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 85 * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入
@@ -121,15 +127,16 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -121,15 +127,16 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
121 .csrf().disable() 127 .csrf().disable()
122 // 基于 token 机制,所以不需要 Session 128 // 基于 token 机制,所以不需要 Session
123 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 129 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
  130 + .headers().frameOptions().disable().and()
124 // 一堆自定义的 Spring Security 处理器 131 // 一堆自定义的 Spring Security 处理器
125 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) 132 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
126 .accessDeniedHandler(accessDeniedHandler).and() 133 .accessDeniedHandler(accessDeniedHandler).and()
127 - // 设置每个请求的权限  
128 - .authorizeRequests() 134 + .logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出
  135 +
  136 + // 设置每个请求的权限 ①:全局共享规则
  137 + httpSecurity.authorizeRequests()
129 // 登陆的接口,可匿名访问 138 // 登陆的接口,可匿名访问
130 .antMatchers(api("/login")).anonymous() 139 .antMatchers(api("/login")).anonymous()
131 - // 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去  
132 - .antMatchers(api("/system/captcha/**")).anonymous()  
133 // 静态资源,可匿名访问 140 // 静态资源,可匿名访问
134 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() 141 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll()
135 // 文件的获取接口,可匿名访问 142 // 文件的获取接口,可匿名访问
@@ -139,21 +146,15 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @@ -139,21 +146,15 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
139 .antMatchers("/swagger-resources/**").anonymous() 146 .antMatchers("/swagger-resources/**").anonymous()
140 .antMatchers("/webjars/**").anonymous() 147 .antMatchers("/webjars/**").anonymous()
141 .antMatchers("/*/api-docs").anonymous() 148 .antMatchers("/*/api-docs").anonymous()
142 - // Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去  
143 - .antMatchers(adminSeverContextPath).anonymous()  
144 - .antMatchers(adminSeverContextPath + "/**").anonymous()  
145 // Spring Boot Actuator 的安全配置 149 // Spring Boot Actuator 的安全配置
146 .antMatchers("/actuator").anonymous() 150 .antMatchers("/actuator").anonymous()
147 .antMatchers("/actuator/**").anonymous() 151 .antMatchers("/actuator/**").anonymous()
148 - // Druid 监控 TODO 芋艿:需要抽象出去 152 + // Druid 监控 TODO 芋艿:等对接了 druid admin 后,在调整下。
149 .antMatchers("/druid/**").anonymous() 153 .antMatchers("/druid/**").anonymous()
150 - // 短信回调 API TODO 芋艿:需要抽象出去  
151 - .antMatchers(api("/system/sms/callback/**")).anonymous()  
152 - // 除上面外的所有请求全部需要鉴权认证  
153 - .anyRequest().authenticated()  
154 - .and()  
155 - .headers().frameOptions().disable();  
156 - httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); 154 + // 设置每个请求的权限 ②:每个项目的自定义规则
  155 + .and().authorizeRequests(authorizeRequestsCustomizer)
  156 + // 设置每个请求的权限 ③:兜底规则,必须认证
  157 + .authorizeRequests().anyRequest().authenticated();
157 // 添加 JWT Filter 158 // 添加 JWT Filter
158 httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); 159 httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
159 } 160 }
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/PreAuthenticated.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.security.core.annotations;
  2 +
  3 +import java.lang.annotation.*;
  4 +
  5 +/**
  6 + * 声明用户需要登陆
  7 + *
  8 + * 为什么不使用 {@link org.springframework.security.access.prepost.PreAuthorize} 注解,原因是不通过时,抛出的是认证不通过,而不是未登陆
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Target({ElementType.METHOD})
  13 +@Retention(RetentionPolicy.RUNTIME)
  14 +@Inherited
  15 +@Documented
  16 +public @interface PreAuthenticated {
  17 +}
yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/aop/PreAuthenticatedAspect.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.security.core.aop;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
  4 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.aspectj.lang.ProceedingJoinPoint;
  7 +import org.aspectj.lang.annotation.Around;
  8 +import org.aspectj.lang.annotation.Aspect;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstants.UNAUTHORIZED;
  11 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  12 +
  13 +@Aspect
  14 +@Slf4j
  15 +public class PreAuthenticatedAspect {
  16 +
  17 + @Around("@annotation(preAuthenticated)")
  18 + public Object around(ProceedingJoinPoint joinPoint, PreAuthenticated preAuthenticated) throws Throwable {
  19 + if (SecurityFrameworkUtils.getLoginUser() == null) {
  20 + throw exception(UNAUTHORIZED);
  21 + }
  22 + return joinPoint.proceed();
  23 + }
  24 +
  25 +}
yudao-user-server/pom.xml 0 → 100644
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0"
  3 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  5 + <parent>
  6 + <groupId>cn.iocoder.boot</groupId>
  7 + <artifactId>yudao</artifactId>
  8 + <version>${revision}</version>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>yudao-user-server</artifactId>
  13 + <packaging>jar</packaging>
  14 +
  15 + <name>yudao-admin-server</name>
  16 + <description>用户前台 Server,提供其 API 接口</description>
  17 + <url>https://github.com/YunaiV/ruoyi-vue-pro</url>
  18 +
  19 + <dependencies>
  20 + <!-- 业务组件 -->
  21 + <dependency>
  22 + <groupId>cn.iocoder.boot</groupId>
  23 + <artifactId>yudao-spring-boot-starter-biz-dict</artifactId>
  24 + </dependency>
  25 + <dependency>
  26 + <groupId>cn.iocoder.boot</groupId>
  27 + <artifactId>yudao-spring-boot-starter-biz-sms</artifactId>
  28 + </dependency>
  29 +
  30 + <!-- Web 相关 -->
  31 + <dependency>
  32 + <groupId>cn.iocoder.boot</groupId>
  33 + <artifactId>yudao-spring-boot-starter-web</artifactId>
  34 + </dependency>
  35 +
  36 + <dependency>
  37 + <groupId>cn.iocoder.boot</groupId>
  38 + <artifactId>yudao-spring-boot-starter-security</artifactId>
  39 + </dependency>
  40 +
  41 + <!-- DB 相关 -->
  42 + <dependency>
  43 + <groupId>cn.iocoder.boot</groupId>
  44 + <artifactId>yudao-spring-boot-starter-mybatis</artifactId>
  45 + </dependency>
  46 +
  47 + <dependency>
  48 + <groupId>cn.iocoder.boot</groupId>
  49 + <artifactId>yudao-spring-boot-starter-redis</artifactId>
  50 + </dependency>
  51 +
  52 + <!-- Config 配置中心相关 -->
  53 + <dependency>
  54 + <groupId>cn.iocoder.boot</groupId>
  55 + <artifactId>yudao-spring-boot-starter-config</artifactId>
  56 + </dependency>
  57 +
  58 + <!-- Job 定时任务相关 -->
  59 +
  60 + <!-- 消息队列相关 -->
  61 + <dependency>
  62 + <groupId>cn.iocoder.boot</groupId>
  63 + <artifactId>yudao-spring-boot-starter-mq</artifactId>
  64 + </dependency>
  65 +
  66 + <!-- 服务保障相关 -->
  67 + <dependency>
  68 + <groupId>cn.iocoder.boot</groupId>
  69 + <artifactId>yudao-spring-boot-starter-protection</artifactId>
  70 + </dependency>
  71 +
  72 + <!-- 监控相关 -->
  73 + <dependency>
  74 + <groupId>cn.iocoder.boot</groupId>
  75 + <artifactId>yudao-spring-boot-starter-monitor</artifactId>
  76 + </dependency>
  77 +
  78 + <!-- Test 测试相关 -->
  79 + <dependency>
  80 + <groupId>cn.iocoder.boot</groupId>
  81 + <artifactId>yudao-spring-boot-starter-test</artifactId>
  82 + <scope>test</scope>
  83 + </dependency>
  84 +
  85 + <!-- 工具类相关 -->
  86 +
  87 + </dependencies>
  88 +
  89 + <build>
  90 + <!-- 设置构建的 jar 包名 -->
  91 + <finalName>${artifactId}</finalName>
  92 + <plugins>
  93 + <!-- 打包 -->
  94 + <plugin>
  95 + <groupId>org.springframework.boot</groupId>
  96 + <artifactId>spring-boot-maven-plugin</artifactId>
  97 + <configuration>
  98 + <fork>true</fork>
  99 + </configuration>
  100 + <executions>
  101 + <execution>
  102 + <goals>
  103 + <goal>repackage</goal> <!-- 将引入的 jar 打入其中 -->
  104 + </goals>
  105 + </execution>
  106 + </executions>
  107 + </plugin>
  108 + </plugins>
  109 + </build>
  110 +
  111 +</project>
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver;
  2 +
  3 +import org.springframework.boot.SpringApplication;
  4 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  5 +
  6 +@SpringBootApplication
  7 +public class UserServerApplication {
  8 +
  9 + public static void main(String[] args) {
  10 + SpringApplication.run(UserServerApplication.class, args);
  11 + }
  12 +
  13 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.framework.async.config;
  2 +
  3 +import org.springframework.context.annotation.Configuration;
  4 +import org.springframework.scheduling.annotation.EnableAsync;
  5 +
  6 +@Configuration
  7 +@EnableAsync
  8 +public class AsyncConfiguration {
  9 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java 0 → 100644
  1 +/**
  2 + * 异步执行,基于 Spring @Async 实现
  3 + */
  4 +package cn.iocoder.yudao.userserver.framework.async;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/Async-Job/?yudao>
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java 0 → 100644
  1 +/**
  2 + * 属于整个 yudao-user-server 的 framework 封装
  3 + *
  4 + * @author 芋道源码
  5 + */
  6 +package cn.iocoder.yudao.userserver.framework;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/security/SecurityConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.framework.security;
  2 +
  3 +import cn.iocoder.yudao.framework.web.config.WebProperties;
  4 +import org.springframework.context.annotation.Bean;
  5 +import org.springframework.context.annotation.Configuration;
  6 +import org.springframework.security.config.Customizer;
  7 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  8 +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
  9 +
  10 +import javax.annotation.Resource;
  11 +
  12 +@Configuration
  13 +public class SecurityConfiguration {
  14 +
  15 + @Resource
  16 + private WebProperties webProperties;
  17 +
  18 + @Bean
  19 + public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
  20 + return registry -> {
  21 + registry.antMatchers(api("/**")).anonymous(); // 默认 API 都是用户可访问
  22 + };
  23 + }
  24 +
  25 + private String api(String url) {
  26 + return webProperties.getApiPrefix() + url;
  27 + }
  28 +
  29 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/controller/HelloController.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.controller;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.springframework.security.access.annotation.Secured;
  6 +import org.springframework.security.access.prepost.PreAuthorize;
  7 +import org.springframework.web.bind.annotation.RequestMapping;
  8 +import org.springframework.web.bind.annotation.RestController;
  9 +
  10 +/**
  11 + * @author weir
  12 + */
  13 +@Slf4j
  14 +@RestController
  15 +public class HelloController {
  16 +
  17 + @RequestMapping("/user/hello")
  18 + public String hello(String hello) {
  19 + return "echo + " + hello;
  20 + }
  21 +
  22 + @RequestMapping("/user/info")
  23 + @PreAuthenticated
  24 + public String xx() {
  25 + return "none";
  26 + }
  27 +
  28 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiAccessLogConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.convert.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO;
  4 +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger.InfApiAccessLogDO;
  5 +import org.mapstruct.Mapper;
  6 +import org.mapstruct.factory.Mappers;
  7 +
  8 +/**
  9 + * API 访问日志 Convert
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@Mapper
  14 +public interface InfApiAccessLogConvert {
  15 +
  16 + InfApiAccessLogConvert INSTANCE = Mappers.getMapper(InfApiAccessLogConvert.class);
  17 +
  18 + InfApiAccessLogDO convert(ApiAccessLogCreateDTO bean);
  19 +
  20 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiErrorLogConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.convert.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO;
  4 +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
  5 +import org.mapstruct.Mapper;
  6 +import org.mapstruct.factory.Mappers;
  7 +
  8 +/**
  9 + * API 错误日志 Convert
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@Mapper
  14 +public interface InfApiErrorLogConvert {
  15 +
  16 + InfApiErrorLogConvert INSTANCE = Mappers.getMapper(InfApiErrorLogConvert.class);
  17 +
  18 + InfApiErrorLogDO convert(ApiErrorLogCreateDTO bean);
  19 +
  20 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/package-info.java 0 → 100644
  1 +/**
  2 + * 提供 POJO 类的实体转换
  3 + *
  4 + * 目前使用 MapStruct 框架
  5 + */
  6 +package cn.iocoder.yudao.userserver.modules.infra.convert;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md 0 → 100644
  1 +<http://www.iocoder.cn/Spring-Boot/MapStruct/?yudao>
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.config;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.TableField;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +import lombok.ToString;
  10 +
  11 +/**
  12 + * 参数配置表
  13 + *
  14 + * @author ruoyi
  15 + */
  16 +@TableName("inf_config")
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +public class InfConfigDO extends BaseDO {
  21 +
  22 + /**
  23 + * 参数主键
  24 + */
  25 + @TableId
  26 + private Long id;
  27 + /**
  28 + * 参数分组
  29 + */
  30 + @TableField("`group`")
  31 + private String group;
  32 + /**
  33 + * 参数名称
  34 + */
  35 + private String name;
  36 + /**
  37 + * 参数键名
  38 + */
  39 + @TableField("`key`")
  40 + private String key;
  41 + /**
  42 + * 参数键值
  43 + */
  44 + private String value;
  45 + /**
  46 + * 参数类型
  47 + *
  48 + * 枚举 {@link InfConfigTypeEnum}
  49 + */
  50 + @TableField("`type`")
  51 + private Integer type;
  52 + /**
  53 + * 是否敏感
  54 + *
  55 + * 对于敏感配置,需要管理权限才能查看
  56 + */
  57 + @TableField("`sensitive`")
  58 + private Boolean sensitive;
  59 + /**
  60 + * 备注
  61 + */
  62 + private String remark;
  63 +
  64 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.file;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import com.baomidou.mybatisplus.annotation.IdType;
  5 +import com.baomidou.mybatisplus.annotation.TableField;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +import java.io.InputStream;
  11 +
  12 +/**
  13 + * 文件表
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Data
  18 +@TableName("inf_file")
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class InfFileDO extends BaseDO {
  25 +
  26 + /**
  27 + * 文件路径
  28 + */
  29 + @TableId(type = IdType.INPUT)
  30 + private String id;
  31 + /**
  32 + * 文件类型
  33 + *
  34 + * 通过 {@link cn.hutool.core.io.FileTypeUtil#getType(InputStream)} 获取
  35 + */
  36 + @TableField(value = "`type`")
  37 + private String type;
  38 + /**
  39 + * 文件内容
  40 + */
  41 + private byte[] content;
  42 +
  43 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  6 +import com.baomidou.mybatisplus.annotation.TableId;
  7 +import com.baomidou.mybatisplus.annotation.TableName;
  8 +import lombok.*;
  9 +
  10 +import java.util.Date;
  11 +
  12 +/**
  13 + * API 访问日志
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@TableName("inf_api_access_log")
  18 +@Data
  19 +@EqualsAndHashCode(callSuper = true)
  20 +@ToString(callSuper = true)
  21 +@Builder
  22 +@NoArgsConstructor
  23 +@AllArgsConstructor
  24 +public class InfApiAccessLogDO extends BaseDO {
  25 +
  26 + /**
  27 + * 编号
  28 + */
  29 + @TableId
  30 + private Integer id;
  31 + /**
  32 + * 链路追踪编号
  33 + *
  34 + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
  35 + */
  36 + private String traceId;
  37 + /**
  38 + * 用户编号
  39 + */
  40 + private Long userId;
  41 + /**
  42 + * 用户类型
  43 + *
  44 + * 枚举 {@link UserTypeEnum}
  45 + */
  46 + private Integer userType;
  47 + /**
  48 + * 应用名
  49 + *
  50 + * 目前读取 `spring.application.name` 配置项
  51 + */
  52 + private String applicationName;
  53 +
  54 + // ========== 请求相关字段 ==========
  55 +
  56 + /**
  57 + * 请求方法名
  58 + */
  59 + private String requestMethod;
  60 + /**
  61 + * 访问地址
  62 + */
  63 + private String requestUrl;
  64 + /**
  65 + * 请求参数
  66 + *
  67 + * query: Query String
  68 + * body: Quest Body
  69 + */
  70 + private String requestParams;
  71 + /**
  72 + * 用户 IP
  73 + */
  74 + private String userIp;
  75 + /**
  76 + * 浏览器 UA
  77 + */
  78 + private String userAgent;
  79 +
  80 + // ========== 执行相关字段 ==========
  81 +
  82 + /**
  83 + * 开始请求时间
  84 + */
  85 + private Date beginTime;
  86 + /**
  87 + * 结束请求时间
  88 + */
  89 + private Date endTime;
  90 + /**
  91 + * 执行时长,单位:毫秒
  92 + */
  93 + private Integer duration;
  94 + /**
  95 + * 结果码
  96 + *
  97 + * 目前使用的 {@link CommonResult#getCode()} 属性
  98 + */
  99 + private Integer resultCode;
  100 + /**
  101 + * 结果提示
  102 + *
  103 + * 目前使用的 {@link CommonResult#getMsg()} 属性
  104 + */
  105 + private String resultMsg;
  106 +
  107 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.userserver.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.*;
  8 +
  9 +import java.util.Date;
  10 +
  11 +/**
  12 + * API 异常数据
  13 + *
  14 + * @author 芋道源码
  15 + */
  16 +@TableName("inf_api_error_log")
  17 +@Data
  18 +@EqualsAndHashCode(callSuper = true)
  19 +@ToString(callSuper = true)
  20 +@Builder
  21 +@NoArgsConstructor
  22 +@AllArgsConstructor
  23 +public class InfApiErrorLogDO extends BaseDO {
  24 +
  25 + /**
  26 + * 编号
  27 + */
  28 + private Long id;
  29 + /**
  30 + * 用户编号
  31 + */
  32 + private Long userId;
  33 + /**
  34 + * 链路追踪编号
  35 + *
  36 + * 一般来说,通过链路追踪编号,可以将访问日志,错误日志,链路追踪日志,logger 打印日志等,结合在一起,从而进行排错。
  37 + */
  38 + private String traceId;
  39 + /**
  40 + * 用户类型
  41 + *
  42 + * 枚举 {@link UserTypeEnum}
  43 + */
  44 + private Integer userType;
  45 + /**
  46 + * 应用名
  47 + *
  48 + * 目前读取 spring.application.name
  49 + */
  50 + private String applicationName;
  51 +
  52 + // ========== 请求相关字段 ==========
  53 +
  54 + /**
  55 + * 请求方法名
  56 + */
  57 + private String requestMethod;
  58 + /**
  59 + * 访问地址
  60 + */
  61 + private String requestUrl;
  62 + /**
  63 + * 请求参数
  64 + *
  65 + * query: Query String
  66 + * body: Quest Body
  67 + */
  68 + private String requestParams;
  69 + /**
  70 + * 用户 IP
  71 + */
  72 + private String userIp;
  73 + /**
  74 + * 浏览器 UA
  75 + */
  76 + private String userAgent;
  77 +
  78 + // ========== 异常相关字段 ==========
  79 +
  80 + /**
  81 + * 异常发生时间
  82 + */
  83 + private Date exceptionTime;
  84 + /**
  85 + * 异常名
  86 + *
  87 + * {@link Throwable#getClass()} 的类全名
  88 + */
  89 + private String exceptionName;
  90 + /**
  91 + * 异常导致的消息
  92 + *
  93 + * {@link cn.hutool.core.exceptions.ExceptionUtil#getMessage(Throwable)}
  94 + */
  95 + private String exceptionMessage;
  96 + /**
  97 + * 异常导致的根消息
  98 + *
  99 + * {@link cn.hutool.core.exceptions.ExceptionUtil#getRootCauseMessage(Throwable)}
  100 + */
  101 + private String exceptionRootCauseMessage;
  102 + /**
  103 + * 异常的栈轨迹
  104 + *
  105 + * {@link org.apache.commons.lang3.exception.ExceptionUtils#getStackTrace(Throwable)}
  106 + */
  107 + private String exceptionStackTrace;
  108 + /**
  109 + * 异常发生的类全名
  110 + *
  111 + * {@link StackTraceElement#getClassName()}
  112 + */
  113 + private String exceptionClassName;
  114 + /**
  115 + * 异常发生的类文件
  116 + *
  117 + * {@link StackTraceElement#getFileName()}
  118 + */
  119 + private String exceptionFileName;
  120 + /**
  121 + * 异常发生的方法名
  122 + *
  123 + * {@link StackTraceElement#getMethodName()}
  124 + */
  125 + private String exceptionMethodName;
  126 + /**
  127 + * 异常发生的方法所在行
  128 + *
  129 + * {@link StackTraceElement#getLineNumber()}
  130 + */
  131 + private Integer exceptionLineNumber;
  132 +
  133 + // ========== 处理相关字段 ==========
  134 +
  135 + /**
  136 + * 处理状态
  137 + *
  138 + * 枚举 {@link InfApiErrorLogProcessStatusEnum}
  139 + */
  140 + private Integer processStatus;
  141 + /**
  142 + * 处理时间
  143 + */
  144 + private Date processTime;
  145 + /**
  146 + * 处理用户编号
  147 + *
  148 + * 关联 cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.user.SysUserDO.SysUserDO#getId()
  149 + */
  150 + private Long processUserId;
  151 +
  152 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.mysql.config;
  2 +
  3 +import cn.iocoder.yudao.framework.apollo.internals.ConfigFrameworkDAO;
  4 +import cn.iocoder.yudao.framework.apollo.internals.dto.ConfigRespDTO;
  5 +import org.springframework.jdbc.core.BeanPropertyRowMapper;
  6 +import org.springframework.jdbc.core.JdbcTemplate;
  7 +import org.springframework.jdbc.datasource.DriverManagerDataSource;
  8 +
  9 +import javax.sql.DataSource;
  10 +import java.sql.ResultSet;
  11 +import java.util.Date;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * ConfigFrameworkDAO 实现类
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +public class InfConfigDAOImpl implements ConfigFrameworkDAO {
  20 +
  21 + private final JdbcTemplate jdbcTemplate;
  22 +
  23 + public InfConfigDAOImpl(String jdbcUrl, String username, String password) {
  24 + DataSource dataSource = new DriverManagerDataSource(jdbcUrl, username, password);
  25 + this.jdbcTemplate = new JdbcTemplate(dataSource);
  26 + }
  27 +
  28 + @Override
  29 + public boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
  30 + return jdbcTemplate.query("SELECT id FROM inf_config WHERE update_time > ? LIMIT 1",
  31 + ResultSet::next, maxUpdateTime);
  32 + }
  33 +
  34 + @Override
  35 + public List<ConfigRespDTO> selectList() {
  36 + return jdbcTemplate.query("SELECT `key`, `value`, update_time, deleted FROM inf_config", new BeanPropertyRowMapper<>(ConfigRespDTO.class));
  37 + }
  38 +
  39 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.mysql.file;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.file.InfFileDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface InfFileMapper extends BaseMapperX<InfFileDO> {
  9 +
  10 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiAccessLogMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.mysql.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger.InfApiAccessLogDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * API 访问日志 Mapper
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Mapper
  15 +public interface InfApiAccessLogMapper extends BaseMapperX<InfApiAccessLogDO> {
  16 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.dal.mysql.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  4 +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +/**
  8 + * API 错误日志 Mapper
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +@Mapper
  13 +public interface InfApiErrorLogMapper extends BaseMapperX<InfApiErrorLogDO> {
  14 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.enums.logger;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +/**
  7 + * API 异常数据的处理状态
  8 + *
  9 + * @author 芋道源码
  10 + */
  11 +@AllArgsConstructor
  12 +@Getter
  13 +public enum InfApiErrorLogProcessStatusEnum {
  14 +
  15 + INIT(0, "未处理"),
  16 + DONE(1, "已处理"),
  17 + IGNORE(2, "已忽略");
  18 +
  19 + /**
  20 + * 状态
  21 + */
  22 + private final Integer status;
  23 + /**
  24 + * 资源类型名
  25 + */
  26 + private final String name;
  27 +
  28 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/package-info.java 0 → 100644
  1 +/**
  2 + * 占位类,可以无视
  3 + */
  4 +package cn.iocoder.yudao.userserver.modules.infra.enums;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java 0 → 100644
  1 +/**
  2 + * infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。
  3 + * 例如说:定时任务的管理、服务器的信息等等
  4 + *
  5 + * 缩写:inf
  6 + */
  7 +package cn.iocoder.yudao.userserver.modules.infra;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/SysAuthService.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.service.auth;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
  4 +
  5 +/**
  6 + * 认证 Service 接口
  7 + *
  8 + * 提供用户的账号密码登陆、token 的校验等认证相关的功能
  9 + *
  10 + * @author 芋道源码
  11 + */
  12 +public interface SysAuthService extends SecurityAuthFrameworkService {
  13 +
  14 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/impl/SysAuthServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.service.auth.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  4 +import cn.iocoder.yudao.userserver.modules.infra.service.auth.SysAuthService;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.springframework.security.core.userdetails.UserDetails;
  7 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
  8 +import org.springframework.stereotype.Service;
  9 +
  10 +/**
  11 + * Auth Service 实现类
  12 + *
  13 + * @author 芋道源码
  14 + */
  15 +@Service
  16 +@Slf4j
  17 +public class SysAuthServiceImpl implements SysAuthService {
  18 +
  19 + @Override
  20 + public LoginUser verifyTokenAndRefresh(String token) {
  21 + return null;
  22 + }
  23 +
  24 + @Override
  25 + public LoginUser mockLogin(Long userId) {
  26 + return null;
  27 + }
  28 +
  29 + @Override
  30 + public void logout(String token) {
  31 +
  32 + }
  33 +
  34 + @Override
  35 + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  36 + return null;
  37 + }
  38 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiAccessLogService.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.service.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.service.ApiAccessLogFrameworkService;
  4 +
  5 +/**
  6 + * API 访问日志 Service 接口
  7 + *
  8 + * @author 芋道源码
  9 + */
  10 +public interface InfApiAccessLogService extends ApiAccessLogFrameworkService {
  11 +
  12 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiErrorLogService.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.service.logger;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.service.ApiErrorLogFrameworkService;
  4 +
  5 +/**
  6 + * API 错误日志 Service 接口
  7 + *
  8 + * @author 芋道源码
  9 + */
  10 +public interface InfApiErrorLogService extends ApiErrorLogFrameworkService {
  11 +
  12 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.service.logger.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiAccessLogCreateDTO;
  4 +import cn.iocoder.yudao.userserver.modules.infra.convert.logger.InfApiAccessLogConvert;
  5 +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger.InfApiAccessLogDO;
  6 +import cn.iocoder.yudao.userserver.modules.infra.dal.mysql.logger.InfApiAccessLogMapper;
  7 +import cn.iocoder.yudao.userserver.modules.infra.service.logger.InfApiAccessLogService;
  8 +import lombok.extern.slf4j.Slf4j;
  9 +import org.springframework.scheduling.annotation.AsyncResult;
  10 +import org.springframework.stereotype.Service;
  11 +import org.springframework.validation.annotation.Validated;
  12 +
  13 +import javax.annotation.Resource;
  14 +import java.util.concurrent.Future;
  15 +
  16 +/**
  17 + * API 访问日志 Service 实现类
  18 + *
  19 + * @author 芋道源码
  20 + */
  21 +@Service
  22 +@Validated
  23 +@Slf4j
  24 +public class InfApiAccessLogServiceImpl implements InfApiAccessLogService {
  25 +
  26 + @Resource
  27 + private InfApiAccessLogMapper apiAccessLogMapper;
  28 +
  29 + @Override
  30 + public Future<Boolean> createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) {
  31 + InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO);
  32 + int insert = apiAccessLogMapper.insert(apiAccessLog);
  33 + return new AsyncResult<>(insert > 1);
  34 + }
  35 +
  36 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.infra.service.logger.impl;
  2 +
  3 +import cn.iocoder.yudao.framework.apilog.core.service.dto.ApiErrorLogCreateDTO;
  4 +import cn.iocoder.yudao.userserver.modules.infra.convert.logger.InfApiErrorLogConvert;
  5 +import cn.iocoder.yudao.userserver.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
  6 +import cn.iocoder.yudao.userserver.modules.infra.dal.mysql.logger.InfApiErrorLogMapper;
  7 +import cn.iocoder.yudao.userserver.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
  8 +import cn.iocoder.yudao.userserver.modules.infra.service.logger.InfApiErrorLogService;
  9 +import lombok.extern.slf4j.Slf4j;
  10 +import org.springframework.scheduling.annotation.AsyncResult;
  11 +import org.springframework.stereotype.Service;
  12 +import org.springframework.validation.annotation.Validated;
  13 +
  14 +import javax.annotation.Resource;
  15 +import java.util.concurrent.Future;
  16 +
  17 +/**
  18 + * API 错误日志 Service 实现类
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +@Service
  23 +@Validated
  24 +@Slf4j
  25 +public class InfApiErrorLogServiceImpl implements InfApiErrorLogService {
  26 +
  27 + @Resource
  28 + private InfApiErrorLogMapper apiErrorLogMapper;
  29 +
  30 + @Override
  31 + public Future<Boolean> createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) {
  32 + InfApiErrorLogDO apiErrorLog = InfApiErrorLogConvert.INSTANCE.convert(createDTO);
  33 + apiErrorLog.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus());
  34 + int insert = apiErrorLogMapper.insert(apiErrorLog);
  35 + return new AsyncResult<>(insert == 1);
  36 + }
  37 +
  38 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/dict/SysDictDataConvert.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.convert.dict;
  2 +
  3 +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
  4 +import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict.SysDictDataDO;
  5 +import org.mapstruct.Mapper;
  6 +import org.mapstruct.factory.Mappers;
  7 +
  8 +import java.util.Collection;
  9 +import java.util.List;
  10 +
  11 +@Mapper
  12 +public interface SysDictDataConvert {
  13 +
  14 + SysDictDataConvert INSTANCE = Mappers.getMapper(SysDictDataConvert.class);
  15 +
  16 + DictDataRespDTO convert02(SysDictDataDO bean);
  17 +
  18 + List<DictDataRespDTO> convertList03(Collection<SysDictDataDO> list);
  19 +
  20 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.convert;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/dict/SysDictDataDO.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.TableId;
  6 +import com.baomidou.mybatisplus.annotation.TableName;
  7 +import lombok.Data;
  8 +import lombok.EqualsAndHashCode;
  9 +
  10 +/**
  11 + * 字典数据表
  12 + *
  13 + * @author ruoyi
  14 + */
  15 +@TableName("sys_dict_data")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +public class SysDictDataDO extends BaseDO {
  19 +
  20 + /**
  21 + * 字典数据编号
  22 + */
  23 + @TableId
  24 + private Long id;
  25 + /**
  26 + * 字典排序
  27 + */
  28 + private Integer sort;
  29 + /**
  30 + * 字典标签
  31 + */
  32 + private String label;
  33 + /**
  34 + * 字典值
  35 + */
  36 + private String value;
  37 + /**
  38 + * 字典类型
  39 + *
  40 + * 冗余 {@link SysDictDataDO#getDictType()}
  41 + */
  42 + private String dictType;
  43 + /**
  44 + * 状态
  45 + *
  46 + * 枚举 {@link CommonStatusEnum}
  47 + */
  48 + private Integer status;
  49 + /**
  50 + * 备注
  51 + */
  52 + private String remark;
  53 +
  54 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dal.dataobject;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/dict/SysDictDataMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dal.mysql.dict;
  2 +
  3 +
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict.SysDictDataDO;
  6 +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  7 +import org.apache.ibatis.annotations.Mapper;
  8 +
  9 +import java.util.Date;
  10 +
  11 +@Mapper
  12 +public interface SysDictDataMapper extends BaseMapperX<SysDictDataDO> {
  13 +
  14 + default SysDictDataDO selectByDictTypeAndValue(String dictType, String value) {
  15 + return selectOne(new QueryWrapper<SysDictDataDO>().eq("dict_type", dictType)
  16 + .eq("value", value));
  17 + }
  18 +
  19 + default int selectCountByDictType(String dictType) {
  20 + return selectCount("dict_type", dictType);
  21 + }
  22 +
  23 + default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
  24 + return selectOne(new QueryWrapper<SysDictDataDO>().select("id")
  25 + .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null;
  26 + }
  27 +
  28 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/package-info.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dal.mysql;
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/SysDictDataService.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dict;
  2 +
  3 +import cn.iocoder.yudao.framework.dict.core.service.DictDataFrameworkService;
  4 +
  5 +/**
  6 + * 字典数据 Service 接口
  7 + *
  8 + * @author ruoyi
  9 + */
  10 +public interface SysDictDataService extends DictDataFrameworkService {
  11 +
  12 + /**
  13 + * 初始化字典数据的本地缓存
  14 + */
  15 + void initLocalCache();
  16 +
  17 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/impl/SysDictDataServiceImpl.java 0 → 100644
  1 +package cn.iocoder.yudao.userserver.modules.system.dict.impl;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.dict.core.dto.DictDataRespDTO;
  5 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  6 +import cn.iocoder.yudao.userserver.modules.system.convert.dict.SysDictDataConvert;
  7 +import cn.iocoder.yudao.userserver.modules.system.dal.dataobject.dict.SysDictDataDO;
  8 +import cn.iocoder.yudao.userserver.modules.system.dal.mysql.dict.SysDictDataMapper;
  9 +import cn.iocoder.yudao.userserver.modules.system.dict.SysDictDataService;
  10 +import com.google.common.collect.ImmutableTable;
  11 +import lombok.extern.slf4j.Slf4j;
  12 +import org.springframework.scheduling.annotation.Scheduled;
  13 +import org.springframework.stereotype.Service;
  14 +
  15 +import javax.annotation.PostConstruct;
  16 +import javax.annotation.Resource;
  17 +import java.util.Comparator;
  18 +import java.util.Date;
  19 +import java.util.List;
  20 +
  21 +/**
  22 + * 字典数据 Service 实现类
  23 + *
  24 + * @author ruoyi
  25 + */
  26 +@Service
  27 +@Slf4j
  28 +public class SysDictDataServiceImpl implements SysDictDataService {
  29 +
  30 + /**
  31 + * 定时执行 {@link #schedulePeriodicRefresh()} 的周期
  32 + * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
  33 + */
  34 + private static final long SCHEDULER_PERIOD = 5 * 60 * 1000L;
  35 +
  36 + /**
  37 + * 字典数据缓存,第二个 key 使用 label
  38 + *
  39 + * key1:字典类型 dictType
  40 + * key2:字典标签 label
  41 + */
  42 + private ImmutableTable<String, String, SysDictDataDO> labelDictDataCache;
  43 + /**
  44 + * 字典数据缓存,第二个 key 使用 value
  45 + *
  46 + * key1:字典类型 dictType
  47 + * key2:字典值 value
  48 + */
  49 + private ImmutableTable<String, String, SysDictDataDO> valueDictDataCache;
  50 + /**
  51 + * 缓存字典数据的最大更新时间,用于后续的增量轮询,判断是否有更新
  52 + */
  53 + private volatile Date maxUpdateTime;
  54 +
  55 + @Resource
  56 + private SysDictDataMapper dictDataMapper;
  57 +
  58 + @Override
  59 + @PostConstruct
  60 + public synchronized void initLocalCache() {
  61 + // 获取字典数据列表,如果有更新
  62 + List<SysDictDataDO> dataList = this.loadDictDataIfUpdate(maxUpdateTime);
  63 + if (CollUtil.isEmpty(dataList)) {
  64 + return;
  65 + }
  66 +
  67 + // 构建缓存
  68 + ImmutableTable.Builder<String, String, SysDictDataDO> labelDictDataBuilder = ImmutableTable.builder();
  69 + ImmutableTable.Builder<String, String, SysDictDataDO> valueDictDataBuilder = ImmutableTable.builder();
  70 + dataList.forEach(dictData -> {
  71 + labelDictDataBuilder.put(dictData.getDictType(), dictData.getLabel(), dictData);
  72 + valueDictDataBuilder.put(dictData.getDictType(), dictData.getValue(), dictData);
  73 + });
  74 + labelDictDataCache = labelDictDataBuilder.build();
  75 + valueDictDataCache = valueDictDataBuilder.build();
  76 + assert dataList.size() > 0; // 断言,避免告警
  77 + maxUpdateTime = dataList.stream().max(Comparator.comparing(BaseDO::getUpdateTime)).get().getUpdateTime();
  78 + log.info("[initLocalCache][缓存字典数据,数量为:{}]", dataList.size());
  79 + }
  80 +
  81 + @Scheduled(fixedDelay = SCHEDULER_PERIOD, initialDelay = SCHEDULER_PERIOD)
  82 + public void schedulePeriodicRefresh() {
  83 + initLocalCache();
  84 + }
  85 +
  86 + /**
  87 + * 如果字典数据发生变化,从数据库中获取最新的全量字典数据。
  88 + * 如果未发生变化,则返回空
  89 + *
  90 + * @param maxUpdateTime 当前字典数据的最大更新时间
  91 + * @return 字典数据列表
  92 + */
  93 + private List<SysDictDataDO> loadDictDataIfUpdate(Date maxUpdateTime) {
  94 + // 第一步,判断是否要更新。
  95 + if (maxUpdateTime == null) { // 如果更新时间为空,说明 DB 一定有新数据
  96 + log.info("[loadDictDataIfUpdate][首次加载全量字典数据]");
  97 + } else { // 判断数据库中是否有更新的字典数据
  98 + if (!dictDataMapper.selectExistsByUpdateTimeAfter(maxUpdateTime)) {
  99 + return null;
  100 + }
  101 + log.info("[loadDictDataIfUpdate][增量加载全量字典数据]");
  102 + }
  103 + // 第二步,如果有更新,则从数据库加载所有字典数据
  104 + return dictDataMapper.selectList();
  105 + }
  106 +
  107 + @Override
  108 + public DictDataRespDTO getDictDataFromCache(String type, String value) {
  109 + return SysDictDataConvert.INSTANCE.convert02(valueDictDataCache.get(type, value));
  110 + }
  111 +
  112 + @Override
  113 + public DictDataRespDTO parseDictDataFromCache(String type, String label) {
  114 + return SysDictDataConvert.INSTANCE.convert02(labelDictDataCache.get(type, label));
  115 + }
  116 +
  117 + @Override
  118 + public List<DictDataRespDTO> listDictDatasFromCache(String type) {
  119 + return SysDictDataConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values());
  120 + }
  121 +
  122 +}
yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/package-info.java 0 → 100644
  1 +/**
  2 + * system 包下,我们放通用业务,支撑上层的核心业务。
  3 + * 例如说:用户、部门、权限、数据字典等等
  4 + *
  5 + * 缩写:sys
  6 + */
  7 +package cn.iocoder.yudao.userserver.modules.system;
yudao-user-server/src/main/resources/application-dev.yaml 0 → 100644
  1 +server:
  2 + port: 28080
  3 +
  4 +--- #################### 数据库相关配置 ####################
  5 +
  6 +spring:
  7 + # 数据源配置项
  8 + autoconfigure:
  9 + exclude:
  10 + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
  11 + datasource:
  12 + druid: # Druid 【监控】相关的全局配置
  13 + web-stat-filter:
  14 + enabled: true
  15 + stat-view-servlet:
  16 + enabled: true
  17 + allow: # 设置白名单,不填则允许所有访问
  18 + url-pattern: /druid/*
  19 + login-username: # 控制台管理用户名和密码
  20 + login-password:
  21 + filter:
  22 + stat:
  23 + enabled: true
  24 + log-slow-sql: true # 慢 SQL 记录
  25 + slow-sql-millis: 100
  26 + merge-sql: true
  27 + wall:
  28 + config:
  29 + multi-statement-allow: true
  30 + dynamic: # 多数据源配置
  31 + druid: # Druid 【连接池】相关的全局配置
  32 + initial-size: 5 # 初始连接数
  33 + min-idle: 10 # 最小连接池数量
  34 + max-active: 20 # 最大连接池数量
  35 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
  36 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
  37 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
  38 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
  39 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
  40 + test-while-idle: true
  41 + test-on-borrow: false
  42 + test-on-return: false
  43 + primary: master
  44 + datasource:
  45 + master:
  46 + name: ruoyi-vue-pro
  47 + url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
  48 + driver-class-name: com.mysql.jdbc.Driver
  49 + username: root
  50 + password: 3WLiVUBEwTbvAfsh
  51 + slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
  52 + name: ruoyi-vue-pro
  53 + url: jdbc:mysql://400-infra.server.iocoder.cn:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
  54 + driver-class-name: com.mysql.jdbc.Driver
  55 + username: root
  56 + password: 3WLiVUBEwTbvAfsh
  57 +
  58 + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  59 + redis:
  60 + host: 400-infra.server.iocoder.cn # 地址
  61 + port: 6379 # 端口
  62 + database: 1 # 数据库索引
  63 +
  64 +--- #################### 定时任务相关配置 ####################
  65 +
  66 +--- #################### 配置中心相关配置 ####################
  67 +
  68 +# Apollo 配置中心
  69 +apollo:
  70 + bootstrap:
  71 + enabled: true # 设置 Apollo 在启动阶段生效
  72 + eagerLoad:
  73 + enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置
  74 + jdbc: # 自定义的 JDBC 配置项,用于数据库的地址
  75 + dao: cn.iocoder.yudao.userserver.modules.infra.dal.mysql.config.InfConfigDAOImpl
  76 + url: ${spring.datasource.dynamic.datasource.master.url}
  77 + username: ${spring.datasource.dynamic.datasource.master.username}
  78 + password: ${spring.datasource.dynamic.datasource.master.password}
  79 +
  80 +--- #################### 服务保障相关配置 ####################
  81 +
  82 +# Lock4j 配置项
  83 +lock4j:
  84 + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
  85 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
  86 +
  87 +# Resilience4j 配置项
  88 +resilience4j:
  89 + ratelimiter:
  90 + instances:
  91 + backendA:
  92 + limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
  93 + limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500
  94 + timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
  95 + register-health-indicator: true # 是否注册到健康监测
  96 +
  97 +--- #################### 监控相关配置 ####################
  98 +
  99 +# Actuator 监控端点的配置项
  100 +management:
  101 + endpoints:
  102 + web:
  103 + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
  104 + exposure:
  105 + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
  106 +
  107 +# Spring Boot Admin 配置项
  108 +spring:
  109 + boot:
  110 + admin:
  111 + # Spring Boot Admin Client 客户端的相关配置
  112 + client:
  113 + url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址
  114 + instance:
  115 + prefer-ip: true # 注册实例时,优先使用 IP
  116 +
  117 +# 日志文件配置
  118 +logging:
  119 + file:
  120 + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
  121 +
  122 +--- #################### 芋道相关配置 ####################
  123 +
  124 +# 芋道配置项,设置当前项目所有自定义的配置
  125 +yudao:
  126 + security:
  127 + token-header: Authorization
  128 + token-secret: abcdefghijklmnopqrstuvwxyz
  129 + token-timeout: 1d
  130 + session-timeout: 30m
  131 + mock-enable: true
  132 + mock-secret: test
  133 + file:
  134 + base-path: http://api-dashboard.yudao.iocoder.cn${yudao.web.api-prefix}/infra/file/get/
  135 + xss:
  136 + enable: false
  137 + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系
  138 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
  139 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
  140 + demo: true # 开启演示模式
yudao-user-server/src/main/resources/application-local.yaml 0 → 100644
  1 +server:
  2 + port: 28080
  3 +
  4 +--- #################### 数据库相关配置 ####################
  5 +
  6 +spring:
  7 + # 数据源配置项
  8 + autoconfigure:
  9 + exclude:
  10 + - com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure # 排除 Druid 的自动配置,使用 dynamic-datasource-spring-boot-starter 配置多数据源
  11 + datasource:
  12 + druid: # Druid 【监控】相关的全局配置
  13 + web-stat-filter:
  14 + enabled: true
  15 + stat-view-servlet:
  16 + enabled: true
  17 + allow: # 设置白名单,不填则允许所有访问
  18 + url-pattern: /druid/*
  19 + login-username: # 控制台管理用户名和密码
  20 + login-password:
  21 + filter:
  22 + stat:
  23 + enabled: true
  24 + log-slow-sql: true # 慢 SQL 记录
  25 + slow-sql-millis: 100
  26 + merge-sql: true
  27 + wall:
  28 + config:
  29 + multi-statement-allow: true
  30 + dynamic: # 多数据源配置
  31 + druid: # Druid 【连接池】相关的全局配置
  32 + initial-size: 5 # 初始连接数
  33 + min-idle: 10 # 最小连接池数量
  34 + max-active: 20 # 最大连接池数量
  35 + max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
  36 + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
  37 + min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
  38 + max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
  39 + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
  40 + test-while-idle: true
  41 + test-on-borrow: false
  42 + test-on-return: false
  43 + primary: master
  44 + datasource:
  45 + master:
  46 + name: ruoyi-vue-pro
  47 + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
  48 + driver-class-name: com.mysql.jdbc.Driver
  49 + username: root
  50 + password: 123456
  51 + slave: # 模拟从库,可根据自己需要修改
  52 + name: ruoyi-vue-pro
  53 + url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT
  54 + driver-class-name: com.mysql.jdbc.Driver
  55 + username: root
  56 + password: 123456
  57 +
  58 + # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
  59 + redis:
  60 + host: 127.0.0.1 # 地址
  61 + port: 6379 # 端口
  62 + database: 0 # 数据库索引
  63 +
  64 +--- #################### 定时任务相关配置 ####################
  65 +
  66 +--- #################### 配置中心相关配置 ####################
  67 +
  68 +# Apollo 配置中心
  69 +apollo:
  70 + bootstrap:
  71 + enabled: true # 设置 Apollo 在启动阶段生效
  72 + eagerLoad:
  73 + enabled: true # 设置 Apollo 在日志初始化前生效,可以实现日志的动态级别配置
  74 + jdbc: # 自定义的 JDBC 配置项,用于数据库的地址
  75 + dao: cn.iocoder.yudao.userserver.modules.infra.dal.mysql.config.InfConfigDAOImpl
  76 + url: ${spring.datasource.dynamic.datasource.master.url}
  77 + username: ${spring.datasource.dynamic.datasource.master.username}
  78 + password: ${spring.datasource.dynamic.datasource.master.password}
  79 +
  80 +--- #################### 服务保障相关配置 ####################
  81 +
  82 +# Lock4j 配置项
  83 +lock4j:
  84 + acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
  85 + expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
  86 +
  87 +# Resilience4j 配置项
  88 +resilience4j:
  89 + ratelimiter:
  90 + instances:
  91 + backendA:
  92 + limit-for-period: 1 # 每个周期内,允许的请求数。默认为 50
  93 + limit-refresh-period: 60s # 每个周期的时长,单位:微秒。默认为 500
  94 + timeout-duration: 1s # 被限流时,阻塞等待的时长,单位:微秒。默认为 5s
  95 + register-health-indicator: true # 是否注册到健康监测
  96 +
  97 +--- #################### 监控相关配置 ####################
  98 +
  99 +# Actuator 监控端点的配置项
  100 +management:
  101 + endpoints:
  102 + web:
  103 + base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
  104 + exposure:
  105 + include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
  106 +
  107 +# Spring Boot Admin 配置项
  108 +spring:
  109 + boot:
  110 + admin:
  111 + # Spring Boot Admin Client 客户端的相关配置
  112 + client:
  113 + url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址
  114 + instance:
  115 + prefer-ip: true # 注册实例时,优先使用 IP
  116 + # Spring Boot Admin Server 服务端的相关配置
  117 + context-path: /admin # 配置 Spring
  118 +
  119 +# 日志文件配置
  120 +logging:
  121 + file:
  122 + name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
  123 +
  124 +--- #################### 芋道相关配置 ####################
  125 +
  126 +# 芋道配置项,设置当前项目所有自定义的配置
  127 +yudao:
  128 + security:
  129 + token-header: Authorization
  130 + token-secret: abcdefghijklmnopqrstuvwxyz
  131 + token-timeout: 1d
  132 + session-timeout: 30m
  133 + mock-enable: true
  134 + mock-secret: test
  135 + file:
  136 + base-path: http://127.0.0.1:${server.port}${yudao.web.api-prefix}/infra/file/get/
  137 + xss:
  138 + enable: false
  139 + exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系
  140 + - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
  141 + - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
  142 + demo: false # 关闭演示模式
yudao-user-server/src/main/resources/application.yaml 0 → 100644
  1 +spring:
  2 + application:
  3 + name: yudao-user-server
  4 +
  5 + profiles:
  6 + active: local
  7 +
  8 + # Servlet 配置
  9 + servlet:
  10 + # 文件上传相关配置项
  11 + multipart:
  12 + max-file-size: 16MB # 单个文件大小
  13 + max-request-size: 32MB # 设置总上传的文件大小
  14 +
  15 + # Jackson 配置项
  16 + jackson:
  17 + serialization:
  18 + write-dates-as-timestamps: true # 设置 Date 的格式,使用时间戳
  19 + write-date-timestamps-as-nanoseconds: false # 设置不使用 nanoseconds 的格式。例如说 1611460870.401,而是直接 1611460870401
  20 + write-durations-as-timestamps: true # 设置 Duration 的格式,使用时间戳
  21 + fail-on-empty-beans: false # 允许序列化无属性的 Bean
  22 +
  23 +# MyBatis Plus 的配置项
  24 +mybatis-plus:
  25 + configuration:
  26 + map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
  27 + log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
  28 + global-config:
  29 + db-config:
  30 + id-type: AUTO # 自增 ID
  31 + logic-delete-value: 1 # 逻辑已删除值(默认为 1)
  32 + logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
  33 + mapper-locations: classpath*:mapper/*.xml
  34 + type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject
  35 +
  36 +--- #################### 芋道相关配置 ####################
  37 +
  38 +yudao:
  39 + info:
  40 + version: 1.0.0
  41 + base-package: cn.iocoder.yudao.userserver
  42 + web:
  43 + api-prefix: /api
  44 + controller-package: ${yudao.info.base-package}
  45 + swagger:
  46 + title: 管理后台
  47 + description: 提供管理员管理的所有功能
  48 + version: ${yudao.info.version}
  49 + base-package: ${yudao.info.base-package}.modules
  50 + captcha:
  51 + timeout: 5m
  52 + width: 160
  53 + height: 60
  54 + codegen:
  55 + base-package: ${yudao.info.base-package}
  56 + db-schemas: ${spring.datasource.dynamic.datasource.master.name}
  57 + error-code: # 错误码相关配置项
  58 + constants-class-list:
  59 +
  60 +debug: false
yudao-user-server/src/main/resources/banner.txt 0 → 100644
  1 +芋道源码 http://www.iocoder.cn
  2 +Application Version: ${yudao.info.version}
  3 +Spring Boot Version: ${spring-boot.version}
  4 +
  5 +.__ __. ______ .______ __ __ _______
  6 +| \ | | / __ \ | _ \ | | | | / _____|
  7 +| \| | | | | | | |_) | | | | | | | __
  8 +| . ` | | | | | | _ < | | | | | | |_ |
  9 +| |\ | | `--' | | |_) | | `--' | | |__| |
  10 +|__| \__| \______/ |______/ \______/ \______|
  11 +
  12 +███╗ ██╗ ██████╗ ██████╗ ██╗ ██╗ ██████╗
  13 +████╗ ██║██╔═══██╗ ██╔══██╗██║ ██║██╔════╝
  14 +██╔██╗ ██║██║ ██║ ██████╔╝██║ ██║██║ ███╗
  15 +██║╚██╗██║██║ ██║ ██╔══██╗██║ ██║██║ ██║
  16 +██║ ╚████║╚██████╔╝ ██████╔╝╚██████╔╝╚██████╔╝
  17 +╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝
yudao-user-server/src/main/resources/logback-spring.xml 0 → 100644
  1 +<configuration>
  2 + <!-- 引用 Spring Boot 的 logback 基础配置 -->
  3 + <include resource="org/springframework/boot/logging/logback/defaults.xml" />
  4 + <!-- 变量 yudao.info.base-package,基础业务包 -->
  5 + <springProperty scope="context" name="yudao.info.base-package" source="yudao.info.base-package"/>
  6 + <!-- 格式化输出:%d 表示日期,%X{tid} SkWalking 链路追踪编号,%thread 表示线程名,%-5level:级别从左显示 5 个字符宽度,%msg:日志消息,%n是换行符 -->
  7 + <property name="PATTERN_DEFAULT" value="%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%thread] [%tid] %-40.40logger{39} : %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}"/>
  8 +
  9 + <!-- 控制台 Appender -->
  10 + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">     
  11 + <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  12 + <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
  13 + <pattern>${PATTERN_DEFAULT}</pattern>
  14 + </layout>
  15 + </encoder>
  16 + </appender>
  17 +
  18 + <!-- 文件 Appender -->
  19 + <!-- 参考 Spring Boot 的 file-appender.xml 编写 -->
  20 + <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
  21 + <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  22 + <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
  23 + <pattern>${PATTERN_DEFAULT}</pattern>
  24 + </layout>
  25 + </encoder>
  26 + <!-- 日志文件名 -->
  27 + <file>${LOG_FILE}</file>
  28 + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
  29 + <!-- 滚动后的日志文件名 -->
  30 + <fileNamePattern>${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz}</fileNamePattern>
  31 + <!-- 启动服务时,是否清理历史日志,一般不建议清理 -->
  32 + <cleanHistoryOnStart>${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false}</cleanHistoryOnStart>
  33 + <!-- 日志文件,到达多少容量,进行滚动 -->
  34 + <maxFileSize>${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB}</maxFileSize>
  35 + <!-- 日志文件的总大小,0 表示不限制 -->
  36 + <totalSizeCap>${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0}</totalSizeCap>
  37 + <!-- 日志文件的保留天数 -->
  38 + <maxHistory>${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30}</maxHistory>
  39 + </rollingPolicy>
  40 + </appender>
  41 + <!-- 异步写入日志,提升性能 -->
  42 + <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
  43 + <!-- 不丢失日志。默认的,如果队列的 80% 已满,则会丢弃 TRACT、DEBUG、INFO 级别的日志 -->
  44 + <discardingThreshold>0</discardingThreshold>
  45 + <!-- 更改默认的队列的深度,该值会影响性能。默认值为 256 -->
  46 + <queueSize>256</queueSize>
  47 + <appender-ref ref="FILE"/>
  48 + </appender>
  49 +
  50 + <!-- SkyWalking GRPC 日志收集,实现日志中心。注意:SkyWalking 8.4.0 版本开始支持 -->
  51 + <appender name="GRPC" class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.log.GRPCLogClientAppender">
  52 + <encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
  53 + <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
  54 + <pattern>${PATTERN_DEFAULT}</pattern>
  55 + </layout>
  56 + </encoder>
  57 + </appender>
  58 +
  59 + <!-- 本地环境 -->
  60 + <springProfile name="local">
  61 + <root level="INFO">
  62 + <appender-ref ref="STDOUT"/>
  63 + <appender-ref ref="GRPC"/> <!-- 本地环境下,如果不想接入 SkyWalking 日志服务,可以注释掉本行 -->
  64 + <appender-ref ref="ASYNC"/> <!-- 本地环境下,如果不想打印日志,可以注释掉本行 -->
  65 + </root>
  66 + </springProfile>
  67 + <!-- 其它环境 -->
  68 + <springProfile name="default">
  69 + <root level="INFO">
  70 + <appender-ref ref="STDOUT"/>
  71 + <appender-ref ref="ASYNC"/>
  72 + <appender-ref ref="GRPC"/>
  73 + </root>
  74 + </springProfile>
  75 +
  76 +</configuration>