1.引入pom.xml
<properties>
<!--JDK版本-->
<java.version>17</java.version>
<!--springboot版本-->
<springboot.version>3.1.0</springboot.version>
<disruptor.version>3.4.2</disruptor.version>
<!--mybatis-plus版本-->
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<!--MyBatis版本,需要升级不然报错:'sqlSessionFactory' or 'sqlSessionTemplate' are required-->
<mybatis.version>3.0.1</mybatis.version>
<pagehelper.version>1.4.5</pagehelper.version>
<guava.version>30.0-jre</guava.version>
<druid.version>1.1.12</druid.version>
<fastjson.version>1.2.83</fastjson.version>
<commons-lang3.version>3.9</commons-lang3.version>
<commons-pool2.version>2.8.0</commons-pool2.version>
<pinyin4j.version>2.5.1</pinyin4j.version>
<snakeyaml.version>2.0</snakeyaml.version>
<aviator.version>5.3.1</aviator.version>
<hutool-all.version>5.8.11</hutool-all.version>
<springdoc-ui.version>2.0.2</springdoc-ui.version>
<springdoc-api.version>2.0.2</springdoc-api.version>
<knife4j.version>3.0.3</knife4j.version>
<jasypt.version>3.0.3</jasypt.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- log4j2 -->
<!-- 支持log4j2的模块,注意把spring-boot-starter和spring-boot-starter-web包中的logging去掉 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<!--log4j2异步AsyncLogger需要这个依赖,否则AsyncLogger日志打印不出来-->
<dependency>
<groupId>com.lmax</groupId>
<artifactId>disruptor</artifactId>
<version>${disruptor.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis集成 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>${pagehelper.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>${commons-pool2.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
<version>${springboot.version}</version>
</dependency>
<!-- 汉子转拼音 -->
<dependency>
<groupId>com.belerweb</groupId>
<artifactId>pinyin4j</artifactId>
<version>${pinyin4j.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.yaml/snakeyaml -->
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
<!-- 表达式解析器 -->
<dependency>
<groupId>com.googlecode.aviator</groupId>
<artifactId>aviator</artifactId>
<version>${aviator.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>${hutool-all.version}</version>
</dependency>
<!-- 支持识别yml配置 -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
</dependency>
<!-- Swagger3 begin -->
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
<version>${springdoc-ui.version}</version>
</dependency>
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-starter-webmvc-api</artifactId>
<version>${springdoc-api.version}</version>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-springdoc-ui</artifactId>
<version>${knife4j.version}</version>
</dependency>
<!-- Swagger3 end -->
<!-- Jasypt加密 -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>${jasypt.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
<testSource>${java.version}</testSource>
<testTarget>${java.version}</testTarget>
<compilerArguments>
<verbose/>
<bootclasspath>${java.home}/lib/rt.jar${path.separator}${java.home}/lib/jce.jar</bootclasspath>
</compilerArguments>
</configuration>
<version>3.8.0</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
2.yml配置文件
server:
port: 8050
servlet:
context-path: /v1
spring:
profiles:
active: dev
application:
name: email
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
main:
allow-bean-definition-overriding: true
mybatis-plus:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.chunjuan.email.entity
configuration:
# org.apache.ibatis.logging.stdout.StdOutImpl 控制台打印sql语句【SQL、参数、数据集】
# org.apache.ibatis.logging.log4j2.Log4j2Impl 这个不在控制台打印查询结果,但是在log4j中打印【SQL、参数】
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapUnderscoreToCamelCase: true # 开启驼峰命名转换法
#global-config:
#db-config:
#logic-delete-field: isDeleted # 全局逻辑删除的实体字段名
# Logger Config
logging:
config: classpath:log4j2.yml
level:
com.chunjuan.email.mapper: DEBUG
# ==============开发环境=================
---
spring:
config:
activate:
on-profile:
- dev
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ENC(123)
username: ENC(231)
password: ENC(123)
springdoc:
api-docs:
#是否开启文档功能,默认为true,可不配置
enabled: true
jasypt:
encryptor:
# 指定加解密在spring ioc容器中bean的名称,默认 jasyptStringEncryptor
bean: myStringEncryptor
# 盐值
password: 123
# ==============测试=================
---
spring:
config:
activate:
on-profile:
- qatest
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ENC(123)
username: ENC(231)
password: ENC(123)
springdoc:
api-docs:
#是否开启文档功能,默认为true,可不配置
enabled: true
jasypt:
encryptor:
# 指定加解密在spring ioc容器中bean的名称,默认 jasyptStringEncryptor
bean: myStringEncryptor
# 盐值
password: 123
# ==============预生产=================
---
spring:
config:
activate:
on-profile:
- hotfix
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ENC(123)
username: ENC(231)
password: ENC(123)
springdoc:
api-docs:
#是否开启文档功能,默认为true,可不配置
enabled: true
jasypt:
encryptor:
# 指定加解密在spring ioc容器中bean的名称,默认 jasyptStringEncryptor
bean: myStringEncryptor
# 盐值
password: 123
# ==============生产=================
---
spring:
config:
activate:
on-profile:
- prod
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: ENC(123)
username: ENC(231)
password: ENC(123)
springdoc:
api-docs:
#是否开启文档功能,默认为true,可不配置
enabled: false
jasypt:
encryptor:
# 指定加解密在spring ioc容器中bean的名称,默认 jasyptStringEncryptor
bean: myStringEncryptor
# 盐值
password: 123
3.日志配置文件log4j2.yml
# 设置log4j2的自身log级别为warn
# 共有8个级别,按照从高到低为: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL
# 如果出现了FATAL 级别的日志就重写吧,别修复了
# Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,当设置成trace时,你会看到log4j2内部各种详细输出
# monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数
Configuration:
status: warn
monitorInterval: 30
Properties:
Property:
- name: FILE_PATH
value: /data/test/logs/email/
- name: FILE_NAME
value: email
- name: LOG_PATTERN
# 格式化输出:%date表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度 %msg:日志消息,%n是换行符
# %logger{36} 表示 Logger 名字最长36个字符
# value: "%date{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n"
value: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{requestId}] :%4p %t (%F:%L) - %m%n"
- name: LAYOUT
value: "%d{HH:mm:ss:SSS} [%X{requestId}]:%p - %l - %m%n"
Appenders:
# 这个输出控制台的配置
Console:
name: CONSOLE
target: SYSTEM_OUT
# 输出日志的格式
ThresholdFilter:
level: INFO # 控制台默认输出info日志【INFO > DEBUG】
onMatch: ACCEPT
onMismatch: DENY
# 文件会打印出所有信息,这个spring每次启动程序会自动清空,适合临时测试用
File:
name: spring
fileName: ${FILE_PATH}spring.log
append: false
ThresholdFilter:
- level: ALL
onMatch: ACCEPT
onMismatch: DENY
PatternLayout:
pattern: ${LOG_PATTERN}
RollingFile:
# 这个会打印出所有的info及以下级别的信息,每次大小超过size,
# 则这size大小的日志会自动存入按年份-月份建立的文件夹下面并进行压缩,作为存档
- name: RollingFileInfo
ignoreExceptions: false
fileName: ${FILE_PATH}info.log
filePattern: "${FILE_PATH}${FILE_NAME}/INFO-%d{yyyy-MM-dd}_%i.log"
Filters:
ThresholdFilter:
- level: INFO
onMatch: ACCEPT
onMismatch: DENY
- level: WARN
onMatch: DENY
onMismatch: NEUTRAL
PatternLayout:
pattern: ${LOG_PATTERN}
Policies:
# interval属性用来指定多久滚动一次,默认是1 hour
# 一天一存,即使文件不满足 4096MB
TimeBasedTriggeringPolicy:
interval: 1
modulate: true
# 单个日志文件最大4096MB,超过后将归档
SizeBasedTriggeringPolicy:
size: "4096 MB"
# DefaultRolloverStrategy属性如不设置,则默认为最多同一文件夹下7个文件,这里设置了60
DefaultRolloverStrategy:
max: 20 # 保留20个归档周期的数据【即:当 当日的20个日志文件每个都达到4096MB 时则删除第一个日志文件,新日志写到新的日志文件中】
Delete:
basePath: ${FILE_PATH}
maxDepth: 2 # 表示往下搜索的最大深度
IfFileName: # 匹配文件名
glob: "INFO-*.log.gz"
IfLastModified:
age: "30d" # 只保留30天日志,超过会删除
- name: RollingFileDebug
fileName: ${FILE_PATH}debug.log
filePattern: "${FILE_PATH}${FILE_NAME}/DEBUG-%d{yyyy-MM-dd}_%i.log"
Filters:
ThresholdFilter:
- level: DEBUG
onMatch: ACCEPT
onMismatch: DENY
- level: INFO
onMatch: DENY
onMismatch: NEUTRAL
PatternLayout:
pattern: ${LOG_PATTERN}
Policies:
TimeBasedTriggeringPolicy:
interval: 1 # 每天生成一个日志文件【因 yyyy-MM-dd 格式而定,若为 yyyy-MM-dd HH,则每小时】
modulate: true # 调整封存时间
SizeBasedTriggeringPolicy:
size: "4096 MB"
DefaultRolloverStrategy:
max: 20
Delete:
basePath: ${FILE_PATH}
maxDepth: 2
IfFileName:
glob: "DEBUG-*.log.gz"
IfLastModified:
age: "30d"
- name: RollingFileWarn
fileName: ${FILE_PATH}warn.log
filePattern: "${FILE_PATH}${FILE_NAME}/WARN-%d{yyyy-MM-dd}-%i.log"
Filters:
ThresholdFilter:
- level: WARN
onMatch: ACCEPT
onMismatch: DENY
- level: FATAL
onMatch: DENY
onMismatch: NEUTRAL
PatternLayout:
pattern: ${LAYOUT}
Policies:
TimeBasedTriggeringPolicy:
modulate: true
interval: 1
SizeBasedTriggeringPolicy:
size: "1024 MB"
DefaultRolloverStrategy:
max: 20
Delete:
basePath: ${FILE_PATH}
maxDepth: 2
IfFileName:
glob: "WARN-*.log"
IfLastModified:
age: "30d"
- name: RollingFileError
ignoreExceptions: false
fileName: ${FILE_PATH}error.log
filePattern: "${FILE_PATH}${FILE_NAME}/ERROR-%d{yyyy-MM-dd}-%i.log"
Filters:
ThresholdFilter:
- level: ERROR
onMatch: ACCEPT
onMismatch: DENY
- level: ERROR
onMatch: DENY
onMismatch: NEUTRAL
PatternLayout:
pattern: ${LAYOUT}
Policies:
TimeBasedTriggeringPolicy:
interval: 1
modulate: true
SizeBasedTriggeringPolicy:
size: "1024 MB"
DefaultRolloverStrategy:
max: 20
Delete:
basePath: ${FILE_PATH}
maxDepth: 2
IfFileName:
glob: "ERROR-*.log"
IfLastModified:
age: "30d"
Loggers:
Root: # 此处使用同步记录日志,如果想要改为异步,只需将 Root 改为 AsyncRoot 即可
level: info
includeLocation: true # 是否记录位置,如果为true,则会影响异步日志性能
AppenderRef:
- ref: CONSOLE
# - ref: spring
- ref: RollingFileDebug
- ref: RollingFileInfo
- ref: RollingFileWarn
- ref: RollingFileError
# AsyncLogger 异步记录日志,Log4j2中的AsyncLogger的内部使用了Disruptor框架,所以需要添加依赖disruptor-3.3.4
# 注意:includeLocation="true" 可以解决 AsyncLogger异步Logger输出appender中的日志 类方法和行数信息显示不出来问题,
# 但是会降低性能(it can make logging 5 - 20 times slower),
# 所以呢 注重性能这里就不显示打印日志的行数和所在方法,把这里的includeLocation="true 去掉。
# AsyncLogger 的additivity属性需要设置为false,这个异步需要依赖disruptor3.4,
# 如果没有disruptor3.4依赖包,AsyncLogger日志会打印不出来
AsyncLogger:
# 过滤spring和mybatis的一些无用的DEBUG信息
- name: org.springframework
level: INFO
additivity: false
AppenderRef:
- ref: CONSOLE
- name: org.mybatis
level: INFO
additivity: false
AppenderRef:
- ref: CONSOLE
# 配置输出的SQL语句
- name: org.apache.ibatis
level: DEBUG
- name: java.sql.Connection
level: DEBUG
- name: java.sql.Statement
level: DEBUG
- name: java.sql.PreparedStatement
level: DEBUG
# Logger:
# - name: asyncLogger # 日志name为 asyncLogger 会同步打印
# level: INFO
# additivity: false
# includeLocation: true
# AppenderRef:
# - ref: CONSOLE
4.日志切面配置文件
4.1 RequestIdAop
@Aspect
@Configuration
@Log4j2
public class RequestIdAop {
@Pointcut("execution(* com.chunjuan.email.controller..*(..))")
public void executionService() {}
@Before(value = "executionService()")
public void doBefore(JoinPoint joinPoint){
String requestId = UUID.randomUUID().toString().replace("-", "");
MDC.put("requestId",requestId);
log.info("=====>@Before:请求参数为:{}", Arrays.toString(joinPoint.getArgs()));
}
@AfterReturning(pointcut = "executionService()", returning="returnValue")
public void doAfterReturning(JoinPoint joinPoint,Object returnValue){
log.info("=====>@AfterReturning:响应参数为:{}",returnValue);
// 处理完请求,返回内容
MDC.clear();
}
}
4.2 ServiceAspect
@Aspect
@Component
@Log4j2
public class ServiceAspect {
@Pointcut("execution(public * com.chunjuan.email.service.impl..*ServiceImpl.*(..))")
public void pointCutMethodService() {}
@Around("pointCutMethodService()")
public Object doAroundService(ProceedingJoinPoint pjp) throws Throwable {
HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
if (request != null) {
log.info("=====>Service请求<=====");
log.info("Service请求地址:{}", HttpContextUtil.getCallPath());
log.info("Service方法:{}", request.getMethod());
log.info("Service参数:{}", Arrays.toString(pjp.getArgs()));
} else {
log.info("=========非WEB请求=========");
}
Object obj = pjp.proceed();
long beginTime = System.nanoTime();
long endTime = System.nanoTime();
long executionTime = endTime - beginTime;
long millisecond = executionTime/1000000L;
log.info("调用Service方法:{},参数:{},执行耗时:{}纳秒,耗时:{}毫秒", pjp.getSignature().toString(), Arrays.toString(pjp.getArgs()), executionTime, millisecond);
return obj;
}
}
4.3 SysLogAspect
@Aspect
@Order(10)
@Component
@Log4j2
public class SysLogAspect {
@Around(value = "execution(public * com.chunjuan.email.controller..*(..))")
public Object saveLogRecord(ProceedingJoinPoint joinPoint) throws Throwable {
// 因项目启动时就会扫描全部文件,避免启动时获取不到request而报错
HttpServletRequest request = HttpContextUtil.getHttpServletRequest();
if (request != null) {
log.info("=====>request<=====");
log.info("ip:{}", HttpContextUtil.getIpAddr());
log.info("url:{}", request.getRequestURL().toString());
log.info("path: {}", HttpContextUtil.getCallPath());
log.info("method:{}", request.getMethod());
log.info("args:{}", Arrays.toString(joinPoint.getArgs()));
} else {
log.info("=========非WEB请求=========");
}
Object result = joinPoint.proceed();
log.info("result:{}", result);
log.info("=====>response<=====");
return result;
}
}
5 config配置文件
5.1 JasyptConfig
@Configuration
public class JasyptConfig {
/**
* 加解密盐值
*/
@Value("${jasypt.encryptor.password}")
private String password;
// @Bean("jasyptStringEncryptor")
@Bean("myStringEncryptor")
public StringEncryptor myStringEncryptor() {
return new MyStringEncryptor(password);
}
}
5.2 MybatisPlusConfig
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件 3.5.X
* @author zhengkai.blog.csdn.net
*/
@Bean
public PaginationInnerInterceptor paginationInnerInterceptor() {
PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor();
// 设置最大单页限制数量,默认 500 条,-1 不受限制
paginationInterceptor.setMaxLimit(-1L);
paginationInterceptor.setDbType(DbType.MYSQL);
// 开启 count 的 join 优化,只针对部分 left join
paginationInterceptor.setOptimizeJoin(true);
return paginationInterceptor;
}
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
mybatisPlusInterceptor.setInterceptors(Collections.singletonList(paginationInnerInterceptor()));
return mybatisPlusInterceptor;
}
}
5.3 SpringBeanLoad
@Component
@Lazy(value = false)
@Log4j2
public class SpringBeanLoad extends SpringContextUtil implements ApplicationContextAware, DisposableBean {
/**
* 清除SpringContextUtil中的ApplicationContext为Null.
*/
private static void clearHolder() {
if (log.isDebugEnabled()) {
log.info("清除SpringContextUtil中的ApplicationContext:" + getContext());
}
setContext(null);
}
/**
* 实现DisposableBean接口, 在Context关闭时清理静态变量.
*/
@Override
public void destroy() throws Exception {
clearHolder();
}
/**
* 实现ApplicationContextAware接口, 注入Context到静态变量中.
*/
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
setContext(applicationContext);
}
}
5.4 SpringDocConfig
@OpenAPIDefinition(
security = @SecurityRequirement(name = "Authorization")
)
@SecurityScheme(type = SecuritySchemeType.APIKEY, name = "Authorization", scheme = "Authorization", in = SecuritySchemeIn.HEADER)
@Configuration
public class SpringDocConfig {
private String title = "SpringDoc API";
private String description = "SpringDoc Application";
private String version = "v0.0.1";
@Bean
public OpenAPI springOpenAPI() {
return new OpenAPI()
.info(new Info()
.title(title)
.description(description)
.version(version));
}
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group(title)
.pathsToMatch("/**")
.build();
}
}
6.utils
6.1 JasyptUtil
public class JasyptUtil {
/**
* PBE 算法
*/
public static final String PBE_ALGORITHMS_MD5_DES = "PBEWITHMD5ANDDES";
public static final String PBE_ALGORITHMS_MD5_TRIPLEDES = "PBEWITHMD5ANDTRIPLEDES";
public static final String PBE_ALGORITHMS_SHA1_DESEDE = "PBEWITHSHA1ANDDESEDE";
public static final String PBE_ALGORITHMS_SHA1_RC2_40 = "PBEWITHSHA1ANDRC2_40";
private JasyptUtil() {
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String password) {
return encrypt(encryptedStr, PBE_ALGORITHMS_MD5_DES, password);
}
/**
* Jasypt 加密
*
* @param encryptedStr 加密字符串
* @param algorithm 加密算法
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String encrypt(String encryptedStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定加密算法
config.setAlgorithm(algorithm);
// 加密盐值
config.setPassword(password);
//config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
encryptor.setConfig(config);
// 加密
return encryptor.encrypt(encryptedStr);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String password) {
return decrypt(decryptStr, PBE_ALGORITHMS_MD5_DES, password);
}
/**
* Jasypt 解密
*
* @param decryptStr 解密字符串
* @param algorithm 指定解密算法:解密算法要与加密算法一一对应
* PBE ALGORITHMS: [PBEWITHMD5ANDDES, PBEWITHMD5ANDTRIPLEDES, PBEWITHSHA1ANDDESEDE, PBEWITHSHA1ANDRC2_40]
* @param password 盐值
* @return
*/
public static String decrypt(String decryptStr, String algorithm, String password) {
// StandardPBEStringEncryptor、StandardPBEBigDecimalEncryptor、StandardPBEBigIntegerEncryptor、StandardPBEByteEncryptor
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentPBEConfig config = new EnvironmentPBEConfig();
// 指定解密算法:解密算法要与加密算法一一对应
config.setAlgorithm(algorithm);
// 加密秘钥
config.setPassword(password);
//config.setIvGeneratorClassName("org.jasypt.iv.NoIvGenerator");
encryptor.setConfig(config);
// 解密
return encryptor.decrypt(decryptStr);
}
public static void main(String[] args) {
String algorithm = PBE_ALGORITHMS_SHA1_DESEDE;
String password = "123";
String encryptedStr = "jdbc:mysql://123122123:3306/copyright?allowMultiQueries=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true";
String str = JasyptUtil.encrypt(encryptedStr, algorithm, password);
System.out.println("加密后的字符串:" + str);
System.out.println("解密后的字符串:" + JasyptUtil.decrypt("61TB4EvxAdjpJMaCmrqm1ab9pLsqpgbiWLpCjpGhSkY=", algorithm, password));
}
}
7.mybatisplus代码生成器
7.1pom.xml
<!-- MyBatis Plus 代码生成器集成,必须要有freemarker包 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<!-- MyBatis Plus集成 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>${mybatis-plus.version}</version>
</dependency>
<!-- MySQL 连接-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
<scope>runtime</scope>
</dependency>
7.2GeneratorUtil
public class GeneratorUtil {
/**
* 数据库连接url
*/
public static final String URL = "123";
/**
* 数据库 用户名
*/
public static final String USER_NAME = "123";
/**
* 数据库 密码
*/
public static final String PASSWORD = "123";
/**
* 作者
*/
public static final String AUTHOR = "231";
/**
* java代码保存目录
*/
public static final String SAVE_PATH = "123";
/**
* xml保存目录
*/
public static final String XML_SAVE_PATH = "123";
/**
* 保存到包下面
*/
public static final String PACKAGE = "123";
/**
* 要生成的表
*/
public static final String[] TABLES = {"123"};
/**
* 代码生成入口
*
* @param args 参数
*/
public static void main(String[] args) {
FastAutoGenerator.create(URL, USER_NAME, PASSWORD).globalConfig(builder -> {
builder.author(AUTHOR) // 设置作者
.enableSpringdoc() // 是否启用springdoc注解
.dateType(DateType.ONLY_DATE) // 时间策略
.commentDate("yyyy-MM-dd") // 注释日期
.outputDir(SAVE_PATH) // 输出目录
// .disableOpenDir()// 生成后禁止打开所生成的系统目录
.fileOverride(); // 覆盖已生成文件
}).packageConfig(builder -> {builder
. parent(PACKAGE) // 父包名
.entity("entity") // 实体类包名
.service("service") // service包名
.serviceImpl("service.impl") // serviceImpl包名
.mapper("mapper") // mapper包名
.pathInfo(Collections.singletonMap(OutputFile.xml,XML_SAVE_PATH)) // xml位置(还可自定义配置entity,service等位置)
.controller("controller"); // controller包名
}).strategyConfig(builder -> {builder
//.addTablePrefix("t_") // 增加过滤表前缀
//.addTableSuffix("_db") // 增加过滤表后缀
//.addFieldPrefix("t_") // 增加过滤字段前缀
//.addFieldSuffix("_field") // 增加过滤字段后缀
.addInclude(TABLES) // 表名称
// Entity 策略配置
.entityBuilder()
.enableLombok() // 开启lombok
.enableChainModel() // 链式
.enableTableFieldAnnotation() //开启生成实体时生成的字段注解
.idType(IdType.AUTO)// 主键生成策略 此处为 自增(可选)
.naming(NamingStrategy.underline_to_camel) // 表名 下划线 -》 驼峰命名
.columnNaming(NamingStrategy.underline_to_camel) // 字段名 下划线 -》 驼峰命名
.formatFileName("%s") // Entity 文件名称
//.enableColumnConstant()
.enableActiveRecord()
// Controller 策略配置
.controllerBuilder()
.enableRestStyle() // 开启@RestController
.formatFileName("%sController") // Controller 文件名称
// Service 策略配置
.serviceBuilder()
.formatServiceFileName("%sService") // Service 文件名称
.formatServiceImplFileName("%sServiceImpl") // ServiceImpl 文件名称
// Mapper 策略配置
.mapperBuilder()
.enableMapperAnnotation() // 开启@Mapper
.enableBaseColumnList() // 启用 columnList (通用查询结果列)
.enableBaseResultMap() // 启动resultMap
.formatMapperFileName("%sMapper") // Mapper 文件名称
.formatXmlFileName("%sMapper"); // Xml 文件名称
})
// 使用Freemarker引擎模板,默认的是Velocity引擎模板
.templateEngine(new FreemarkerTemplateEngine()).execute();
}
}