diff --git a/pom.xml b/pom.xml index 1962a92fd..84e886116 100644 --- a/pom.xml +++ b/pom.xml @@ -11,6 +11,7 @@ yudao-dependencies yudao-framework yudao-admin-server + yudao-user-server ${artifactId} @@ -18,7 +19,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.0.0 + 1.1.0-snapshot 1.8 ${java.version} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java new file mode 100644 index 000000000..8bb4bc9a6 --- /dev/null +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java @@ -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.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; + } + +} diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java index 8fae484ac..aba6382d2 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java +++ b/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 { @Override @Async public Future createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) { - // 插入 InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO); int insert = apiAccessLogMapper.insert(apiAccessLog); - return new AsyncResult<>(insert == 1); + return new AsyncResult<>(insert > 1); } @Override diff --git a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java index df54e7980..6de3f6b0c 100644 --- a/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java +++ b/yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.java @@ -167,7 +167,7 @@ public class SysUserController { @PreAuthorize("@ss.hasPermission('system:user:import')") public CommonResult importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { - List list = ExcelUtils.raed(file, SysUserImportExcelVO.class); + List list = ExcelUtils.read(file, SysUserImportExcelVO.class); return success(userService.importUsers(list, updateSupport)); } diff --git a/yudao-admin-ui/src/views/system/role/index.vue b/yudao-admin-ui/src/views/system/role/index.vue index 0ced5d8df..7ab00f82b 100644 --- a/yudao-admin-ui/src/views/system/role/index.vue +++ b/yudao-admin-ui/src/views/system/role/index.vue @@ -66,7 +66,7 @@ - diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 42adcdf8a..0758e5e81 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 1.0.0 + 1.1.0-snapshot 2.4.5 diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index 0e9bfb4de..67d558f6b 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/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 { response.setContentType("application/vnd.ms-excel;charset=UTF-8"); } - public static List raed(MultipartFile file, Class head) throws IOException { + public static List read(MultipartFile file, Class head) throws IOException { return EasyExcel.read(file.getInputStream(), head, null) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .doReadAllSync(); diff --git a/yudao-framework/yudao-spring-boot-starter-security/pom.xml b/yudao-framework/yudao-spring-boot-starter-security/pom.xml index 4a2b1878a..670a09774 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-security/pom.xml @@ -19,7 +19,12 @@ cn.iocoder.boot yudao-common - ${revision} + + + + + org.springframework.boot + spring-boot-starter-aop diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java index b9e0f34fc..94b3ecd14 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoSecurityAutoConfiguration.java @@ -1,5 +1,6 @@ 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.handler.AccessDeniedHandlerImpl; import cn.iocoder.yudao.framework.security.core.handler.AuthenticationEntryPointImpl; @@ -32,6 +33,14 @@ public class YudaoSecurityAutoConfiguration { @Resource private SecurityProperties securityProperties; + /** + * 处理用户未登陆拦截的切面的 Bean + */ + @Bean + public PreAuthenticatedAspect preAuthenticatedAspect() { + return new PreAuthenticatedAspect(); + } + /** * 认证失败处理类 Bean */ diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java index 3d678eefd..893d2b0f5 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/config/YudaoWebSecurityConfigurerAdapter.java +++ b/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; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpMethod; 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.method.configuration.EnableGlobalMethodSecurity; 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.configurers.ExpressionUrlAuthorizationConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @@ -41,9 +43,6 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap @Resource private WebProperties webProperties; - @Value("${spring.boot.admin.context-path:''}") - private String adminSeverContextPath; - /** * 自定义用户【认证】逻辑 */ @@ -74,6 +73,13 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap */ @Resource private JwtAuthenticationTokenFilter authenticationTokenFilter; + /** + * 自定义的权限映射 Bean + * + * @see #configure(HttpSecurity) + */ + @Resource + private Customizer.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer; /** * 由于 Spring Security 创建 AuthenticationManager 对象时,没声明 @Bean 注解,导致无法被注入 @@ -121,15 +127,16 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap .csrf().disable() // 基于 token 机制,所以不需要 Session .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() + .headers().frameOptions().disable().and() // 一堆自定义的 Spring Security 处理器 .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) .accessDeniedHandler(accessDeniedHandler).and() - // 设置每个请求的权限 - .authorizeRequests() + .logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出 + + // 设置每个请求的权限 ①:全局共享规则 + httpSecurity.authorizeRequests() // 登陆的接口,可匿名访问 .antMatchers(api("/login")).anonymous() - // 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去 - .antMatchers(api("/system/captcha/**")).anonymous() // 静态资源,可匿名访问 .antMatchers(HttpMethod.GET, "/*.html", "/**/*.html", "/**/*.css", "/**/*.js").permitAll() // 文件的获取接口,可匿名访问 @@ -139,21 +146,15 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap .antMatchers("/swagger-resources/**").anonymous() .antMatchers("/webjars/**").anonymous() .antMatchers("/*/api-docs").anonymous() - // Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去 - .antMatchers(adminSeverContextPath).anonymous() - .antMatchers(adminSeverContextPath + "/**").anonymous() // Spring Boot Actuator 的安全配置 .antMatchers("/actuator").anonymous() .antMatchers("/actuator/**").anonymous() - // Druid 监控 TODO 芋艿:需要抽象出去 + // Druid 监控 TODO 芋艿:等对接了 druid admin 后,在调整下。 .antMatchers("/druid/**").anonymous() - // 短信回调 API TODO 芋艿:需要抽象出去 - .antMatchers(api("/system/sms/callback/**")).anonymous() - // 除上面外的所有请求全部需要鉴权认证 - .anyRequest().authenticated() - .and() - .headers().frameOptions().disable(); - httpSecurity.logout().logoutUrl(api("/logout")).logoutSuccessHandler(logoutSuccessHandler); + // 设置每个请求的权限 ②:每个项目的自定义规则 + .and().authorizeRequests(authorizeRequestsCustomizer) + // 设置每个请求的权限 ③:兜底规则,必须认证 + .authorizeRequests().anyRequest().authenticated(); // 添加 JWT Filter httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); } diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/PreAuthenticated.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/PreAuthenticated.java new file mode 100644 index 000000000..901936dd7 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/annotations/PreAuthenticated.java @@ -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 { +} diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/aop/PreAuthenticatedAspect.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/aop/PreAuthenticatedAspect.java new file mode 100644 index 000000000..808afc393 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/aop/PreAuthenticatedAspect.java @@ -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(); + } + +} diff --git a/yudao-user-server/pom.xml b/yudao-user-server/pom.xml new file mode 100644 index 000000000..4bd1c5857 --- /dev/null +++ b/yudao-user-server/pom.xml @@ -0,0 +1,111 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + 4.0.0 + + yudao-user-server + jar + + yudao-admin-server + 用户前台 Server,提供其 API 接口 + https://github.com/YunaiV/ruoyi-vue-pro + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-sms + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-config + + + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mq + + + + + cn.iocoder.boot + yudao-spring-boot-starter-protection + + + + + cn.iocoder.boot + yudao-spring-boot-starter-monitor + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + test + + + + + + + + + ${artifactId} + + + + org.springframework.boot + spring-boot-maven-plugin + + true + + + + + repackage + + + + + + + + diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java new file mode 100644 index 000000000..edfbc63dc --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/UserServerApplication.java @@ -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); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java new file mode 100644 index 000000000..ed271220c --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/config/AsyncConfiguration.java @@ -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 { +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java new file mode 100644 index 000000000..a06351522 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/package-info.java @@ -0,0 +1,4 @@ +/** + * 异步执行,基于 Spring @Async 实现 + */ +package cn.iocoder.yudao.userserver.framework.async; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md new file mode 100644 index 000000000..5822b838c --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/async/《芋道 Spring Boot 异步任务入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java new file mode 100644 index 000000000..db25ed2a4 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于整个 yudao-user-server 的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.userserver.framework; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/security/SecurityConfiguration.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/security/SecurityConfiguration.java new file mode 100644 index 000000000..e43f5e3e6 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/framework/security/SecurityConfiguration.java @@ -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.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() { + return registry -> { + registry.antMatchers(api("/**")).anonymous(); // 默认 API 都是用户可访问 + }; + } + + private String api(String url) { + return webProperties.getApiPrefix() + url; + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/controller/HelloController.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/controller/HelloController.java new file mode 100644 index 000000000..6a3270fc2 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/controller/HelloController.java @@ -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"; + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiAccessLogConvert.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiAccessLogConvert.java new file mode 100644 index 000000000..3ddbbf65b --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiAccessLogConvert.java @@ -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); + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiErrorLogConvert.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiErrorLogConvert.java new file mode 100644 index 000000000..51c6c3eef --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/logger/InfApiErrorLogConvert.java @@ -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); + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/package-info.java new file mode 100644 index 000000000..d1aa5643a --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 POJO 类的实体转换 + * + * 目前使用 MapStruct 框架 + */ +package cn.iocoder.yudao.userserver.modules.infra.convert; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md new file mode 100644 index 000000000..8153487b7 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/convert/《芋道 Spring Boot 对象转换 MapStruct 入门》.md @@ -0,0 +1 @@ + diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java new file mode 100644 index 000000000..a9ab432d6 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/config/InfConfigDO.java @@ -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; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java new file mode 100644 index 000000000..604a888c2 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/file/InfFileDO.java @@ -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; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java new file mode 100644 index 000000000..2548ec469 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiAccessLogDO.java @@ -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; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java new file mode 100644 index 000000000..6ed2b3150 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java @@ -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; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java new file mode 100644 index 000000000..5453c05a2 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/config/InfConfigDAOImpl.java @@ -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 selectList() { + return jdbcTemplate.query("SELECT `key`, `value`, update_time, deleted FROM inf_config", new BeanPropertyRowMapper<>(ConfigRespDTO.class)); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java new file mode 100644 index 000000000..1db7d311b --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/file/InfFileMapper.java @@ -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 { + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiAccessLogMapper.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiAccessLogMapper.java new file mode 100644 index 000000000..cf7f6e92c --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiAccessLogMapper.java @@ -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 { +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java new file mode 100644 index 000000000..9e9124267 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/dal/mysql/logger/InfApiErrorLogMapper.java @@ -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 { +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java new file mode 100644 index 000000000..618d5d9be --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/logger/InfApiErrorLogProcessStatusEnum.java @@ -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; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/package-info.java new file mode 100644 index 000000000..3a03078cb --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/enums/package-info.java @@ -0,0 +1,4 @@ +/** + * 占位类,可以无视 + */ +package cn.iocoder.yudao.userserver.modules.infra.enums; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java new file mode 100644 index 000000000..fdf89894e --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/package-info.java @@ -0,0 +1,7 @@ +/** + * infra 包下,我们放基础设施的运维与管理,支撑上层的通用与核心业务。 + * 例如说:定时任务的管理、服务器的信息等等 + * + * 缩写:inf + */ +package cn.iocoder.yudao.userserver.modules.infra; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/SysAuthService.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/SysAuthService.java new file mode 100644 index 000000000..e9b530904 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/SysAuthService.java @@ -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 { + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/impl/SysAuthServiceImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/impl/SysAuthServiceImpl.java new file mode 100644 index 000000000..6ab606c59 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/auth/impl/SysAuthServiceImpl.java @@ -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; + } +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiAccessLogService.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiAccessLogService.java new file mode 100644 index 000000000..bcc4f3a97 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiAccessLogService.java @@ -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 { + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiErrorLogService.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiErrorLogService.java new file mode 100644 index 000000000..2c221604e --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/InfApiErrorLogService.java @@ -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 { + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java new file mode 100644 index 000000000..1b0f2611c --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiAccessLogServiceImpl.java @@ -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 createApiAccessLogAsync(ApiAccessLogCreateDTO createDTO) { + InfApiAccessLogDO apiAccessLog = InfApiAccessLogConvert.INSTANCE.convert(createDTO); + int insert = apiAccessLogMapper.insert(apiAccessLog); + return new AsyncResult<>(insert > 1); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java new file mode 100644 index 000000000..05bddb7d9 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/infra/service/logger/impl/InfApiErrorLogServiceImpl.java @@ -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 createApiErrorLogAsync(ApiErrorLogCreateDTO createDTO) { + InfApiErrorLogDO apiErrorLog = InfApiErrorLogConvert.INSTANCE.convert(createDTO); + apiErrorLog.setProcessStatus(InfApiErrorLogProcessStatusEnum.INIT.getStatus()); + int insert = apiErrorLogMapper.insert(apiErrorLog); + return new AsyncResult<>(insert == 1); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java new file mode 100644 index 000000000..430f6c945 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.userserver.modules; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/dict/SysDictDataConvert.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/dict/SysDictDataConvert.java new file mode 100644 index 000000000..02155f698 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/dict/SysDictDataConvert.java @@ -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 convertList03(Collection list); + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/package-info.java new file mode 100644 index 000000000..65ad8dc88 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/convert/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.userserver.modules.system.convert; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/dict/SysDictDataDO.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/dict/SysDictDataDO.java new file mode 100644 index 000000000..eacec758f --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/dict/SysDictDataDO.java @@ -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; + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/package-info.java new file mode 100644 index 000000000..0c99dcc95 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/dataobject/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.userserver.modules.system.dal.dataobject; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/dict/SysDictDataMapper.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/dict/SysDictDataMapper.java new file mode 100644 index 000000000..928a53f7d --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/dict/SysDictDataMapper.java @@ -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 { + + default SysDictDataDO selectByDictTypeAndValue(String dictType, String value) { + return selectOne(new QueryWrapper().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().select("id") + .gt("update_time", maxUpdateTime).last("LIMIT 1")) != null; + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/package-info.java new file mode 100644 index 000000000..a1bdeadcd --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dal/mysql/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.userserver.modules.system.dal.mysql; diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/SysDictDataService.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/SysDictDataService.java new file mode 100644 index 000000000..2efffe19e --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/SysDictDataService.java @@ -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(); + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/impl/SysDictDataServiceImpl.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/impl/SysDictDataServiceImpl.java new file mode 100644 index 000000000..6e062eca7 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/dict/impl/SysDictDataServiceImpl.java @@ -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 labelDictDataCache; + /** + * 字典数据缓存,第二个 key 使用 value + * + * key1:字典类型 dictType + * key2:字典值 value + */ + private ImmutableTable valueDictDataCache; + /** + * 缓存字典数据的最大更新时间,用于后续的增量轮询,判断是否有更新 + */ + private volatile Date maxUpdateTime; + + @Resource + private SysDictDataMapper dictDataMapper; + + @Override + @PostConstruct + public synchronized void initLocalCache() { + // 获取字典数据列表,如果有更新 + List dataList = this.loadDictDataIfUpdate(maxUpdateTime); + if (CollUtil.isEmpty(dataList)) { + return; + } + + // 构建缓存 + ImmutableTable.Builder labelDictDataBuilder = ImmutableTable.builder(); + ImmutableTable.Builder 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 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 listDictDatasFromCache(String type) { + return SysDictDataConvert.INSTANCE.convertList03(labelDictDataCache.row(type).values()); + } + +} diff --git a/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/package-info.java b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/package-info.java new file mode 100644 index 000000000..89fa9c162 --- /dev/null +++ b/yudao-user-server/src/main/java/cn/iocoder/yudao/userserver/modules/system/package-info.java @@ -0,0 +1,7 @@ +/** + * system 包下,我们放通用业务,支撑上层的核心业务。 + * 例如说:用户、部门、权限、数据字典等等 + * + * 缩写:sys + */ +package cn.iocoder.yudao.userserver.modules.system; diff --git a/yudao-user-server/src/main/resources/application-dev.yaml b/yudao-user-server/src/main/resources/application-dev.yaml new file mode 100644 index 000000000..c21eeec80 --- /dev/null +++ b/yudao-user-server/src/main/resources/application-dev.yaml @@ -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 # 开启演示模式 diff --git a/yudao-user-server/src/main/resources/application-local.yaml b/yudao-user-server/src/main/resources/application-local.yaml new file mode 100644 index 000000000..62a53cf07 --- /dev/null +++ b/yudao-user-server/src/main/resources/application-local.yaml @@ -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 # 关闭演示模式 diff --git a/yudao-user-server/src/main/resources/application.yaml b/yudao-user-server/src/main/resources/application.yaml new file mode 100644 index 000000000..573a9a5e1 --- /dev/null +++ b/yudao-user-server/src/main/resources/application.yaml @@ -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 diff --git a/yudao-user-server/src/main/resources/banner.txt b/yudao-user-server/src/main/resources/banner.txt new file mode 100644 index 000000000..39a441d7d --- /dev/null +++ b/yudao-user-server/src/main/resources/banner.txt @@ -0,0 +1,17 @@ +芋道源码 http://www.iocoder.cn +Application Version: ${yudao.info.version} +Spring Boot Version: ${spring-boot.version} + +.__ __. ______ .______ __ __ _______ +| \ | | / __ \ | _ \ | | | | / _____| +| \| | | | | | | |_) | | | | | | | __ +| . ` | | | | | | _ < | | | | | | |_ | +| |\ | | `--' | | |_) | | `--' | | |__| | +|__| \__| \______/ |______/ \______/ \______| + +███╗ ██╗ ██████╗ ██████╗ ██╗ ██╗ ██████╗ +████╗ ██║██╔═══██╗ ██╔══██╗██║ ██║██╔════╝ +██╔██╗ ██║██║ ██║ ██████╔╝██║ ██║██║ ███╗ +██║╚██╗██║██║ ██║ ██╔══██╗██║ ██║██║ ██║ +██║ ╚████║╚██████╔╝ ██████╔╝╚██████╔╝╚██████╔╝ +╚═╝ ╚═══╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚═════╝ diff --git a/yudao-user-server/src/main/resources/logback-spring.xml b/yudao-user-server/src/main/resources/logback-spring.xml new file mode 100644 index 000000000..5bc181fd2 --- /dev/null +++ b/yudao-user-server/src/main/resources/logback-spring.xml @@ -0,0 +1,76 @@ + + + + + + + + + +       + + + ${PATTERN_DEFAULT} + + + + + + + + + + ${PATTERN_DEFAULT} + + + + ${LOG_FILE} + + + ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} + + ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} + + ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} + + ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} + + ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} + + + + + + 0 + + 256 + + + + + + + + ${PATTERN_DEFAULT} + + + + + + + + + + + + + + + + + + + + + +