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