Skip to content
This repository has been archived by the owner on Jun 26, 2023. It is now read-only.

vaulka/java-enhancement-kit

Repository files navigation

Spring logo

Java 增强套件 旨在减少重复造轮子以及封装一些实用功能,让开发者专注于业务,提高工作效率,值得一试。

包含组件

kit-captcha 验证码模块

captcha-input-char 输入型字符 字符验证码模块

模块 介绍
captcha-input-char-utils 输入型字符 验证码 Utils 模块
spring-boot-starter-captcha-input-char 输入型字符 验证码 Spring Boot Starter 模块

captcha-input-math 输入型算数 字符验证码模块

模块 介绍
captcha-input-math-utils 输入型算数 验证码 Utils 模块
spring-boot-starter-captcha-input-math 输入型算数 验证码 Spring Boot Starter 模块

kit-desensitization 数据脱敏模块

模块 介绍
desensitization-annotation 数据脱敏 Annotation 模块
desensitization-utils 数据脱敏 Utils 模块
spring-boot-starter-desensitization 数据脱敏 Spring Boot Starter 模块

kit-doc 文档模块

springdoc SringDoc 模块

模块 介绍
spring-boot-springdoc-common SpringDoc Common Spring Boot 模块
spring-boot-starter-springdoc SpringDoc Spring Boot Starter 模块
spring-boot-starter-springdoc-knife4j SpringDoc Knife4j Spring Boot Starter 模块
spring-boot-starter-webflux-springdoc WebFlux SpringDoc Spring Boot Starter 模块
spring-boot-starter-webflux-springdoc-knife4j WebFlux SpringDoc Knife4j Spring Boot Starter 模块

springfox SpringFox 模块

模块 介绍
spring-boot-starter-springfox SpringDoc Spring Boot Starter 模块
spring-boot-starter-springfox-knife4j SpringDoc Knife4j Spring Boot Starter 模块

kit-excel 导入/导出 Excel 模块

模块 介绍
excel-utils Excel Utils 模块
spring-boot-starter-excel Excel Spring Boot Starter 模块

kit-ip IP 模块

模块 介绍
spring-boot-starter-ip IP Spring Boot Starter 模块

kit-sms 短信模块

aliyun-sms 阿里云短信模块

模块 介绍
aliyun-sms-utils 阿里云短信 Utils 模块
spring-boot-starter-aliyun-sms 阿里云短信 Spring Boot Starter 模块

tencent-sms 腾讯云短信模块

模块 介绍
tencent-sms-utils 腾讯云短信 Utils 模块
spring-boot-starter-tencent-sms 腾讯云短信 Spring Boot Starter 模块

kit-spring-boot Spring Boot 增强模块

模块 介绍
spring-boot-starter-cache-redis Redis 缓存 Spring Boot Starter 模块
spring-boot-starter-common 公共 Spring Boot Starter 模块
spring-boot-starter-core Core Spring Boot Starter 模块
spring-boot-starter-dynamic-datasource 动态数据源 Spring Boot Starter 模块
spring-boot-starter-global-response 全局响应 Spring Boot Starter 模块
spring-boot-starter-trace 链路 Spring Boot Starter 模块
spring-boot-starter-web Web Spring Boot Starter 模块
spring-boot-starter-web-core Web Core Spring Boot Starter 模块

kit-storage 云存储模块

模块 介绍
spring-boot-storage 云存储 Spring Boot 模块

minio MinIO 云存储模块

模块 介绍
spring-boot-starter-storage-minio 云存储 MinIO Spring Boot Starter 模块
storage-minio-utils 云存储 MinIO Utils 模块

oss OSS 云存储模块

模块 介绍
spring-boot-starter-aliyun-oss 云存储 OSS Spring Boot Starter 模块
storage-aliyun-utils 云存储 OSS Utils 模块

kit-system 系统模块

模块 介绍
system-utils 系统 Utils 模块

kit-tree 树形结构模块

模块 介绍
tree-utils 树形结构 Utils 模块

kit-type-parser 类型解析模块

模块 介绍
type-parser-utils 类型解析 Utils 模块

kit-validation 校验模块

模块 介绍
validation-utils 校验 Utils 模块

使用

版本号说明

版本由:项目版本号-Spring Boot 版本 组成。

最新版本请点击 Maven Repository 查阅

Maven 依赖

<dependency>
    <groupId>com.pongsky.kit</groupId>
    <artifactId>spring-boot-starter-captcha-input-math</artifactId>
    <version>${latestVersion}</version>
</dependency>

Gradle 依赖

implementation "com.pongsky.kit:spring-boot-starter-captcha-input-math:$latestVersion"

其他功能特点(TODO,后续功能将拆模块移除优化)

  • config-core

    • Swagger 配置(自动装配)
    • 全局日志链路追踪(需配合 bootstrap.yml)
    • 异步配置(增强日志链路追踪)
    • Quartz 配置(增强日志链路追踪)
  • config-web

    • Feign 调用日志打印

前置条件

  • 需引入 spring-boot-starter-data-redis 依赖并配置相关 yml 信息
  • 需配置 yml 信息,信息如下:
参数 示例 说明
application.name @name@ 应用名称。
建议读取项目名称,并在 bootstrap.yml 中配置
application.module gateway 模块名称。
建议在 application.yml 中配置
application.version @version@ 版本号。
建议读取项目版本号,并在 bootstrap.yml 中配置
application.formatted-version ${application.name}-${application.module}-${application.version} 打印版本号格式。
建议在 application.yml 中配置
spring.profiles.active dev 环境,localdevbetaprod
建议在 bootstrap.yml 中配置
spring.application.name ${application.name}-${application.module} 应用名称。
建议在 application.yml 中配置

功能配置

全局实例ID

在 yml 或 @Value 中可直接引用 ${brokerId} 获取当前实例ID。

brokerId 由 系统 HostName、HostAddress 信息进行 MD5 后组成。

该场景适用于容器部署,每个实例的 HostName、HostAddress 组成唯一。

全局日志链路追踪

日志打印信息需添加打印 X-Trace-Id 参数。

logging:
  pattern:
    console: ${CONSOLE_LOG_PATTERN:%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}  %-5.5L{5}){cyan} %clr([%39X{X-Trace-Id}]){yellow} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}} # 控制台日志打印格式

Feign 日志打印

    @Bean
    public feign.Logger logger() {
        return new Slf4jLogger();
    }
logging:
  level:
    feign.Logger: debug # Feign 日志打印
feign:
  client:
    config:
      default:
        loggerLevel: basic # Feign 日志打印等级

模块建议

按照此信息进行分模块,配合此套件能获得最佳的体验~

在多模块项目中建议按如下分包:

${project}:项目名。

${service}:服务名。

  • ${project}-common-entity
    • 依赖 ${project}-common-utils
  • ${project}-common-utils
    • 依赖 com.pongsky.kit:common-utils
  • ${project}-config-core
    • 依赖 ${project}-common-entity
    • 依赖 com.pongsky.kit:config-core
  • ${project}-config-core
    • 依赖 ${project}-config-core
    • 依赖 com.pongsky.kit:config-web
  • ${project}-service-${service}
    • 依赖 com.pongsky.kit:config-core / com.pongsky.kit:config-web

代码、分包建议

按照此信息进行代码实装、分包,配合此套件能获得最佳的体验~

${basePackage}:基础项目包,譬如 com.pongsky.kit

${project}-config-core

包:${basePackage}.config

譬如:com.pongsky.kit.config

BaseConfig

/**
 * 基础配置
 *
 * @author pengsenhao
 */
@Component
@Import({RedisConfig.class})
public class BaseConfig {


}

bootstrap.yml

application:
  name: @name@ # 工程名称
  version: @version@ # 工程版本号
spring:
  profiles:
    active: local # 选择配置文件
  security:
    user:
      name: ${application.name} # security 默认账号
      password: ${application.name} # security 默认密码
  web:
    locale: zh_CN # 简体中文语言
    resources:
      add-mappings: false # 不要为资源文件建立映射
  mvc:
    log-resolved-exception: true # 开启日志解析异常
    throw-exception-if-no-handler-found: true # 出现异常直接抛出错误
    format:
      time: HH:mm:ss # time 转换格式
      date: yyyy-MM-dd # date 转换格式
      date-time: yyyy-MM-dd HH:mm:ss # date-time 转换格式
  thymeleaf:
    check-template-location: false # 不检查模块位置
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss # 设置时间默认序列化格式
    time-zone: Asia/Shanghai # 设置序列化时区
    default-property-inclusion: non_null # 只序列化非空字段
  servlet:
    multipart:
      max-file-size: 100MB # 设置最大文件上传大小 100MB
      max-request-size: 100MB # 设置发起请求最大文件上传大小 100MB
  task:
    execution:
      pool:
        core-size: 10 # 定时任务线程池核心数
        max-size: 100 # 定时任务最大线程数
        keep-alive: 30s # 定时任务线程保持空闲时间
  output:
    ansi:
      enabled: always # 启用控制台打印颜色
  cloud:
    consul:
      discovery:
        health-check-critical-timeout: 10s # 设置健康检查失败多长时间后,取消注册
        tags:
          - ${spring.profiles.active}-@version@ # 版本号,通过与 server-list-query-tags 参数关联,实现服务隔离
        server-list-query-tags:
          genshin-adventure-mihoyo: ${spring.profiles.active}-@version@
          genshin-adventure-gateway: ${spring.profiles.active}-@version@
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver
    type: com.zaxxer.hikari.HikariDataSource
    hikari:
      minimum-idle: 5
      maximum-pool-size: 50
      auto-commit: true
      idle-timeout: 600000
      pool-name: DatebookHikariCP
      max-lifetime: 1800000
      connection-timeout: 30000
      connection-test-query: SELECT 1
  rabbitmq:
    template:
      reply-timeout: 10000 # sendAndReceive()方法的超时时间,单位毫秒
logging:
  pattern:
    console: ${CONSOLE_LOG_PATTERN:%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}  %-5.5L{5}){cyan} %clr([%39X{X-Trace-Id}]){yellow} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:%wEx}} # 控制台日志打印格式
  level:
    feign.Logger: debug # Feign 日志打印
server:
  shutdown: graceful # 优雅关机
management:
  endpoints:
    web:
      exposure:
        include: "*" # 以 web 方式暴露所有监控端点
  endpoint:
    health:
      show-details: always # 总是显示健康详情
mybatis-plus:
  global-config:
    banner: false # 关闭 mybatis-plus banner 打印
    db-config:
      id-type: input # 主键策略
feign:
  client:
    config:
      default:
        loggerLevel: basic # Feign 日志打印等级

${project}-config-web

包:${basePackage}.security

譬如:com.pongsky.kit.security

基于 spring-boot-starter-security 拦截。

SecurityConfig

import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpHeaders;
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.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 鉴权配置
 *
 * @author pengsenhao
 */
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final TraceFilter traceFilter;
    private final AuthenticationFilter authenticationFilter;

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 配置跨域请求
     *
     * @param http http
     * @throws Exception 异常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().configurationSource(corsConfigurationSource())
                .and().csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterBefore(traceFilter, UsernamePasswordAuthenticationFilter.class)
                .addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    /**
     * 配置跨域请求
     *
     * @return 跨域请求
     */
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
        List<String> methods = Stream.of(RequestMethod.PATCH, RequestMethod.OPTIONS,
                        RequestMethod.GET, RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE)
                .map(Enum::toString)
                .collect(Collectors.toList());
        corsConfiguration.setAllowedMethods(methods);
        corsConfiguration.setAllowedHeaders(Collections.singletonList("*"));
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setMaxAge(0L);
        corsConfiguration.addExposedHeader(HttpHeaders.AUTHORIZATION);
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfiguration);
        return source;
    }

}

TraceFilter

import CurrentInfo;
import CurrentThreadConfig;
import DiyHeader;
import com.pongsky.kit.web.request.Whitelist;
import org.slf4j.MDC;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Nonnull;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;

/**
 * 链路拦截器
 *
 * @author pengsenhao
 */
@Component
public class TraceFilter extends OncePerRequestFilter {

    @Override
    protected boolean shouldNotFilter(HttpServletRequest request) {
        return Whitelist.URLS.contains(request.getRequestURI());
    }

    @Override
    protected void doFilterInternal(
            @Nonnull HttpServletRequest request,
            @Nonnull HttpServletResponse response,
            @Nonnull FilterChain chain) throws IOException, ServletException {
        String traceId = CurrentThreadConfig.buildTraceId(request);
        MDC.put(DiyHeader.X_TRACE_ID, traceId);
        Enumeration<String> headerNames = request.getHeaderNames();
        Map<String, String> requestHeaders = new HashMap<>(16);
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            String value = request.getHeader(key);
            requestHeaders.put(key, value);
        }
        String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
        CurrentInfo currentInfo = new CurrentInfo()
                .setTraceId(traceId)
                .setAuthorization(authorization)
                .setRequestHeaders(requestHeaders);
        CurrentThreadConfig.setCurrentInfo(currentInfo);
        try {
            chain.doFilter(request, response);
        } finally {
            MDC.clear();
            CurrentThreadConfig.relCurrentInfo();
        }
    }

}

${project}-service-${service}

包:${basePackage}.config

譬如:com.pongsky.kit.config

LocalConfig

/**
 * @author pengsenhao
 */
@Component
@Import({MyBatisConfig.class, AsyncConfig.class})
public class LocalConfig {


}

QuartzConfig

import QuartzUtils;
import lombok.RequiredArgsConstructor;
import org.quartz.Scheduler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author pengsenhao
 * @create 2021-02-25
 */
@Configuration
@RequiredArgsConstructor
public class QuartzConfig {

    private final Scheduler scheduler;

    @Bean
    public QuartzUtils quartzUtils() {
        QuartzUtils quartzUtils = new QuartzUtils(scheduler);
        // xxx.quartzUtils = quartzUtils;
        return quartzUtils;
    }

}

包:${basePackage}.controller

譬如:com.pongsky.kit.controller

用于放置所有 controller 接口。

包:${basePackage}.controller.api

譬如:com.pongsky.kit.controller.api

该包下接口用于第三方调用。

包:${basePackage}.controller.console

譬如:com.pongsky.kit.controller.console

该包下接口用于前端项目调用。

包:${basePackage}.controller.service

譬如:com.pongsky.kit.controller.service

该包下接口用于后端项目远程调用。

包:${basePackage}.job

譬如:com.pongsky.kit.job

用于放置所有 job 定时任务调度。

包:${basePackage}.mapper

譬如:com.pongsky.kit.mapper

用于放置所有 Mapper。

包:${basePackage}.service

譬如:com.pongsky.kit.service

用于放置所有 Service。

包:${basePackage}.service.impl

譬如:com.pongsky.kit.service.impl

用于放置所有 Service Impl。

banner.txt

logo 自行替换成项目模块。

  ██╗ ██╗ █████╗ ██████╗ ██╗   ██╗███████╗███╗   ██╗████████╗██╗   ██╗██████╗ ███████╗    ███╗   ███╗██╗██╗  ██╗ ██████╗ ██╗   ██╗ ██████╗ ██╗ ██╗
 ██╔╝██╔╝██╔══██╗██╔══██╗██║   ██║██╔════╝████╗  ██║╚══██╔══╝██║   ██║██╔══██╗██╔════╝    ████╗ ████║██║██║  ██║██╔═══██╗╚██╗ ██╔╝██╔═══██╗╚██╗╚██╗
██╔╝██╔╝ ███████║██║  ██║██║   ██║█████╗  ██╔██╗ ██║   ██║   ██║   ██║██████╔╝█████╗█████╗██╔████╔██║██║███████║██║   ██║ ╚████╔╝ ██║   ██║ ╚██╗╚██╗
╚██╗╚██╗ ██╔══██║██║  ██║╚██╗ ██╔╝██╔══╝  ██║╚██╗██║   ██║   ██║   ██║██╔══██╗██╔══╝╚════╝██║╚██╔╝██║██║██╔══██║██║   ██║  ╚██╔╝  ██║   ██║ ██╔╝██╔╝
 ╚██╗╚██╗██║  ██║██████╔╝ ╚████╔╝ ███████╗██║ ╚████║   ██║   ╚██████╔╝██║  ██║███████╗    ██║ ╚═╝ ██║██║██║  ██║╚██████╔╝   ██║   ╚██████╔╝██╔╝██╔╝
  ╚═╝ ╚═╝╚═╝  ╚═╝╚═════╝   ╚═══╝  ╚══════╝╚═╝  ╚═══╝   ╚═╝    ╚═════╝ ╚═╝  ╚═╝╚══════╝    ╚═╝     ╚═╝╚═╝╚═╝  ╚═╝ ╚═════╝    ╚═╝    ╚═════╝ ╚═╝ ╚═╝

Application Version: ${application.formatted-version}-${application.instance-id}
Spring Boot Version: ${spring-boot.formatted-version}

application.yml

application:
  module: mihoyo # 模块名称
  formatted-version: ${application.name}-${application.module}-${application.version} # 格式化版本
spring:
  application:
    name: ${application.name}-${application.module} # 应用名称
  cloud:
    consul:
      discovery:
        service-name: ${spring.profiles.active}-${spring.application.name} # 服务名称
        hostname: ${spring.profiles.active}-${spring.application.name} # hostname 名称
        instance-id: ${spring.application.name}-${application.instance-id} # 唯一实例ID
  # 集群定时任务 配置
  quartz:
    job-store-type: jdbc
    wait-for-jobs-to-complete-on-shutdown: true
    properties:
      org:
        quartz:
          scheduler:
            instanceName: clusteredScheduler
            instanceId: AUTO
          jobStore:
            acquireTriggersWithinLock: true
            class: org.quartz.impl.jdbcjobstore.JobStoreTX
            driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
            tablePrefix: QRTZ_
            isClustered: true
            clusterCheckinInterval: 10000
            misfireThreshold: 60000
            maxMisfiresToHandleAtATime: 1
            useProperties: false
          threadPool:
            class: org.quartz.simpl.SimpleThreadPool
            threadCount: 50
            threadPriority: 5
            threadsInheritContextClassLoaderOfInitializingThread: true

Releases

No releases published

Packages

No packages published