first commit

This commit is contained in:
2026-07-13 08:57:05 +08:00
commit 3ecbd0957b
2536 changed files with 200576 additions and 0 deletions
@@ -0,0 +1,26 @@
package com.zxdmy.excite.common.config;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
/**
* 全局错误访问返回结果
*
* @author 沈松
* @since 2021-09-08 0008 21:00
*/
@Component
public class ErrorPageConfig implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
errorPageRegistry.addErrorPages(
// 当遇到 NOT_FOUND 错误时,请求 /error/404 路由。
new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"),
// 当遇到 INTERNAL_SERVER_ERROR 错误时,请求 /error/500 路由。
new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500")
);
}
}
@@ -0,0 +1,67 @@
package com.zxdmy.excite.common.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* <p>
* 描述
* </p>
*
* @author 沈松
* @since 2021-10-07 0007 19:04
*/
@Component
@ConfigurationProperties(prefix = "excite")
public class ExciteConfig {
private String name;
/**
* 是否允许Redis缓存:true:允许 | false:不允许
* 此Redis缓存用到的地方主要有:用户角色、权限控制;
*/
private Boolean allowRedis;
/**
* RSA加密算法的公钥
*/
private String rsaPublicKey;
/**
* RSA加密算法的私钥
*/
private String rsaPrivateKey;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Boolean getAllowRedis() {
return allowRedis;
}
public void setAllowRedis(Boolean allowRedis) {
this.allowRedis = allowRedis;
}
public String getRsaPublicKey() {
return rsaPublicKey;
}
public void setRsaPublicKey(String rsaPublicKey) {
this.rsaPublicKey = rsaPublicKey;
}
public String getRsaPrivateKey() {
return rsaPrivateKey;
}
public void setRsaPrivateKey(String rsaPrivateKey) {
this.rsaPrivateKey = rsaPrivateKey;
}
}
@@ -0,0 +1,139 @@
package com.zxdmy.excite.common.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
import static com.google.code.kaptcha.Constants.*;
/**
* <p>
* Google验证码配置类
* </p>
*
* @author 沈松
* @since 2021-10-04 0004 20:12
*/
@Configuration
public class KaptchaConfig {
/**
* 验证码配置默认配置
*
* @return 配置信息
*/
@Bean(name = "captchaProducer")
public DefaultKaptcha getKaptchaBean() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yes,no
properties.setProperty(KAPTCHA_BORDER, "yes");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
/**
* 验证码数学题类配置(一位数加减乘除)
*
* @return 配置信息
*/
@Bean(name = "captchaProducerMathOne")
public DefaultKaptcha getKaptchaBeanMathOne() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yes,no
properties.setProperty(KAPTCHA_BORDER, "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.zxdmy.excite.common.utils.KaptchaMathOneTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为 5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
/**
* 验证码数学题类配置(两位数的加减乘除)
*
* @return 配置信息
*/
@Bean(name = "captchaProducerMathTwo")
public DefaultKaptcha getKaptchaBeanMathTwo() {
DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
Properties properties = new Properties();
// 是否有边框 默认为true 我们可以自己设置yes,no
properties.setProperty(KAPTCHA_BORDER, "yes");
// 边框颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
// 验证码文本字符颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
// 验证码图片宽度 默认为200
properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
// 验证码图片高度 默认为50
properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
// 验证码文本字符大小 默认为40
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
// KAPTCHA_SESSION_KEY
properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
// 验证码文本生成器
properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.zxdmy.excite.common.utils.KaptchaMathTwoTextCreator");
// 验证码文本字符间距 默认为2
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
// 验证码文本字符长度 默认为5
properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
// 验证码文本字体样式 默认为new Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
// 验证码噪点颜色 默认为Color.BLACK
properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
// 干扰实现类
properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
// 图片样式 水纹com.google.code.kaptcha.impl.WaterRipple 鱼眼com.google.code.kaptcha.impl.FishEyeGimpy 阴影com.google.code.kaptcha.impl.ShadowGimpy
properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
Config config = new Config(properties);
defaultKaptcha.setConfig(config);
return defaultKaptcha;
}
}
@@ -0,0 +1,34 @@
package com.zxdmy.excite.common.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <p>
* Mybatis Plus 配置信息
* </p>
*
* @author 沈松
* @since 2021-09-01 0001 18:34
*/
@Configuration
@MapperScan({"com.zxdmy.excite.system.mapper", ""})
public class MybatisPlusConfig {
/**
* 分页插件配置
*
* @return MP拦截器
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
@@ -0,0 +1,100 @@
package com.zxdmy.excite.common.config;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Component;
import java.io.Serializable;
/**
* <p>
* Redis 相关配置,参考自:spring-boot-demo
* </p>
*
* @author 沈松
* @since 2021-09-30 0030 19:15
*/
@Component
@Configuration
@EnableCaching
@AutoConfigureAfter(RedisAutoConfiguration.class)
@ConfigurationProperties(prefix = "spring.redis")
public class RedisConfig {
/**
* 自定义属性:Redis key 的前缀
*/
private String prefix = "redis:prefix:";
/**
* 自定义属性:是否开启Redis自定义前缀,默认关闭。
*/
private Boolean allowPrefix = false;
/**
* 默认情况下的模板只能支持RedisTemplate<String, String>,也就是只能存入字符串,因此支持序列化
*/
@Bean
public RedisTemplate<String, Serializable> redisCacheTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Serializable> template = new RedisTemplate<>();
// key采用String的序列化方式
template.setKeySerializer(new StringRedisSerializer());
// hash的key也采用String的序列化方式
template.setHashKeySerializer(new StringRedisSerializer());
// value序列化方式采用jackson
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
// hash的value序列化方式采用jackson
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setConnectionFactory(redisConnectionFactory);
return template;
}
/**
* 配置使用注解的时候缓存配置,默认是序列化反序列化的形式,加上此配置则为 json 形式
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
// 覆盖默认的构造key,否则会多出一个冒号
.computePrefixWith(cacheName -> this.allowPrefix ? this.prefix + cacheName + ":" : cacheName)
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(new GenericJackson2JsonRedisSerializer()))
// 不缓存空值
// .disableCachingNullValues()
;
return RedisCacheManager.builder(factory).cacheDefaults(redisCacheConfiguration).build();
}
public String getPrefix() {
return prefix;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public Boolean getAllowPrefix() {
return allowPrefix;
}
public void setAllowPrefix(Boolean allowPrefix) {
this.allowPrefix = allowPrefix;
}
}
@@ -0,0 +1,59 @@
package com.zxdmy.excite.common.config;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
import io.swagger.v3.oas.annotations.info.Info;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* <p>
* SpringDoc API配置文档
* </p>
*
* @author 沈松
* @since 2021-09-10 0010 21:57
*/
// 全局只能定义一个,主要配置文档信息和安全配置
@OpenAPIDefinition(
// 配置接口文档基本信息,用于网页显示
info = @Info(
title = "ExciteCMS", //标题
version = "1.0", //版本号
description = "An integrated content management system based on Spring Boot (v2.5.4)" //描述信息
)
// 当然还可以添加其他的安全配置。
)
@Configuration // 如果需要在此处配置分组信息,则需要添加此注解。
public class SpringDocConfig {
@Bean
public GroupedOpenApi guestApi() {
return GroupedOpenApi.builder()
// 分组名
.group("guest")
// 扫描的包路径。可选项。
.packagesToScan("com.zxdmy.cms.excite.guest")
// 匹配的路径。可选项,可以与包路径二选一,也可以都用。
.pathsToMatch("/guest/**")
.build();
}
// @Bean
// public GroupedOpenApi thirdApi() {
// return GroupedOpenApi.builder()
// // 分组名
// .group("third")
// // 扫描的包路径。可选项。
// .packagesToScan("com.zxdmy.cms.excite.third")
// // 匹配的路径。可选项,可以与包路径二选一,也可以都用。
// .pathsToMatch("/third/**")
// .build();
// }
}