feat:优化

This commit is contained in:
2025-04-14 19:44:36 +08:00
parent 5535dc98da
commit d356895156
59 changed files with 540 additions and 515 deletions
@@ -0,0 +1,31 @@
package cn.odboy.config;
import cn.odboy.config.model.ContentRsaEncodeSettingModel;
import cn.odboy.config.model.FileUploadSettingModel;
import cn.odboy.config.model.JwtAuthSettingModel;
import cn.odboy.config.model.QuartzTaskThreadPoolSettingModel;
import cn.odboy.config.model.SwaggerApiDocSettingModel;
import cn.odboy.config.model.UserLoginSettingModel;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* 应用配置
*
* @author odboy
* @date 2025-04-13
*/
@Data
@Component
@ConfigurationProperties(prefix = "app")
public class AppProperties {
private FileUploadSettingModel file;
private ContentRsaEncodeSettingModel rsa;
private JwtAuthSettingModel jwt;
private UserLoginSettingModel login;
private SwaggerApiDocSettingModel swagger;
private QuartzTaskThreadPoolSettingModel asyncTaskPool;
}
@@ -0,0 +1,10 @@
package cn.odboy.config.model;
import lombok.Data;
/**
* 密码加密传输,前端公钥加密,后端私钥解密
*/
@Data
public class ContentRsaEncodeSettingModel {
public String privateKey;
}
@@ -1,20 +1,17 @@
package cn.odboy.properties; package cn.odboy.config.model;
import cn.odboy.constant.SystemConst; import cn.odboy.constant.SystemConst;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 文件上传配置
*/
@Data @Data
@Configuration public class FileUploadSettingModel {
@ConfigurationProperties(prefix = "file")
public class FileProperties {
/** /**
* 文件大小限制 * 文件大小限制
*/ */
private Long maxSize; private Long fileMaxSize;
/** /**
* 头像大小限制 * 头像大小限制
*/ */
@@ -1,16 +1,12 @@
package cn.odboy.application.core.config; package cn.odboy.config.model;
import lombok.Data; import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/** /**
* Jwt参数配置 * Jwt参数配置
*/ */
@Data @Data
@Configuration public class JwtAuthSettingModel {
@ConfigurationProperties(prefix = "jwt")
public class SecurityProperties {
/** /**
* 必须使用最少88位的Base64对该令牌进行编码 * 必须使用最少88位的Base64对该令牌进行编码
*/ */
@@ -0,0 +1,29 @@
package cn.odboy.config.model;
import lombok.Data;
/**
* 定时任务线程池 配置
*
* @author odboy
* @date 2025-04-13
*/
@Data
public class QuartzTaskThreadPoolSettingModel {
/**
* 核心线程池大小
*/
private int corePoolSize;
/**
* 最大线程数
*/
private int maxPoolSize;
/**
* 活跃时间
*/
private int keepAliveSeconds;
/**
* 队列容量
*/
private int queueCapacity;
}
@@ -0,0 +1,12 @@
package cn.odboy.config.model;
import lombok.Data;
/**
*
* @author odboy
* @date 2025-04-13
*/
@Data
public class SwaggerApiDocSettingModel {
private boolean enabled;
}
@@ -1,6 +1,6 @@
package cn.odboy.application.core.config; package cn.odboy.config.model;
import cn.odboy.application.core.constant.LoginCodeEnum; import cn.odboy.constant.LoginCodeEnum;
import cn.odboy.exception.BadRequestException; import cn.odboy.exception.BadRequestException;
import cn.odboy.util.StringUtil; import cn.odboy.util.StringUtil;
import com.wf.captcha.ArithmeticCaptcha; import com.wf.captcha.ArithmeticCaptcha;
@@ -10,22 +10,13 @@ import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha; import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha; import com.wf.captcha.base.Captcha;
import lombok.Data; import lombok.Data;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.awt.*; import java.awt.*;
/** /**
* 登录验证码配置信息
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "login.code")
public class CaptchaProperties {
/**
* 验证码配置 * 验证码配置
*/ */
@Getter @Data
public class UserLoginCaptchaSettingModel {
private LoginCodeEnum codeType; private LoginCodeEnum codeType;
/** /**
@@ -0,0 +1,15 @@
package cn.odboy.config.model;
import lombok.Data;
/**
* 登录配置
*/
@Data
public class UserLoginSettingModel {
/**
* 账号单用户 登录
*/
private boolean single = false;
private UserLoginCaptchaSettingModel captchaSetting;
}
@@ -0,0 +1,46 @@
package cn.odboy.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 验证码业务场景
*/
@Getter
@AllArgsConstructor
public enum CaptchaBizEnum {
/* 通过手机号码重置邮箱 */
PHONE_RESET_EMAIL_CODE("10000", "phone_reset_email_code_", "通过手机号码重置邮箱"),
/* 通过旧邮箱重置邮箱 */
EMAIL_RESET_EMAIL_CODE("10001", "email_reset_email_code_", "通过旧邮箱重置邮箱"),
/* 通过手机号码重置密码 */
PHONE_RESET_PWD_CODE("10002", "phone_reset_pwd_code_", "通过手机号码重置密码"),
/* 通过邮箱重置密码 */
EMAIL_RESET_PWD_CODE("10003", "email_reset_pwd_code_", "通过邮箱重置密码");
/**
* 业务编码
*/
private final String bizCode;
/**
* redis中的key
*/
private final String redisKey;
/**
* 业务描述
*/
private final String description;
public static CaptchaBizEnum getByBizCode(String bizCode) {
for (CaptchaBizEnum value : CaptchaBizEnum.values()) {
if (value.getBizCode().equals(bizCode)) {
return value;
}
}
return null;
}
}
@@ -1,31 +0,0 @@
package cn.odboy.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 验证码业务场景
*/
@Getter
@AllArgsConstructor
public enum CodeBiEnum {
/* 旧邮箱修改邮箱 */
ONE(1, "旧邮箱修改邮箱"),
/* 通过邮箱修改密码 */
TWO(2, "通过邮箱修改密码");
private final Integer code;
private final String description;
public static CodeBiEnum find(Integer code) {
for (CodeBiEnum value : CodeBiEnum.values()) {
if (value.getCode().equals(code)) {
return value;
}
}
return null;
}
}
@@ -1,27 +0,0 @@
package cn.odboy.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 验证码业务场景对应的 Redis 中的 key
*/
@Getter
@AllArgsConstructor
public enum CodeEnum {
/* 通过手机号码重置邮箱 */
PHONE_RESET_EMAIL_CODE("phone_reset_email_code_", "通过手机号码重置邮箱"),
/* 通过旧邮箱重置邮箱 */
EMAIL_RESET_EMAIL_CODE("email_reset_email_code_", "通过旧邮箱重置邮箱"),
/* 通过手机号码重置密码 */
PHONE_RESET_PWD_CODE("phone_reset_pwd_code_", "通过手机号码重置密码"),
/* 通过邮箱重置密码 */
EMAIL_RESET_PWD_CODE("email_reset_pwd_code_", "通过邮箱重置密码");
private final String key;
private final String description;
}
@@ -1,4 +1,4 @@
package cn.odboy.application.core.constant; package cn.odboy.constant;
/** /**
* 验证码配置枚举 * 验证码配置枚举
@@ -23,11 +23,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper; import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.toolkit.ChainWrappers;
import org.apache.ibatis.annotations.Param; import org.apache.ibatis.annotations.Param;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
@@ -60,22 +56,6 @@ public interface EasyMapper<E> extends BaseMapper<E> {
*/ */
int alwaysUpdateSomeColumnById(@Param("et") E entity); int alwaysUpdateSomeColumnById(@Param("et") E entity);
default QueryChainWrapper<E> select() {
return ChainWrappers.queryChain(this);
}
default UpdateChainWrapper<E> update() {
return ChainWrappers.updateChain(this);
}
default LambdaQueryChainWrapper<E> lambdaSelect() {
return ChainWrappers.lambdaQueryChain(this);
}
default LambdaUpdateChainWrapper<E> lambdaUpdate() {
return ChainWrappers.lambdaUpdateChain(this);
}
/** /**
* 获取字典 * 获取字典
* *
@@ -84,7 +64,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param valueName 值对应的列名称 * @param valueName 值对应的列名称
* @return Map<String, Object> * @return Map<String, Object>
*/ */
default Map<String, Object> selectMap(LambdaQueryWrapper<E> wrapper, String keyName, String valueName) { default Map<String, Object> getMapWithKv(LambdaQueryWrapper<E> wrapper, String keyName, String valueName) {
Map<String, Object> result = new ConcurrentHashMap<>(1); Map<String, Object> result = new ConcurrentHashMap<>(1);
List<E> list = this.selectList(wrapper); List<E> list = this.selectList(wrapper);
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
@@ -123,7 +103,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型 * @param clazz 期望的对象类型
* @return List<T> * @return List<T>
*/ */
default <T> List<T> selectList(LambdaQueryWrapper<E> wrapper, Class<T> clazz) { default <T> List<T> queryFeatureClazzList(LambdaQueryWrapper<E> wrapper, Class<T> clazz) {
List<E> list = this.selectList(wrapper); List<E> list = this.selectList(wrapper);
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
return new ArrayList<>(); return new ArrayList<>();
@@ -138,7 +118,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型 * @param clazz 期望的对象类型
* @return List<T> * @return List<T>
*/ */
default <T> List<T> selectList(LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) { default <T> List<T> queryFeatureClazzList(LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) {
List<E> list = wrapper.list(); List<E> list = wrapper.list();
if (CollUtil.isEmpty(list)) { if (CollUtil.isEmpty(list)) {
return new ArrayList<>(); return new ArrayList<>();
@@ -154,7 +134,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型 * @param clazz 期望的对象类型
* @return IPage<T> * @return IPage<T>
*/ */
default <T> PageResult<T> selectPage(Pageable pageable, LambdaQueryWrapper<E> wrapper, Class<T> clazz) { default <T> PageResult<T> queryFeatureClazzPage(Pageable pageable, LambdaQueryWrapper<E> wrapper, Class<T> clazz) {
int pageNumber = pageable.getPageNumber(); int pageNumber = pageable.getPageNumber();
int pageSize = pageable.getPageSize(); int pageSize = pageable.getPageSize();
pageNumber = pageNumber <= 0 ? 1 : pageNumber; pageNumber = pageNumber <= 0 ? 1 : pageNumber;
@@ -174,7 +154,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型 * @param clazz 期望的对象类型
* @return IPage<T> * @return IPage<T>
*/ */
default <T> PageResult<T> selectPage(Pageable pageable, LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) { default <T> PageResult<T> queryFeatureClazzPage(Pageable pageable, LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) {
int pageNumber = pageable.getPageNumber(); int pageNumber = pageable.getPageNumber();
int pageSize = pageable.getPageSize(); int pageSize = pageable.getPageSize();
pageNumber = pageNumber <= 0 ? 1 : pageNumber; pageNumber = pageNumber <= 0 ? 1 : pageNumber;
@@ -193,7 +173,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型 * @param clazz 期望的对象类型
* @return T * @return T
*/ */
default <T> T selectOne(LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) { default <T> T getFeatureClazz(LambdaQueryChainWrapper<E> wrapper, Class<T> clazz) {
E e = this.selectOne(wrapper); E e = this.selectOne(wrapper);
if (e == null) { if (e == null) {
return null; return null;
@@ -31,41 +31,39 @@ import java.util.List;
* @date 2022-04-03 * @date 2022-04-03
*/ */
public interface EasyService<T> extends IService<T> { public interface EasyService<T> extends IService<T> {
LambdaQueryWrapper<T> quick(); <G> int saveFeatureClazz(G resources);
<G> int quickSave(G resources); <G> int saveFeatureClazzList(List<G> resources);
<G> int quickSaveBatch(List<G> resources); <G> int modifyFeatureClazzById(G resources);
<G> int quickModifyById(G resources); <G> boolean modifyFeatureClazzListById(Collection<G> resources, int batchSize);
<G> boolean quickModifyBatchById(Collection<G> resources, int batchSize); <G> G describeFeatureClazzById(Serializable id, Class<G> targetClazz);
<G> G quickGetOneById(Serializable id, Class<G> targetClazz); T describeClazzByArgs(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn);
T quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn); <G> G describeFeatureClazzByArgs(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn, Class<G> clazz);
<G> G quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn, Class<G> clazz); <G> List<G> describeFeatureClazzListByIds(List<Serializable> ids, Class<G> targetClazz);
<G> List<G> quickListByIds(List<Serializable> ids, Class<G> targetClazz); <Q> List<T> describeClazzListByArgs(Q criteria);
<Q> List<T> quickList(Q criteria); List<T> describeClazzListByArgs(LambdaQueryWrapper<T> wrapper);
List<T> quickList(LambdaQueryWrapper<T> wrapper); <G, Q> List<G> describeFeatureClazzListByArgs(Q criteria, Class<G> targetClazz);
<G, Q> List<G> quickList(Q criteria, Class<G> targetClazz); <G> List<G> describeFeatureClazzListByArgs(LambdaQueryWrapper<T> wrapper, Class<G> targetClazz);
<G> List<G> quickList(LambdaQueryWrapper<T> wrapper, Class<G> targetClazz); PageResult<T> describeClazzPageByArgs(LambdaQueryWrapper<T> wrapper, IPage<T> pageable);
PageResult<T> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable); <G> PageResult<G> describeFeatureClazzPageByArgs(LambdaQueryWrapper<T> wrapper, IPage<T> pageable, Class<G> targetClazz);
<G> PageResult<G> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable, Class<G> targetClazz); <G, Q> PageResult<G> describeFeatureClazzPageByArgs(Q criteria, IPage<T> pageable, Class<G> targetClazz);
<G, Q> PageResult<G> quickPage(Q criteria, IPage<T> pageable, Class<G> targetClazz); <Q> PageResult<T> describeClazzPageByArgs(Q criteria, IPage<T> pageable);
<Q> PageResult<T> quickPage(Q criteria, IPage<T> pageable); int modifyClazzByArgs(LambdaQueryWrapper<T> wrapper, T entity);
int quickUpdate(LambdaQueryWrapper<T> wrapper, T entity); int removeClazzByArgs(LambdaQueryWrapper<T> wrapper);
int quickDelete(LambdaQueryWrapper<T> wrapper);
} }
@@ -39,16 +39,12 @@ import java.util.List;
* @date 2022-04-03 * @date 2022-04-03
*/ */
public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M, T> { public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M, T> {
public LambdaQueryWrapper<T> quick() {
return new LambdaQueryWrapper<>();
}
/** /**
* 快速插入 * 快速插入
* *
* @param resources / * @param resources /
*/ */
public <G> int quickSave(G resources) { public <G> int saveFeatureClazz(G resources) {
return getBaseMapper().insert(BeanUtil.copyProperties(resources, this.getEntityClass())); return getBaseMapper().insert(BeanUtil.copyProperties(resources, this.getEntityClass()));
} }
@@ -57,7 +53,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* *
* @param resources / * @param resources /
*/ */
public <G> int quickSaveBatch(List<G> resources) { public <G> int saveFeatureClazzList(List<G> resources) {
return getBaseMapper().insertBatchSomeColumn(BeanUtil.copyToList(resources, this.getEntityClass())); return getBaseMapper().insertBatchSomeColumn(BeanUtil.copyToList(resources, this.getEntityClass()));
} }
@@ -66,7 +62,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* *
* @param resources / * @param resources /
*/ */
public <G> int quickModifyById(G resources) { public <G> int modifyFeatureClazzById(G resources) {
return getBaseMapper().updateById(BeanUtil.copyProperties(resources, this.getEntityClass())); return getBaseMapper().updateById(BeanUtil.copyProperties(resources, this.getEntityClass()));
} }
@@ -76,7 +72,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param resources / * @param resources /
* @param batchSize 每批数量 * @param batchSize 每批数量
*/ */
public <G> boolean quickModifyBatchById(Collection<G> resources, int batchSize) { public <G> boolean modifyFeatureClazzListById(Collection<G> resources, int batchSize) {
String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE_BY_ID); String sqlStatement = this.getSqlStatement(SqlMethod.UPDATE_BY_ID);
return this.executeBatch(resources, batchSize, (sqlSession, entity) -> { return this.executeBatch(resources, batchSize, (sqlSession, entity) -> {
MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>(); MapperMethod.ParamMap<T> param = new MapperMethod.ParamMap<>();
@@ -91,7 +87,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param id / * @param id /
* @param targetClazz 目标类型 * @param targetClazz 目标类型
*/ */
public <G> G quickGetOneById(Serializable id, Class<G> targetClazz) { public <G> G describeFeatureClazzById(Serializable id, Class<G> targetClazz) {
T entity = this.getById(id); T entity = this.getById(id);
return entity == null ? null : BeanUtil.copyProperties(entity, targetClazz); return entity == null ? null : BeanUtil.copyProperties(entity, targetClazz);
} }
@@ -101,7 +97,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* *
* @param wrapper 制造条件 * @param wrapper 制造条件
*/ */
public T quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn) { public T describeClazzByArgs(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn) {
if (orderColumn == null) { if (orderColumn == null) {
throw new BadRequestException("参数orderColumn(排序的列)必填"); throw new BadRequestException("参数orderColumn(排序的列)必填");
} }
@@ -117,7 +113,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
return ts.stream().findFirst().get(); return ts.stream().findFirst().get();
} }
public <G> G quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn, Class<G> clazz) { public <G> G describeFeatureClazzByArgs(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn, Class<G> clazz) {
if (orderColumn == null) { if (orderColumn == null) {
throw new BadRequestException("参数orderColumn(排序的列)必填"); throw new BadRequestException("参数orderColumn(排序的列)必填");
} }
@@ -139,7 +135,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param ids / * @param ids /
* @param targetClazz 目标类型 * @param targetClazz 目标类型
*/ */
public <G> List<G> quickListByIds(List<Serializable> ids, Class<G> targetClazz) { public <G> List<G> describeFeatureClazzListByIds(List<Serializable> ids, Class<G> targetClazz) {
List<T> entitys = this.listByIds(ids); List<T> entitys = this.listByIds(ids);
return entitys == null || entitys.isEmpty() ? CollUtil.newArrayList() : BeanUtil.copyToList(entitys, targetClazz); return entitys == null || entitys.isEmpty() ? CollUtil.newArrayList() : BeanUtil.copyToList(entitys, targetClazz);
} }
@@ -149,7 +145,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* *
* @param criteria 动态条件 * @param criteria 动态条件
*/ */
public <Q> List<T> quickList(Q criteria) { public <Q> List<T> describeClazzListByArgs(Q criteria) {
QueryWrapper<T> predicate = MybatisHelper.build(criteria); QueryWrapper<T> predicate = MybatisHelper.build(criteria);
return baseMapper.selectList(predicate); return baseMapper.selectList(predicate);
} }
@@ -159,7 +155,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* *
* @param wrapper 制造条件 * @param wrapper 制造条件
*/ */
public List<T> quickList(LambdaQueryWrapper<T> wrapper) { public List<T> describeClazzListByArgs(LambdaQueryWrapper<T> wrapper) {
if (wrapper == null) { if (wrapper == null) {
wrapper = new LambdaQueryWrapper<>(); wrapper = new LambdaQueryWrapper<>();
} }
@@ -172,7 +168,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param criteria 动态条件 * @param criteria 动态条件
* @param targetClazz 目标类型 * @param targetClazz 目标类型
*/ */
public <G, Q> List<G> quickList(Q criteria, Class<G> targetClazz) { public <G, Q> List<G> describeFeatureClazzListByArgs(Q criteria, Class<G> targetClazz) {
QueryWrapper<T> predicate = MybatisHelper.build(criteria); QueryWrapper<T> predicate = MybatisHelper.build(criteria);
List<T> data = baseMapper.selectList(predicate); List<T> data = baseMapper.selectList(predicate);
return BeanUtil.copyToList(data, targetClazz); return BeanUtil.copyToList(data, targetClazz);
@@ -184,7 +180,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param wrapper 制造条件 * @param wrapper 制造条件
* @param targetClazz 目标类型 * @param targetClazz 目标类型
*/ */
public <G> List<G> quickList(LambdaQueryWrapper<T> wrapper, Class<G> targetClazz) { public <G> List<G> describeFeatureClazzListByArgs(LambdaQueryWrapper<T> wrapper, Class<G> targetClazz) {
if (wrapper == null) { if (wrapper == null) {
wrapper = new LambdaQueryWrapper<>(); wrapper = new LambdaQueryWrapper<>();
} }
@@ -197,7 +193,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param wrapper 制造条件 * @param wrapper 制造条件
* @param pageable 分页参数 * @param pageable 分页参数
*/ */
public PageResult<T> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable) { public PageResult<T> describeClazzPageByArgs(LambdaQueryWrapper<T> wrapper, IPage<T> pageable) {
if (wrapper == null) { if (wrapper == null) {
wrapper = new LambdaQueryWrapper<>(); wrapper = new LambdaQueryWrapper<>();
} }
@@ -212,7 +208,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param pageable 分页参数 * @param pageable 分页参数
* @param targetClazz 目标类型 * @param targetClazz 目标类型
*/ */
public <G> PageResult<G> quickPage(LambdaQueryWrapper<T> wrapper, IPage<T> pageable, Class<G> targetClazz) { public <G> PageResult<G> describeFeatureClazzPageByArgs(LambdaQueryWrapper<T> wrapper, IPage<T> pageable, Class<G> targetClazz) {
if (wrapper == null) { if (wrapper == null) {
wrapper = new LambdaQueryWrapper<>(); wrapper = new LambdaQueryWrapper<>();
} }
@@ -220,13 +216,13 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
return new PageResult<>(BeanUtil.copyToList(originPageData.getRecords(), targetClazz), originPageData.getTotal()); return new PageResult<>(BeanUtil.copyToList(originPageData.getRecords(), targetClazz), originPageData.getTotal());
} }
public <G, Q> PageResult<G> quickPage(Q criteria, IPage<T> pageable, Class<G> targetClazz) { public <G, Q> PageResult<G> describeFeatureClazzPageByArgs(Q criteria, IPage<T> pageable, Class<G> targetClazz) {
QueryWrapper<T> wrapper = MybatisHelper.build(criteria); QueryWrapper<T> wrapper = MybatisHelper.build(criteria);
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper); IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
return new PageResult<>(BeanUtil.copyToList(originPageData.getRecords(), targetClazz), originPageData.getTotal()); return new PageResult<>(BeanUtil.copyToList(originPageData.getRecords(), targetClazz), originPageData.getTotal());
} }
public <Q> PageResult<T> quickPage(Q criteria, IPage<T> pageable) { public <Q> PageResult<T> describeClazzPageByArgs(Q criteria, IPage<T> pageable) {
QueryWrapper<T> wrapper = MybatisHelper.build(criteria); QueryWrapper<T> wrapper = MybatisHelper.build(criteria);
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper); IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
return new PageResult<>(originPageData.getRecords(), originPageData.getTotal()); return new PageResult<>(originPageData.getRecords(), originPageData.getTotal());
@@ -238,7 +234,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param wrapper 制造条件 * @param wrapper 制造条件
* @param entity 更新内容 * @param entity 更新内容
*/ */
public int quickUpdate(LambdaQueryWrapper<T> wrapper, T entity) { public int modifyClazzByArgs(LambdaQueryWrapper<T> wrapper, T entity) {
if (wrapper == null) { if (wrapper == null) {
throw new BadRequestException("参数wrapper必填"); throw new BadRequestException("参数wrapper必填");
} }
@@ -250,7 +246,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* *
* @param wrapper 制造条件 * @param wrapper 制造条件
*/ */
public int quickDelete(LambdaQueryWrapper<T> wrapper) { public int removeClazzByArgs(LambdaQueryWrapper<T> wrapper) {
if (wrapper == null) { if (wrapper == null) {
throw new BadRequestException("参数wrapper必填"); throw new BadRequestException("参数wrapper必填");
} }
@@ -36,20 +36,17 @@ public class MybatisHelper {
try { try {
List<Field> fields = getAllFields(clazz, new ArrayList<>()); List<Field> fields = getAllFields(clazz, new ArrayList<>());
for (Field field : fields) { for (Field field : fields) {
if (!field.canAccess(clazz)) { if (!field.canAccess(query)) {
field.setAccessible(true); field.setAccessible(true);
MpQuery q = field.getAnnotation(MpQuery.class); MpQuery q = field.getAnnotation(MpQuery.class);
if (q != null) { if (q != null) {
String propName = q.propName(); String attributeName = getAttributeName(q, field);
String blurry = q.blurry();
String attributeName = StrUtil.isBlank(propName) ? field.getName() : propName;
attributeName = humpToUnderline(attributeName);
Object fieldVal = field.get(query); Object fieldVal = field.get(query);
if (ObjectUtil.isNull(fieldVal) || "".equals(fieldVal)) { if (ObjectUtil.isNull(fieldVal) || "".equals(fieldVal)) {
continue; continue;
} }
if (ObjectUtil.isNotEmpty(blurry)) { if (StrUtil.isNotBlank(q.blurry())) {
handleBlurryQuery(queryWrapper, blurry, fieldVal); handleBlurryQuery(queryWrapper, q.blurry(), fieldVal);
continue; continue;
} }
handleWrapper(q, queryWrapper, attributeName, fieldVal); handleWrapper(q, queryWrapper, attributeName, fieldVal);
@@ -58,11 +55,16 @@ public class MybatisHelper {
} }
} }
} catch (Exception e) { } catch (Exception e) {
log.error("组装SQL失败", e); log.error("Failed to build query wrapper for class: {}", clazz.getName(), e);
} }
return queryWrapper; return queryWrapper;
} }
private static String getAttributeName(MpQuery q, Field field) {
String attributeName = StrUtil.isBlank(q.propName()) ? field.getName() : q.propName();
return StrUtil.toUnderlineCase(attributeName);
}
private static <R> void handleWrapper(MpQuery q, QueryWrapper<R> queryWrapper, String attributeName, Object fieldVal) { private static <R> void handleWrapper(MpQuery q, QueryWrapper<R> queryWrapper, String attributeName, Object fieldVal) {
switch (q.type()) { switch (q.type()) {
case EQUAL: case EQUAL:
@@ -87,10 +89,10 @@ public class MybatisHelper {
queryWrapper.likeRight(attributeName, fieldVal); queryWrapper.likeRight(attributeName, fieldVal);
break; break;
case IN: case IN:
handleInQuery(queryWrapper, attributeName, fieldVal); handleInOrNotQuery(true, queryWrapper, attributeName, fieldVal);
break; break;
case NOT_IN: case NOT_IN:
handleNotInQuery(queryWrapper, attributeName, fieldVal); handleInOrNotQuery(false, queryWrapper, attributeName, fieldVal);
break; break;
case NOT_EQUAL: case NOT_EQUAL:
queryWrapper.ne(attributeName, fieldVal); queryWrapper.ne(attributeName, fieldVal);
@@ -109,61 +111,42 @@ public class MybatisHelper {
} }
} }
private static <R> void handleBetweenQuery(QueryWrapper<R> queryWrapper, Object fieldVal, String finalAttributeName) { private static <R> void handleInOrNotQuery(boolean b, QueryWrapper<R> queryWrapper, String attributeName, Object fieldVal) {
if (fieldVal instanceof List) {
List<Object> between = new ArrayList<>((List<?>) fieldVal);
if (CollectionUtil.isNotEmpty(between)) {
int minSize = 2;
if (between.size() >= minSize) {
queryWrapper.between(finalAttributeName, between.get(0), between.get(1));
} else {
throw new BadRequestException("BETWEEN类型的对象列表长度必须 >= " + minSize);
}
}
} else {
throw new BadRequestException("BETWEEN类型的对象必须是一个List子集合");
}
}
private static <R> void handleNotInQuery(QueryWrapper<R> queryWrapper, String finalAttributeName, Object fieldVal) {
Collection<?> wrapNotInVal = (Collection<?>) fieldVal; Collection<?> wrapNotInVal = (Collection<?>) fieldVal;
if (CollectionUtil.isNotEmpty(wrapNotInVal)) { if (CollectionUtil.isNotEmpty(wrapNotInVal)) {
Optional<?> anyValOptional = wrapNotInVal.stream().findAny(); Optional<?> anyValOptional = wrapNotInVal.stream().findAny();
if (anyValOptional.isPresent()) { if (anyValOptional.isPresent()) {
Object o = anyValOptional.get(); Object o = anyValOptional.get();
if (o instanceof Long) { if (o instanceof Long) {
queryWrapper.notIn(finalAttributeName, fieldVal); if (b) {
} else if (o instanceof Integer) { queryWrapper.in(attributeName, fieldVal);
queryWrapper.notIn(finalAttributeName, fieldVal);
} else { } else {
throw new BadRequestException("NOT_IN类型的对象属性值必须是Long/Integer类型集合"); queryWrapper.notIn(attributeName, fieldVal);
}
} else if (o instanceof Integer) {
if (b) {
queryWrapper.in(attributeName, fieldVal);
} else {
queryWrapper.notIn(attributeName, fieldVal);
}
} else {
throw new BadRequestException("InOrNotIn查询参数类型的对象属性值必须是Long/Integer类型集合");
} }
} }
} }
} }
/** private static <R> void handleBetweenQuery(QueryWrapper<R> queryWrapper, Object fieldVal, String finalAttributeName) {
* IN查询 if (fieldVal instanceof List) {
* List<Object> between = new ArrayList<>((List<?>) fieldVal);
* @param queryWrapper / int minLength = 2;
* @param fieldVal / if (CollectionUtil.isNotEmpty(between) && between.size() >= minLength) {
* @param finalAttributeName / queryWrapper.between(finalAttributeName, between.get(0), between.get(1));
* @param <R> /
*/
private static <R> void handleInQuery(QueryWrapper<R> queryWrapper, String finalAttributeName, Object fieldVal) {
Collection<?> wrapInVal = (Collection<?>) fieldVal;
if (CollectionUtil.isNotEmpty(wrapInVal)) {
Optional<?> anyValOptional = wrapInVal.stream().findAny();
if (anyValOptional.isPresent()) {
Object o = anyValOptional.get();
if (o instanceof Long) {
queryWrapper.in(finalAttributeName, fieldVal);
} else if (o instanceof Integer) {
queryWrapper.in(finalAttributeName, fieldVal);
} else { } else {
throw new BadRequestException("IN类型的对象属性值必须是Long/Integer类型集合"); throw new BadRequestException("BETWEEN类型的对象列表长度必须 >= 2");
}
} }
} else {
throw new BadRequestException("BETWEEN类型的对象必须是一个List子集合");
} }
} }
@@ -179,7 +162,7 @@ public class MybatisHelper {
List<String> blurryList = Arrays.stream(blurry.split(",")).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList()); List<String> blurryList = Arrays.stream(blurry.split(",")).filter(StrUtil::isNotBlank).distinct().collect(Collectors.toList());
queryWrapper.and(wrapper -> { queryWrapper.and(wrapper -> {
for (String blurryItem : blurryList) { for (String blurryItem : blurryList) {
String column = humpToUnderline(blurryItem); String column = StrUtil.toUnderlineCase(blurryItem);
wrapper.or(); wrapper.or();
wrapper.like(column, fieldVal.toString()); wrapper.like(column, fieldVal.toString());
} }
@@ -194,16 +177,6 @@ public class MybatisHelper {
return fields; return fields;
} }
/***
* 驼峰命名转为下划线命名
*
* @param para
* 驼峰命名的字符串
*/
private static String humpToUnderline(String para) {
return StrUtil.toUnderlineCase(para);
}
@TableName("test_domain") @TableName("test_domain")
private static class TestDomain { private static class TestDomain {
@NotNull(groups = MyEntity.Update.class) @NotNull(groups = MyEntity.Update.class)
@@ -1,17 +0,0 @@
package cn.odboy.properties;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Data
@Component
public class RsaProperties {
public static String privateKey;
@Value("${rsa.private_key}")
public void setPrivateKey(String privateKey) {
RsaProperties.privateKey = privateKey;
}
}
@@ -1,6 +1,7 @@
package cn.odboy.server; package cn.odboy.server;
import cn.odboy.properties.FileProperties; import cn.odboy.config.AppProperties;
import cn.odboy.config.model.FileUploadSettingModel;
import com.alibaba.fastjson2.JSONWriter; import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.support.config.FastJsonConfig; import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter; import com.alibaba.fastjson2.support.spring.http.converter.FastJsonHttpMessageConverter;
@@ -26,9 +27,9 @@ public class ConfigurerAdapter implements WebMvcConfigurer {
/** /**
* 文件配置 * 文件配置
*/ */
private final FileProperties properties; private final AppProperties properties;
public ConfigurerAdapter(FileProperties properties) { public ConfigurerAdapter(AppProperties properties) {
this.properties = properties; this.properties = properties;
} }
@@ -46,7 +47,7 @@ public class ConfigurerAdapter implements WebMvcConfigurer {
@Override @Override
public void addResourceHandlers(ResourceHandlerRegistry registry) { public void addResourceHandlers(ResourceHandlerRegistry registry) {
FileProperties.ElPath path = properties.getPath(); FileUploadSettingModel.ElPath path = properties.getFile().getPath();
String avatarUtl = "file:" + path.getAvatar().replace("\\", "/"); String avatarUtl = "file:" + path.getAvatar().replace("\\", "/");
String pathUtl = "file:" + path.getPath().replace("\\", "/"); String pathUtl = "file:" + path.getPath().replace("\\", "/");
registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0); registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0);
@@ -42,7 +42,7 @@ public class SwaggerConfig {
@Value("${server.servlet.context-path:}") @Value("${server.servlet.context-path:}")
private String apiPath; private String apiPath;
@Value("${swagger.enabled}") @Value("${app.swagger.enabled}")
private Boolean enabled; private Boolean enabled;
private final ApplicationContext applicationContext; private final ApplicationContext applicationContext;
@@ -1,5 +1,7 @@
package cn.odboy.thread; package cn.odboy.thread;
import cn.odboy.config.AppProperties;
import cn.odboy.config.model.QuartzTaskThreadPoolSettingModel;
import com.alibaba.ttl.TtlRunnable; import com.alibaba.ttl.TtlRunnable;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@@ -21,7 +23,7 @@ import java.util.concurrent.atomic.AtomicInteger;
@Configuration @Configuration
public class AsyncExecutor implements AsyncConfigurer { public class AsyncExecutor implements AsyncConfigurer {
@Autowired @Autowired
private AsyncTaskProperties properties; private AppProperties properties;
/** /**
* 自定义线程池,用法 @Async * 自定义线程池,用法 @Async
@@ -30,11 +32,12 @@ public class AsyncExecutor implements AsyncConfigurer {
*/ */
@Override @Override
public Executor getAsyncExecutor() { public Executor getAsyncExecutor() {
QuartzTaskThreadPoolSettingModel asyncTaskPool = properties.getAsyncTaskPool();
// 自定义工厂 // 自定义工厂
ThreadFactory factory = r -> new Thread(r, "default-async-" + new AtomicInteger(1).getAndIncrement()); ThreadFactory factory = r -> new Thread(r, "default-async-" + new AtomicInteger(1).getAndIncrement());
// 自定义线程池 // 自定义线程池
return new ThreadPoolExecutor(properties.getCorePoolSize(), properties.getMaxPoolSize(), properties.getKeepAliveSeconds(), return new ThreadPoolExecutor(asyncTaskPool.getCorePoolSize(), asyncTaskPool.getMaxPoolSize(), asyncTaskPool.getKeepAliveSeconds(),
TimeUnit.SECONDS, new ArrayBlockingQueue<>(properties.getQueueCapacity()), factory, TimeUnit.SECONDS, new ArrayBlockingQueue<>(asyncTaskPool.getQueueCapacity()), factory,
new ThreadPoolExecutor.CallerRunsPolicy()); new ThreadPoolExecutor.CallerRunsPolicy());
} }
@@ -43,13 +46,14 @@ public class AsyncExecutor implements AsyncConfigurer {
*/ */
@Bean("taskAsync") @Bean("taskAsync")
public ThreadPoolTaskExecutor taskAsync() { public ThreadPoolTaskExecutor taskAsync() {
QuartzTaskThreadPoolSettingModel asyncTaskPool = properties.getAsyncTaskPool();
// 用法 private ThreadPoolTaskExecutor taskExecutor // 用法 private ThreadPoolTaskExecutor taskExecutor
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.getCorePoolSize()); executor.setCorePoolSize(asyncTaskPool.getCorePoolSize());
executor.setMaxPoolSize(properties.getMaxPoolSize()); executor.setMaxPoolSize(asyncTaskPool.getMaxPoolSize());
executor.setQueueCapacity(properties.getQueueCapacity()); executor.setQueueCapacity(asyncTaskPool.getQueueCapacity());
executor.setThreadNamePrefix("task-async-"); executor.setThreadNamePrefix("task-async-");
executor.setKeepAliveSeconds(properties.getKeepAliveSeconds()); executor.setKeepAliveSeconds(asyncTaskPool.getKeepAliveSeconds());
// DiscardOldestPolicy,抛弃最早的任务,将新任务加入队列。 // DiscardOldestPolicy,抛弃最早的任务,将新任务加入队列。
// AbortPolicy,拒绝执行新任务,并抛出异常。 // AbortPolicy,拒绝执行新任务,并抛出异常。
// CallerRunsPolicy,交由调用者线程执行新任务,如果调用者线程已关闭,则抛弃任务。 // CallerRunsPolicy,交由调用者线程执行新任务,如果调用者线程已关闭,则抛弃任务。
@@ -1,15 +0,0 @@
package cn.odboy.thread;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "task.pool")
public class AsyncTaskProperties {
private int corePoolSize;
private int maxPoolSize;
private int keepAliveSeconds;
private int queueCapacity;
}
@@ -1,7 +1,7 @@
package cn.odboy.websocket.constant; package cn.odboy.websocket.constant;
public enum WebSocketMsgTypeEnum { public enum WebSocketMessageBizTypeEnum {
/** /**
* 连接 * 连接
*/ */
@@ -1,6 +1,6 @@
package cn.odboy.websocket.context; package cn.odboy.websocket.context;
import cn.odboy.websocket.dto.WebSocketMsgDto; import cn.odboy.websocket.dto.WebSocketMessageDto;
import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -88,8 +88,8 @@ public class WebSocketServer {
/** /**
* 群发自定义消息 * 群发自定义消息
*/ */
public static void sendMessage(WebSocketMsgDto webSocketMsgDto, @PathParam("sid") String sid) throws IOException { public static void sendMessage(WebSocketMessageDto webSocketMessageDto, @PathParam("sid") String sid) throws IOException {
String message = JSON.toJSONString(webSocketMsgDto); String message = JSON.toJSONString(webSocketMessageDto);
log.info("推送消息到{},推送内容:{}", sid, message); log.info("推送消息到{},推送内容:{}", sid, message);
try { try {
if (sid == null) { if (sid == null) {
@@ -0,0 +1,15 @@
package cn.odboy.websocket.dto;
import cn.odboy.websocket.constant.WebSocketMessageBizTypeEnum;
import lombok.Data;
@Data
public class WebSocketMessageDto {
private String message;
private WebSocketMessageBizTypeEnum bizType;
public WebSocketMessageDto(String message, WebSocketMessageBizTypeEnum bizType) {
this.message = message;
this.bizType = bizType;
}
}
@@ -1,15 +0,0 @@
package cn.odboy.websocket.dto;
import cn.odboy.websocket.constant.WebSocketMsgTypeEnum;
import lombok.Data;
@Data
public class WebSocketMsgDto {
private String msg;
private WebSocketMsgTypeEnum msgType;
public WebSocketMsgDto(String msg, WebSocketMsgTypeEnum msgType) {
this.msg = msg;
this.msgType = msgType;
}
}
@@ -1,4 +1,4 @@
package cn.odboy; package cn.odboy.monitor;
import cn.odboy.application.system.service.DictService; import cn.odboy.application.system.service.DictService;
import cn.odboy.monitor.service.HealthCheckPointService; import cn.odboy.monitor.service.HealthCheckPointService;
@@ -7,7 +7,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@Component @Component
public class HealthCheckPointer implements HealthCheckPointService { public class HealthCheckPointerImpl implements HealthCheckPointService {
@Autowired @Autowired
private DictService dictService; private DictService dictService;
@@ -157,12 +157,40 @@ mybatis-plus:
# 是否控制台 print mybatis-plus 的 LOGO # 是否控制台 print mybatis-plus 的 LOGO
banner: true banner: true
# 登录 app:
login: # 文件存储路径
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/${spring.application.name}/file/
avatar: /home/${spring.application.name}/avatar/
windows:
path: C:\${spring.application.name}\file\
avatar: C:\${spring.application.name}\avatar\
# 文件大小M
fileMaxSize: 100
avatarMaxSize: 5
# 密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
# 鉴权
jwt:
# 必须使用最少88位的Base64对该令牌进行编码
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
# 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
token-validity-in-seconds: 14400000
# token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
detect: 1800000
# 续期时间范围,默认1小时,单位毫秒
renew: 3600000
# 登录
login:
# 是否限制单用户登录 # 是否限制单用户登录
single-login: false single: false
# 验证码 # 验证码
code: captchaSetting:
# 验证码类型配置 查看 LoginProperties 类 # 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic code-type: arithmetic
# 登录图形验证码有效时间/分钟 # 登录图形验证码有效时间/分钟
@@ -177,39 +205,11 @@ login:
font-name: font-name:
# 字体大小 # 字体大小
font-size: 25 font-size: 25
# 是否开启 swagger-ui
# 鉴权 swagger:
jwt:
# 必须使用最少88位的Base64对该令牌进行编码
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
# 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
token-validity-in-seconds: 14400000
# token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
detect: 1800000
# 续期时间范围,默认1小时,单位毫秒
renew: 3600000
# 是否开启 swagger-ui
swagger:
enabled: true enabled: true
# 针对@Async
# 文件存储路径 async-task-pool:
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/${spring.application.name}/file/
avatar: /home/${spring.application.name}/avatar/
windows:
path: C:\${spring.application.name}\file\
avatar: C:\${spring.application.name}\avatar\
# 文件大小M
maxSize: 100
avatarMaxSize: 5
task:
pool:
# 核心线程池大小 # 核心线程池大小
core-pool-size: 10 core-pool-size: 10
# 最大线程数 # 最大线程数
@@ -218,16 +218,13 @@ task:
keep-alive-seconds: 60 keep-alive-seconds: 60
# 队列容量 # 队列容量
queue-capacity: 50 queue-capacity: 50
# oss
# 七牛云 oss:
qiniu: # 七牛云
qiniu:
# 文件大小 /M # 文件大小 /M
max-size: 15 max-size: 15
email:
# 邮箱验证码有效时间/秒 captchaSetting:
code: # 邮箱验证码有效时间/秒
expiration: 300 expiration: 300
# 密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
@@ -3,6 +3,21 @@ server:
http2: http2:
# 启用 HTTP/2 支持,提升传输效率 # 启用 HTTP/2 支持,提升传输效率
enabled: true enabled: true
undertow:
threads:
# 工作线程数,默认设置为io-threads * 8。如果你的应用程序有很多同步阻塞操作,可以适当增加这个值
worker: 4
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
io: 2
# 设置为true以使用直接内存(堆外内存)来存储缓冲区。这可以减少垃圾回收的开销。
direct-buffers: true
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 1024
accesslog:
# 关闭日志
enabled: false
compression: compression:
# 启用 GZIP 压缩,减少传输数据量 # 启用 GZIP 压缩,减少传输数据量
enabled: true enabled: true
@@ -38,16 +53,16 @@ spring:
datasource: datasource:
druid: druid:
db-type: com.alibaba.druid.pool.DruidDataSource db-type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver driverClassName: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:mysql://127.0.0.1:3306/cutejava20250321?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false url: jdbc:p6spy:mysql://127.0.0.1:3306/cutejava20250321?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root username: root
password: 123456 password: 123456
# 初始连接数,建议设置为与最小空闲连接数相同 # 初始连接数,建议设置为与最小空闲连接数相同
initial-size: 20 initial-size: 2
# 最小空闲连接数,保持足够的空闲连接以应对请求 # 最小空闲连接数,保持足够的空闲连接以应对请求
min-idle: 20 min-idle: 2
# 最大连接数,根据并发需求适当增加 # 最大连接数,根据并发需求适当增加
max-active: 50 max-active: 8
# 获取连接超时时间(毫秒),调整以满足响应时间要求 # 获取连接超时时间(毫秒),调整以满足响应时间要求
max-wait: 3000 max-wait: 3000
# 启用KeepAlive机制,保持长连接 # 启用KeepAlive机制,保持长连接
@@ -110,7 +125,6 @@ spring:
max-idle: 20 max-idle: 20
# 连接池中的最小空闲连接数 # 连接池中的最小空闲连接数
min-idle: 1 min-idle: 1
# 持久层 # 持久层
mybatis-plus: mybatis-plus:
configuration: configuration:
@@ -143,12 +157,40 @@ mybatis-plus:
# 是否控制台 print mybatis-plus 的 LOGO # 是否控制台 print mybatis-plus 的 LOGO
banner: true banner: true
# 登录 app:
login: # 文件存储路径
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/${spring.application.name}/file/
avatar: /home/${spring.application.name}/avatar/
windows:
path: C:\${spring.application.name}\file\
avatar: C:\${spring.application.name}\avatar\
# 文件大小M
fileMaxSize: 100
avatarMaxSize: 5
# 密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
# 鉴权
jwt:
# 必须使用最少88位的Base64对该令牌进行编码
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI=
# 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
token-validity-in-seconds: 14400000
# token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
detect: 1800000
# 续期时间范围,默认1小时,单位毫秒
renew: 3600000
# 登录
login:
# 是否限制单用户登录 # 是否限制单用户登录
single-login: true single: true
# 验证码 # 验证码
code: captchaSetting:
# 验证码类型配置 查看 LoginProperties 类 # 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic code-type: arithmetic
# 登录图形验证码有效时间/分钟 # 登录图形验证码有效时间/分钟
@@ -163,39 +205,11 @@ login:
font-name: font-name:
# 字体大小 # 字体大小
font-size: 25 font-size: 25
# 是否开启 swagger-ui
# 鉴权 swagger:
jwt: enabled: false
# 必须使用最少88位的Base64对该令牌进行编码 # 针对@Async
base64-secret: ZmQ0ZGI5NjQ0MDQwY2I4MjMxY2Y3ZmI3MjdhN2ZmMjNhODViOTg1ZGE0NTBjMGM4NDA5NzYxMjdjOWMwYWRmZTBlZjlhNGY3ZTg4Y2U3YTE1ODVkZDU5Y2Y3OGYwZWE1NzUzNWQ2YjFjZDc0NGMxZWU2MmQ3MjY1NzJmNTE0MzI= async-task-pool:
# 令牌过期时间 此处单位/毫秒 ,默认4小时,可在此网站生成 https://www.convertworld.com/zh-hans/time/milliseconds.html
token-validity-in-seconds: 14400000
# token 续期检查时间范围(默认30分钟,单位毫秒),在token即将过期的一段时间内用户操作了,则给用户的token续期
detect: 1800000
# 续期时间范围,默认1小时,单位毫秒
renew: 3600000
# 是否开启 swagger-ui
swagger:
enabled: true
# 文件存储路径
file:
mac:
path: ~/file/
avatar: ~/avatar/
linux:
path: /home/${spring.application.name}/file/
avatar: /home/${spring.application.name}/avatar/
windows:
path: C:\${spring.application.name}\file\
avatar: C:\${spring.application.name}\avatar\
# 文件大小M
maxSize: 100
avatarMaxSize: 5
task:
pool:
# 核心线程池大小 # 核心线程池大小
core-pool-size: 10 core-pool-size: 10
# 最大线程数 # 最大线程数
@@ -204,16 +218,13 @@ task:
keep-alive-seconds: 60 keep-alive-seconds: 60
# 队列容量 # 队列容量
queue-capacity: 50 queue-capacity: 50
# oss
# 七牛云 oss:
qiniu: # 七牛云
qiniu:
# 文件大小 /M # 文件大小 /M
max-size: 15 max-size: 15
email:
# 邮箱验证码有效时间/秒 captchaSetting:
code: # 邮箱验证码有效时间/秒
expiration: 300 expiration: 300
# 密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
@@ -1,19 +0,0 @@
package cn.odboy.application.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 登录配置
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "login")
public class LoginProperties {
/**
* 账号单用户 登录
*/
private boolean singleLogin = false;
}
@@ -1,6 +1,5 @@
package cn.odboy.application.core.context; package cn.odboy.application.core.context;
import cn.odboy.application.core.config.SecurityProperties;
import cn.odboy.application.core.service.impl.UserOnlineServiceImpl; import cn.odboy.application.core.service.impl.UserOnlineServiceImpl;
import cn.odboy.constant.RequestMethodEnum; import cn.odboy.constant.RequestMethodEnum;
import cn.odboy.util.AnonTagUtil; import cn.odboy.util.AnonTagUtil;
@@ -31,7 +30,6 @@ public class SpringSecurityConfig {
private final JwtAuthenticationEntryPoint authenticationErrorHandler; private final JwtAuthenticationEntryPoint authenticationErrorHandler;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler; private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final ApplicationContext applicationContext; private final ApplicationContext applicationContext;
private final SecurityProperties securityProperties;
private final UserOnlineServiceImpl onlineUserService; private final UserOnlineServiceImpl onlineUserService;
@Bean @Bean
@@ -3,7 +3,7 @@ package cn.odboy.application.core.context;
import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil; import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.odboy.application.core.config.SecurityProperties; import cn.odboy.config.AppProperties;
import cn.odboy.constant.SystemConst; import cn.odboy.constant.SystemConst;
import cn.odboy.constant.SystemRedisKey; import cn.odboy.constant.SystemRedisKey;
import cn.odboy.model.system.model.UserJwtModel; import cn.odboy.model.system.model.UserJwtModel;
@@ -39,13 +39,13 @@ public class TokenProvider implements InitializingBean {
private JwtParser jwtParser; private JwtParser jwtParser;
private JwtBuilder jwtBuilder; private JwtBuilder jwtBuilder;
private final RedisHelper redisHelper; private final RedisHelper redisHelper;
private final SecurityProperties properties; private final AppProperties properties;
public static final String AUTHORITIES_UUID_KEY = "uid"; public static final String AUTHORITIES_UUID_KEY = "uid";
public static final String AUTHORITIES_UID_KEY = "userId"; public static final String AUTHORITIES_UID_KEY = "userId";
@Override @Override
public void afterPropertiesSet() { public void afterPropertiesSet() {
byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret()); byte[] keyBytes = Decoders.BASE64.decode(properties.getJwt().getBase64Secret());
Key key = Keys.hmacShaKeyFor(keyBytes); Key key = Keys.hmacShaKeyFor(keyBytes);
jwtParser = Jwts.parserBuilder() jwtParser = Jwts.parserBuilder()
.setSigningKey(key) .setSigningKey(key)
@@ -103,8 +103,8 @@ public class TokenProvider implements InitializingBean {
// 判断当前时间与过期时间的时间差 // 判断当前时间与过期时间的时间差
long differ = expireDate.getTime() - System.currentTimeMillis(); long differ = expireDate.getTime() - System.currentTimeMillis();
// 如果在续期检查的范围内,则续期 // 如果在续期检查的范围内,则续期
if (differ <= properties.getDetect()) { if (differ <= properties.getJwt().getDetect()) {
long renew = time + properties.getRenew(); long renew = time + properties.getJwt().getRenew();
redisHelper.expire(loginKey, renew, TimeUnit.MILLISECONDS); redisHelper.expire(loginKey, renew, TimeUnit.MILLISECONDS);
} }
} }
@@ -3,23 +3,18 @@ package cn.odboy.application.core.rest;
import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import cn.odboy.annotation.AnonymousPostMapping; import cn.odboy.annotation.AnonymousPostMapping;
import cn.odboy.application.core.config.CaptchaProperties; import cn.odboy.constant.LoginCodeEnum;
import cn.odboy.application.core.config.LoginProperties;
import cn.odboy.application.core.constant.LoginCodeEnum;
import cn.odboy.application.core.context.TokenProvider; import cn.odboy.application.core.context.TokenProvider;
import cn.odboy.application.core.service.UserOnlineService;
import cn.odboy.application.core.service.impl.UserDetailsServiceImpl; import cn.odboy.application.core.service.impl.UserDetailsServiceImpl;
import cn.odboy.application.core.service.impl.UserOnlineServiceImpl; import cn.odboy.application.core.service.impl.UserOnlineServiceImpl;
import cn.odboy.base.PageResult;
import cn.odboy.constant.SystemConst; import cn.odboy.constant.SystemConst;
import cn.odboy.constant.SystemRedisKey; import cn.odboy.constant.SystemRedisKey;
import cn.odboy.config.AppProperties;
import cn.odboy.context.SecurityHelper; import cn.odboy.context.SecurityHelper;
import cn.odboy.exception.BadRequestException; import cn.odboy.exception.BadRequestException;
import cn.odboy.model.system.model.UserJwtModel; import cn.odboy.model.system.model.UserJwtModel;
import cn.odboy.model.system.model.UserOnlineModel;
import cn.odboy.model.system.request.UserLoginRequest; import cn.odboy.model.system.request.UserLoginRequest;
import cn.odboy.model.system.response.UserInfoResponse; import cn.odboy.model.system.response.UserInfoResponse;
import cn.odboy.properties.RsaProperties;
import cn.odboy.redis.RedisHelper; import cn.odboy.redis.RedisHelper;
import cn.odboy.util.RsaEncryptUtil; import cn.odboy.util.RsaEncryptUtil;
import cn.odboy.util.StringUtil; import cn.odboy.util.StringUtil;
@@ -28,10 +23,8 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication; import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
@@ -58,8 +51,7 @@ public class AuthController {
private final RedisHelper redisHelper; private final RedisHelper redisHelper;
private final UserOnlineServiceImpl onlineUserService; private final UserOnlineServiceImpl onlineUserService;
private final TokenProvider tokenProvider; private final TokenProvider tokenProvider;
private final CaptchaProperties captchaProperties; private final AppProperties properties;
private final LoginProperties loginProperties;
private final PasswordEncoder passwordEncoder; private final PasswordEncoder passwordEncoder;
private final UserDetailsServiceImpl userDetailsService; private final UserDetailsServiceImpl userDetailsService;
@@ -67,7 +59,7 @@ public class AuthController {
@AnonymousPostMapping(value = "/login") @AnonymousPostMapping(value = "/login")
public ResponseEntity<Object> login(@Validated @RequestBody UserLoginRequest loginRequest, HttpServletRequest request) throws Exception { public ResponseEntity<Object> login(@Validated @RequestBody UserLoginRequest loginRequest, HttpServletRequest request) throws Exception {
// 密码解密 // 密码解密
String password = RsaEncryptUtil.decryptByPrivateKey(RsaProperties.privateKey, loginRequest.getPassword()); String password = RsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), loginRequest.getPassword());
// 查询验证码 // 查询验证码
String code = redisHelper.get(loginRequest.getUuid(), String.class); String code = redisHelper.get(loginRequest.getUuid(), String.class);
// 清除验证码 // 清除验证码
@@ -93,7 +85,7 @@ public class AuthController {
put("token", String.format("%s %s", SystemConst.TOKEN_PREFIX, token)); put("token", String.format("%s %s", SystemConst.TOKEN_PREFIX, token));
put("user", BeanUtil.copyProperties(jwtUser, UserInfoResponse.class)); put("user", BeanUtil.copyProperties(jwtUser, UserInfoResponse.class));
}}; }};
if (loginProperties.isSingleLogin()) { if (properties.getLogin().isSingle()) {
// 踢掉之前已经登录的token // 踢掉之前已经登录的token
onlineUserService.kickOutByUsername(loginRequest.getUsername()); onlineUserService.kickOutByUsername(loginRequest.getUsername());
} }
@@ -115,7 +107,7 @@ public class AuthController {
@AnonymousPostMapping(value = "/code") @AnonymousPostMapping(value = "/code")
public ResponseEntity<Object> getCode() { public ResponseEntity<Object> getCode() {
// 获取运算的结果 // 获取运算的结果
Captcha captcha = captchaProperties.getCaptcha(); Captcha captcha = properties.getLogin().getCaptchaSetting().getCaptcha();
String uuid = SystemRedisKey.CAPTCHA_LOGIN + IdUtil.simpleUUID(); String uuid = SystemRedisKey.CAPTCHA_LOGIN + IdUtil.simpleUUID();
//当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型 //当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
String captchaValue = captcha.text(); String captchaValue = captcha.text();
@@ -123,7 +115,7 @@ public class AuthController {
captchaValue = captchaValue.split("\\.")[0]; captchaValue = captchaValue.split("\\.")[0];
} }
// 保存 // 保存
redisHelper.set(uuid, captchaValue, captchaProperties.getExpiration(), TimeUnit.MINUTES); redisHelper.set(uuid, captchaValue, properties.getLogin().getCaptchaSetting().getExpiration(), TimeUnit.MINUTES);
// 验证码信息 // 验证码信息
Map<String, Object> imgResult = new HashMap<String, Object>(2) {{ Map<String, Object> imgResult = new HashMap<String, Object>(2) {{
put("img", captcha.toBase64()); put("img", captcha.toBase64());
@@ -1,9 +1,9 @@
package cn.odboy.application.core.service.impl; package cn.odboy.application.core.service.impl;
import cn.odboy.application.core.config.SecurityProperties;
import cn.odboy.application.core.context.TokenProvider; import cn.odboy.application.core.context.TokenProvider;
import cn.odboy.application.core.service.UserOnlineService; import cn.odboy.application.core.service.UserOnlineService;
import cn.odboy.base.PageResult; import cn.odboy.base.PageResult;
import cn.odboy.config.AppProperties;
import cn.odboy.constant.SystemRedisKey; import cn.odboy.constant.SystemRedisKey;
import cn.odboy.model.system.model.UserJwtModel; import cn.odboy.model.system.model.UserJwtModel;
import cn.odboy.model.system.model.UserOnlineModel; import cn.odboy.model.system.model.UserOnlineModel;
@@ -34,7 +34,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j @Slf4j
@AllArgsConstructor @AllArgsConstructor
public class UserOnlineServiceImpl implements UserOnlineService { public class UserOnlineServiceImpl implements UserOnlineService {
private final SecurityProperties properties; private final AppProperties properties;
private final TokenProvider tokenProvider; private final TokenProvider tokenProvider;
private final RedisHelper redisHelper; private final RedisHelper redisHelper;
@@ -61,7 +61,7 @@ public class UserOnlineServiceImpl implements UserOnlineService {
log.error(e.getMessage(), e); log.error(e.getMessage(), e);
} }
String loginKey = tokenProvider.loginKey(token); String loginKey = tokenProvider.loginKey(token);
redisHelper.set(loginKey, userOnlineModel, properties.getTokenValidityInSeconds(), TimeUnit.MILLISECONDS); redisHelper.set(loginKey, userOnlineModel, properties.getJwt().getTokenValidityInSeconds(), TimeUnit.MILLISECONDS);
} }
@Override @Override
@@ -2,8 +2,7 @@ package cn.odboy.application.system.rest;
import cn.odboy.application.tools.service.CaptchaService; import cn.odboy.application.tools.service.CaptchaService;
import cn.odboy.application.tools.service.EmailService; import cn.odboy.application.tools.service.EmailService;
import cn.odboy.constant.CodeBiEnum; import cn.odboy.constant.CaptchaBizEnum;
import cn.odboy.constant.CodeEnum;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -31,27 +30,27 @@ public class CaptchaController {
@ApiOperation("重置邮箱,发送验证码") @ApiOperation("重置邮箱,发送验证码")
@PostMapping(value = "/sendResetEmailCaptcha") @PostMapping(value = "/sendResetEmailCaptcha")
public ResponseEntity<Object> sendResetEmailCaptcha(@RequestParam String email) { public ResponseEntity<Object> sendResetEmailCaptcha(@RequestParam String email) {
emailService.sendEmail(captchaService.renderCodeTemplate(email, CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey())); emailService.sendEmail(captchaService.renderCodeTemplate(email, CaptchaBizEnum.EMAIL_RESET_EMAIL_CODE.getRedisKey()));
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@ApiOperation("重置密码,发送验证码") @ApiOperation("重置密码,发送验证码")
@PostMapping(value = "/sendResetPasswordCaptcha") @PostMapping(value = "/sendResetPasswordCaptcha")
public ResponseEntity<Object> sendResetPasswordCaptcha(@RequestParam String email) { public ResponseEntity<Object> sendResetPasswordCaptcha(@RequestParam String email) {
emailService.sendEmail(captchaService.renderCodeTemplate(email, CodeEnum.EMAIL_RESET_PWD_CODE.getKey())); emailService.sendEmail(captchaService.renderCodeTemplate(email, CaptchaBizEnum.EMAIL_RESET_PWD_CODE.getRedisKey()));
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@ApiOperation("验证码验证") @ApiOperation("验证码验证")
@PostMapping(value = "/checkCodeAvailable") @PostMapping(value = "/checkCodeAvailable")
public ResponseEntity<Object> checkCodeAvailable(@RequestParam String email, @RequestParam String code, @RequestParam Integer codeBi) { public ResponseEntity<Object> checkCodeAvailable(@RequestParam String email, @RequestParam String code, @RequestParam String codeBi) {
CodeBiEnum biEnum = CodeBiEnum.find(codeBi); CaptchaBizEnum biEnum = CaptchaBizEnum.getByBizCode(codeBi);
switch (Objects.requireNonNull(biEnum)) { switch (Objects.requireNonNull(biEnum)) {
case ONE: case EMAIL_RESET_EMAIL_CODE:
captchaService.checkCodeAvailable(CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey(), email, code); captchaService.checkCodeAvailable(CaptchaBizEnum.EMAIL_RESET_EMAIL_CODE.getBizCode(), email, code);
break; break;
case TWO: case EMAIL_RESET_PWD_CODE:
captchaService.checkCodeAvailable(CodeEnum.EMAIL_RESET_PWD_CODE.getKey(), email, code); captchaService.checkCodeAvailable(CaptchaBizEnum.EMAIL_RESET_PWD_CODE.getBizCode(), email, code);
break; break;
default: default:
break; break;
@@ -8,7 +8,8 @@ import cn.odboy.application.system.service.UserService;
import cn.odboy.application.tools.service.CaptchaService; import cn.odboy.application.tools.service.CaptchaService;
import cn.odboy.base.MyMetaOption; import cn.odboy.base.MyMetaOption;
import cn.odboy.base.PageResult; import cn.odboy.base.PageResult;
import cn.odboy.constant.CodeEnum; import cn.odboy.config.AppProperties;
import cn.odboy.constant.CaptchaBizEnum;
import cn.odboy.context.SecurityHelper; import cn.odboy.context.SecurityHelper;
import cn.odboy.exception.BadRequestException; import cn.odboy.exception.BadRequestException;
import cn.odboy.model.system.domain.Dept; import cn.odboy.model.system.domain.Dept;
@@ -16,7 +17,6 @@ import cn.odboy.model.system.domain.Role;
import cn.odboy.model.system.domain.User; import cn.odboy.model.system.domain.User;
import cn.odboy.model.system.request.QueryUserRequest; import cn.odboy.model.system.request.QueryUserRequest;
import cn.odboy.model.system.response.UpdateUserPasswordResponse; import cn.odboy.model.system.response.UpdateUserPasswordResponse;
import cn.odboy.properties.RsaProperties;
import cn.odboy.util.PageUtil; import cn.odboy.util.PageUtil;
import cn.odboy.util.RsaEncryptUtil; import cn.odboy.util.RsaEncryptUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -59,6 +59,7 @@ public class UserController {
private final DeptService deptService; private final DeptService deptService;
private final RoleService roleService; private final RoleService roleService;
private final CaptchaService verificationCodeService; private final CaptchaService verificationCodeService;
private final AppProperties properties;
@ApiOperation("导出用户数据") @ApiOperation("导出用户数据")
@GetMapping(value = "/download") @GetMapping(value = "/download")
@@ -144,8 +145,8 @@ public class UserController {
@ApiOperation("修改密码") @ApiOperation("修改密码")
@PostMapping(value = "/modifyUserPasswordByUsername") @PostMapping(value = "/modifyUserPasswordByUsername")
public ResponseEntity<Object> modifyUserPasswordByUsername(@RequestBody UpdateUserPasswordResponse passVo) throws Exception { public ResponseEntity<Object> modifyUserPasswordByUsername(@RequestBody UpdateUserPasswordResponse passVo) throws Exception {
String oldPass = RsaEncryptUtil.decryptByPrivateKey(RsaProperties.privateKey, passVo.getOldPass()); String oldPass = RsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getOldPass());
String newPass = RsaEncryptUtil.decryptByPrivateKey(RsaProperties.privateKey, passVo.getNewPass()); String newPass = RsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getNewPass());
User user = userService.describeUserByUsername(SecurityHelper.getCurrentUsername()); User user = userService.describeUserByUsername(SecurityHelper.getCurrentUsername());
if (!passwordEncoder.matches(oldPass, user.getPassword())) { if (!passwordEncoder.matches(oldPass, user.getPassword())) {
throw new BadRequestException("修改失败,旧密码错误"); throw new BadRequestException("修改失败,旧密码错误");
@@ -174,12 +175,12 @@ public class UserController {
@ApiOperation("修改邮箱") @ApiOperation("修改邮箱")
@PostMapping(value = "/modifyUserEmailByUsername/{code}") @PostMapping(value = "/modifyUserEmailByUsername/{code}")
public ResponseEntity<Object> modifyUserEmailByUsername(@PathVariable String code, @RequestBody User resources) throws Exception { public ResponseEntity<Object> modifyUserEmailByUsername(@PathVariable String code, @RequestBody User resources) throws Exception {
String password = RsaEncryptUtil.decryptByPrivateKey(RsaProperties.privateKey, resources.getPassword()); String password = RsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), resources.getPassword());
User user = userService.describeUserByUsername(SecurityHelper.getCurrentUsername()); User user = userService.describeUserByUsername(SecurityHelper.getCurrentUsername());
if (!passwordEncoder.matches(password, user.getPassword())) { if (!passwordEncoder.matches(password, user.getPassword())) {
throw new BadRequestException("密码错误"); throw new BadRequestException("密码错误");
} }
verificationCodeService.checkCodeAvailable(CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey(), resources.getEmail(), code); verificationCodeService.checkCodeAvailable(CaptchaBizEnum.EMAIL_RESET_EMAIL_CODE.getBizCode(), resources.getEmail(), code);
userService.modifyUserEmailByUsername(user.getUsername(), resources.getEmail()); userService.modifyUserEmailByUsername(user.getUsername(), resources.getEmail());
return new ResponseEntity<>(HttpStatus.OK); return new ResponseEntity<>(HttpStatus.OK);
} }
@@ -7,6 +7,7 @@ import cn.odboy.application.system.mapper.UserMapper;
import cn.odboy.application.system.mapper.UserRoleMapper; import cn.odboy.application.system.mapper.UserRoleMapper;
import cn.odboy.application.system.service.UserService; import cn.odboy.application.system.service.UserService;
import cn.odboy.base.PageResult; import cn.odboy.base.PageResult;
import cn.odboy.config.AppProperties;
import cn.odboy.constant.SystemRedisKey; import cn.odboy.constant.SystemRedisKey;
import cn.odboy.context.SecurityHelper; import cn.odboy.context.SecurityHelper;
import cn.odboy.exception.BadRequestException; import cn.odboy.exception.BadRequestException;
@@ -15,7 +16,6 @@ import cn.odboy.model.system.domain.Job;
import cn.odboy.model.system.domain.Role; import cn.odboy.model.system.domain.Role;
import cn.odboy.model.system.domain.User; import cn.odboy.model.system.domain.User;
import cn.odboy.model.system.request.QueryUserRequest; import cn.odboy.model.system.request.QueryUserRequest;
import cn.odboy.properties.FileProperties;
import cn.odboy.redis.RedisHelper; import cn.odboy.redis.RedisHelper;
import cn.odboy.util.FileUtil; import cn.odboy.util.FileUtil;
import cn.odboy.util.PageUtil; import cn.odboy.util.PageUtil;
@@ -47,7 +47,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private final UserMapper userMapper; private final UserMapper userMapper;
private final UserJobMapper userJobMapper; private final UserJobMapper userJobMapper;
private final UserRoleMapper userRoleMapper; private final UserRoleMapper userRoleMapper;
private final FileProperties fileProperties; private final AppProperties properties;
private final RedisHelper redisHelper; private final RedisHelper redisHelper;
private final UserCacheService userCacheService; private final UserCacheService userCacheService;
private final UserOnlineService userOnlineService; private final UserOnlineService userOnlineService;
@@ -211,7 +211,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Map<String, String> modifyUserAvatar(MultipartFile multipartFile) { public Map<String, String> modifyUserAvatar(MultipartFile multipartFile) {
// 文件大小验证 // 文件大小验证
FileUtil.checkSize(fileProperties.getAvatarMaxSize(), multipartFile.getSize()); FileUtil.checkSize(properties.getFile().getAvatarMaxSize(), multipartFile.getSize());
// 验证文件上传的格式 // 验证文件上传的格式
String image = "gif jpg png jpeg"; String image = "gif jpg png jpeg";
String fileType = FileUtil.getSuffix(multipartFile.getOriginalFilename()); String fileType = FileUtil.getSuffix(multipartFile.getOriginalFilename());
@@ -220,7 +220,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
} }
User user = userMapper.getUserByUsername(SecurityHelper.getCurrentUsername()); User user = userMapper.getUserByUsername(SecurityHelper.getCurrentUsername());
String oldPath = user.getAvatarPath(); String oldPath = user.getAvatarPath();
File file = FileUtil.upload(multipartFile, fileProperties.getPath().getAvatar()); File file = FileUtil.upload(multipartFile, properties.getFile().getPath().getAvatar());
user.setAvatarPath(Objects.requireNonNull(file).getPath()); user.setAvatarPath(Objects.requireNonNull(file).getPath());
user.setAvatarName(file.getName()); user.setAvatarName(file.getName());
saveOrUpdate(user); saveOrUpdate(user);
@@ -1,6 +1,6 @@
package cn.odboy.application.tools.rest; package cn.odboy.application.tools.rest;
import cn.odboy.application.tools.service.QiNiuConfigService; import cn.odboy.application.tools.service.QiniuConfigService;
import cn.odboy.application.tools.service.QiniuContentService; import cn.odboy.application.tools.service.QiniuContentService;
import cn.odboy.base.PageResult; import cn.odboy.base.PageResult;
import cn.odboy.model.tools.domain.QiniuConfig; import cn.odboy.model.tools.domain.QiniuConfig;
@@ -38,7 +38,7 @@ import java.util.Map;
@Api(tags = "工具:七牛云存储管理") @Api(tags = "工具:七牛云存储管理")
public class QiniuController { public class QiniuController {
private final QiniuContentService qiniuContentService; private final QiniuContentService qiniuContentService;
private final QiNiuConfigService qiNiuConfigService; private final QiniuConfigService qiNiuConfigService;
@ApiOperation("查询七牛云存储配置") @ApiOperation("查询七牛云存储配置")
@PostMapping(value = "/describeQiniuConfig") @PostMapping(value = "/describeQiniuConfig")
@@ -4,7 +4,7 @@ import cn.odboy.model.tools.domain.QiniuConfig;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
public interface QiNiuConfigService extends IService<QiniuConfig> { public interface QiniuConfigService extends IService<QiniuConfig> {
/** /**
* 查询配置 * 查询配置
@@ -20,7 +20,7 @@ import java.util.Collections;
@RequiredArgsConstructor @RequiredArgsConstructor
public class CaptchaServiceImpl implements CaptchaService { public class CaptchaServiceImpl implements CaptchaService {
private final RedisHelper redisHelper; private final RedisHelper redisHelper;
@Value("${code.expiration}") @Value("${app.email.captchaSetting.expiration}")
private Long expiration; private Long expiration;
@Override @Override
@@ -4,10 +4,10 @@ import cn.hutool.core.util.ObjectUtil;
import cn.odboy.application.tools.mapper.LocalStorageMapper; import cn.odboy.application.tools.mapper.LocalStorageMapper;
import cn.odboy.application.tools.service.LocalStorageService; import cn.odboy.application.tools.service.LocalStorageService;
import cn.odboy.base.PageResult; import cn.odboy.base.PageResult;
import cn.odboy.config.AppProperties;
import cn.odboy.exception.BadRequestException; import cn.odboy.exception.BadRequestException;
import cn.odboy.model.tools.domain.LocalStorage; import cn.odboy.model.tools.domain.LocalStorage;
import cn.odboy.model.tools.request.QueryLocalStorageRequest; import cn.odboy.model.tools.request.QueryLocalStorageRequest;
import cn.odboy.properties.FileProperties;
import cn.odboy.util.FileUtil; import cn.odboy.util.FileUtil;
import cn.odboy.util.PageUtil; import cn.odboy.util.PageUtil;
import cn.odboy.util.StringUtil; import cn.odboy.util.StringUtil;
@@ -29,9 +29,8 @@ import java.util.Map;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class LocalStorageServiceImpl extends ServiceImpl<LocalStorageMapper, LocalStorage> implements LocalStorageService { public class LocalStorageServiceImpl extends ServiceImpl<LocalStorageMapper, LocalStorage> implements LocalStorageService {
private final LocalStorageMapper localStorageMapper; private final LocalStorageMapper localStorageMapper;
private final FileProperties properties; private final AppProperties properties;
@Override @Override
public PageResult<LocalStorage> describeLocalStoragePage(QueryLocalStorageRequest criteria, Page<Object> page) { public PageResult<LocalStorage> describeLocalStoragePage(QueryLocalStorageRequest criteria, Page<Object> page) {
@@ -47,10 +46,10 @@ public class LocalStorageServiceImpl extends ServiceImpl<LocalStorageMapper, Loc
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public LocalStorage uploadFile(String name, MultipartFile multipartFile) { public LocalStorage uploadFile(String name, MultipartFile multipartFile) {
long size = multipartFile.getSize(); long size = multipartFile.getSize();
FileUtil.checkSize(properties.getMaxSize(), size); FileUtil.checkSize(properties.getFile().getFileMaxSize(), size);
String suffix = FileUtil.getSuffix(multipartFile.getOriginalFilename()); String suffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
String type = FileUtil.getFileType(suffix); String type = FileUtil.getFileType(suffix);
File file = FileUtil.upload(multipartFile, properties.getPath().getPath() + type + File.separator); File file = FileUtil.upload(multipartFile, properties.getFile().getPath() + type + File.separator);
if (ObjectUtil.isNull(file)) { if (ObjectUtil.isNull(file)) {
throw new BadRequestException("上传失败"); throw new BadRequestException("上传失败");
} }
@@ -1,7 +1,7 @@
package cn.odboy.application.tools.service.impl; package cn.odboy.application.tools.service.impl;
import cn.odboy.application.tools.mapper.QiniuConfigMapper; import cn.odboy.application.tools.mapper.QiniuConfigMapper;
import cn.odboy.application.tools.service.QiNiuConfigService; import cn.odboy.application.tools.service.QiniuConfigService;
import cn.odboy.constant.TransferProtocolConst; import cn.odboy.constant.TransferProtocolConst;
import cn.odboy.exception.BadRequestException; import cn.odboy.exception.BadRequestException;
import cn.odboy.model.tools.domain.QiniuConfig; import cn.odboy.model.tools.domain.QiniuConfig;
@@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
@CacheConfig(cacheNames = "qiNiu") @CacheConfig(cacheNames = "qiNiu")
public class QiNiuConfigServiceImpl extends ServiceImpl<QiniuConfigMapper, QiniuConfig> implements QiNiuConfigService { public class QiniuConfigServiceImpl extends ServiceImpl<QiniuConfigMapper, QiniuConfig> implements QiniuConfigService {
@Override @Override
@Cacheable(key = "'config'") @Cacheable(key = "'config'")
public QiniuConfig describeQiniuConfig() { public QiniuConfig describeQiniuConfig() {
@@ -1,9 +1,9 @@
package cn.odboy.application.tools.service.impl; package cn.odboy.application.tools.service.impl;
import cn.odboy.application.tools.mapper.QiniuContentMapper; import cn.odboy.application.tools.mapper.QiniuContentMapper;
import cn.odboy.application.tools.service.QiNiuConfigService; import cn.odboy.application.tools.service.QiniuConfigService;
import cn.odboy.application.tools.service.QiniuContentService; import cn.odboy.application.tools.service.QiniuContentService;
import cn.odboy.application.tools.util.QiNiuUtil; import cn.odboy.application.tools.util.QiniuUtil;
import cn.odboy.base.PageResult; import cn.odboy.base.PageResult;
import cn.odboy.exception.BadRequestException; import cn.odboy.exception.BadRequestException;
import cn.odboy.model.tools.domain.QiniuConfig; import cn.odboy.model.tools.domain.QiniuConfig;
@@ -40,9 +40,9 @@ import java.util.Map;
@CacheConfig(cacheNames = "qiNiu") @CacheConfig(cacheNames = "qiNiu")
public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, QiniuContent> implements QiniuContentService { public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, QiniuContent> implements QiniuContentService {
private final QiniuContentMapper qiniuContentMapper; private final QiniuContentMapper qiniuContentMapper;
private final QiNiuConfigService qiNiuConfigService; private final QiniuConfigService qiNiuConfigService;
@Value("${qiniu.max-size}") @Value("${app.oss.qiniu.max-size}")
private Long maxSize; private Long maxSize;
@Override @Override
@@ -64,14 +64,14 @@ public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, Qin
throw new BadRequestException("请先添加相应配置,再操作"); throw new BadRequestException("请先添加相应配置,再操作");
} }
// 构造一个带指定Zone对象的配置类 // 构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiniuConfig.getZone())); Configuration cfg = new Configuration(QiniuUtil.getRegion(qiniuConfig.getZone()));
UploadManager uploadManager = new UploadManager(cfg); UploadManager uploadManager = new UploadManager(cfg);
Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey()); Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
String upToken = auth.uploadToken(qiniuConfig.getBucket()); String upToken = auth.uploadToken(qiniuConfig.getBucket());
try { try {
String key = file.getOriginalFilename(); String key = file.getOriginalFilename();
if (qiniuContentMapper.getQiniuContentByName(key) != null) { if (qiniuContentMapper.getQiniuContentByName(key) != null) {
key = QiNiuUtil.getKey(key); key = QiniuUtil.getKey(key);
} }
Response response = uploadManager.put(file.getBytes(), key, upToken); Response response = uploadManager.put(file.getBytes(), key, upToken);
// 解析上传成功的结果 // 解析上传成功的结果
@@ -120,7 +120,7 @@ public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, Qin
throw new BadRequestException("文件不存在"); throw new BadRequestException("文件不存在");
} }
// 构造一个带指定Zone对象的配置类 // 构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiniuConfig.getZone())); Configuration cfg = new Configuration(QiniuUtil.getRegion(qiniuConfig.getZone()));
Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey()); Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
BucketManager bucketManager = new BucketManager(auth, cfg); BucketManager bucketManager = new BucketManager(auth, cfg);
try { try {
@@ -140,7 +140,7 @@ public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, Qin
throw new BadRequestException("请先添加相应配置,再操作"); throw new BadRequestException("请先添加相应配置,再操作");
} }
//构造一个带指定Zone对象的配置类 //构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiniuConfig.getZone())); Configuration cfg = new Configuration(QiniuUtil.getRegion(qiniuConfig.getZone()));
Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey()); Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
BucketManager bucketManager = new BucketManager(auth, cfg); BucketManager bucketManager = new BucketManager(auth, cfg);
//文件名前缀 //文件名前缀
@@ -8,7 +8,7 @@ import java.util.Date;
/** /**
* 七牛云存储工具类 * 七牛云存储工具类
*/ */
public final class QiNiuUtil { public final class QiniuUtil {
private static final String HUAD = "华东"; private static final String HUAD = "华东";
+20
View File
@@ -0,0 +1,20 @@
# 可参考: https://hub.docker.com/_/mysql
version: '3'
services:
mysql:
image: registry.cn-shanghai.aliyuncs.com/odboy/ops:mysql-8.0 # 原镜像`mysql:8.0`
container_name: mysql8 # 容器名为'mysql8'
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./mysql/my.cnf:/etc/mysql/my.cnf"
- "./mysql/data:/var/lib/mysql"
- "./mysql/mysql-files:/var/lib/mysql-files"
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
MYSQL_ROOT_PASSWORD: root # 设置root用户密码
MYSQL_DATABASE: demo # 初始化的数据库名称
privileged: true
user: root
ports: # 映射端口
- "3306:3306"
+3
View File
@@ -0,0 +1,3 @@
port: 13306
username: root
password: root
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose -f docker-compose-mysql.yml -p mysql8 up -d
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
docker-compose -p mysql8 down
+16
View File
@@ -0,0 +1,16 @@
version: '3'
services:
redis:
image: registry.cn-shanghai.aliyuncs.com/odboy/ops:redis-7.0.5 # 镜像'redis:7.0.5'
container_name: redis7 # 容器名为'redis'
restart: unless-stopped # 指定容器退出后的重启策略为始终重启,但是不考虑在Docker守护进程启动时就已经停止了的容器
command: redis-server /etc/redis/redis.conf --requirepass 123456 --appendonly no # 启动redis服务并添加密码为:123456,默认不开启redis-aof方式持久化配置
# command: redis-server --requirepass 123456 --appendonly yes # 启动redis服务并添加密码为:123456,并开启redis持久化配置
environment: # 设置环境变量,相当于docker run命令中的-e
TZ: Asia/Shanghai
LANG: en_US.UTF-8
volumes: # 数据卷挂载路径设置,将本机目录映射到容器目录
- "./redis/data:/data"
- "./redis/config/redis.conf:/etc/redis/redis.conf" # `redis.conf`文件内容`http://download.redis.io/redis-stable/redis.conf`
ports: # 映射端口
- "6379:6379"
+2
View File
@@ -0,0 +1,2 @@
port: 16379
password: 123456
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# 当前目录下所有文件赋予权限(读、写、执行)
chmod -R 777 ./redis
# 运行 -- 单机模式
docker-compose -f docker-compose-redis.yml -p redis7 up -d
+1
View File
@@ -0,0 +1 @@
docker-compose -p redis7 down
@@ -11,7 +11,7 @@
Target Server Version : 80025 Target Server Version : 80025
File Encoding : 65001 File Encoding : 65001
Date: 28/03/2025 19:11:17 Date: 11/04/2025 14:45:16
*/ */
SET NAMES utf8mb4; SET NAMES utf8mb4;
@@ -281,14 +281,13 @@ CREATE TABLE `sys_dept` (
-- ---------------------------- -- ----------------------------
-- Records of sys_dept -- Records of sys_dept
-- ---------------------------- -- ----------------------------
INSERT INTO `sys_dept` VALUES (2, 7, 2, '研发部', 3, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_dept` VALUES (2, 7, 1, '研发部', 3, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_dept` VALUES (5, 7, 0, '运维部', 4, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_dept` VALUES (5, 7, 0, '运维部', 4, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_dept` VALUES (6, 8, 0, '测试部', 6, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_dept` VALUES (6, 8, 0, '测试部', 6, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_dept` VALUES (7, NULL, 2, '华南分部', 0, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_dept` VALUES (7, NULL, 2, '华南分部', 0, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_dept` VALUES (8, NULL, 2, '华北分部', 1, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_dept` VALUES (8, NULL, 2, '华北分部', 1, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_dept` VALUES (15, 8, 0, 'UI部门', 7, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_dept` VALUES (15, 8, 0, 'UI部门', 7, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_dept` VALUES (17, 2, 0, '研发一组', 999, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_dept` VALUES (17, 2, 0, '研发一组', 999, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_dept` VALUES (18, 2, 0, 'asdasdasd', 999, b'1', 'admin', 'admin', '2025-03-28 14:56:05', '2025-03-28 14:56:05');
-- ---------------------------- -- ----------------------------
-- Table structure for sys_dict -- Table structure for sys_dict
@@ -303,7 +302,7 @@ CREATE TABLE `sys_dict` (
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据字典' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '数据字典' ROW_FORMAT = Dynamic;
-- ---------------------------- -- ----------------------------
-- Records of sys_dict -- Records of sys_dict
@@ -455,7 +454,7 @@ INSERT INTO `sys_menu` VALUES (119, 10, 0, 1, '数字滚动', 'countToDemo', 'co
INSERT INTO `sys_menu` VALUES (120, 10, 0, 1, '拖拽表格', 'dragTableDemo', 'components/base/DragTableDemo', 999, 'menu', 'dragTableDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_menu` VALUES (120, 10, 0, 1, '拖拽表格', 'dragTableDemo', 'components/base/DragTableDemo', 999, 'menu', 'dragTableDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_menu` VALUES (121, 10, 0, 1, '分割面板', 'splitPaneDemo', 'components/base/SplitPaneDemo', 999, 'menu', 'splitPaneDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_menu` VALUES (121, 10, 0, 1, '分割面板', 'splitPaneDemo', 'components/base/SplitPaneDemo', 999, 'menu', 'splitPaneDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_menu` VALUES (122, 10, 0, 1, 'WebSocket', 'webSocketDemo', 'components/base/WebSocketDemo', 999, 'menu', 'webSocketDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_menu` VALUES (122, 10, 0, 1, 'WebSocket', 'webSocketDemo', 'components/base/WebSocketDemo', 999, 'menu', 'webSocketDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_menu` VALUES (125, 10, 0, 1, '业务组件Demo', 'DemoShow', 'components/business/DemoShow', 999, 'menu', 'bussinessDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-03-28 11:28:35', '2025-03-28 11:28:35'); INSERT INTO `sys_menu` VALUES (125, 10, 0, 1, '业务组件Demo', 'DemoShow', 'components/business/DemoShow', 999, 'menu', 'bussinessDemo', b'0', b'0', b'0', NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
-- ---------------------------- -- ----------------------------
-- Table structure for sys_quartz_job -- Table structure for sys_quartz_job
@@ -487,8 +486,6 @@ CREATE TABLE `sys_quartz_job` (
-- ---------------------------- -- ----------------------------
INSERT INTO `sys_quartz_job` VALUES (2, 'testTask', '0/5 * * * * ?', b'1', '测试1', 'run1', 'test', '带参测试,多参使用json', '测试', NULL, NULL, NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_quartz_job` VALUES (2, 'testTask', '0/5 * * * * ?', b'1', '测试1', 'run1', 'test', '带参测试,多参使用json', '测试', NULL, NULL, NULL, 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_quartz_job` VALUES (3, 'testTask', '0/5 * * * * ?', b'1', '测试', 'run', '', '不带参测试', 'Zheng Jie', '', '6', b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_quartz_job` VALUES (3, 'testTask', '0/5 * * * * ?', b'1', '测试', 'run', '', '不带参测试', 'Zheng Jie', '', '6', b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_quartz_job` VALUES (5, 'Test', '0/5 * * * * ?', b'1', '任务告警测试', 'run', NULL, '测试', 'test', '', NULL, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_quartz_job` VALUES (6, 'testTask', '0/5 * * * * ?', b'1', '测试3', 'run2', NULL, '测试3', 'Zheng Jie', '', NULL, b'1', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
-- ---------------------------- -- ----------------------------
-- Table structure for sys_quartz_log -- Table structure for sys_quartz_log
@@ -506,7 +503,7 @@ CREATE TABLE `sys_quartz_log` (
`exception_detail` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '异常详情', `exception_detail` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '异常详情',
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间',
PRIMARY KEY (`id`) USING BTREE PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '定时任务日志' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB AUTO_INCREMENT = 26 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '定时任务日志' ROW_FORMAT = Dynamic;
-- ---------------------------- -- ----------------------------
-- Records of sys_quartz_log -- Records of sys_quartz_log
@@ -537,7 +534,7 @@ CREATE TABLE `sys_role` (
-- ---------------------------- -- ----------------------------
INSERT INTO `sys_role` VALUES (1, '超级管理员', 1, '666', '全部', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_role` VALUES (1, '超级管理员', 1, '666', '全部', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_role` VALUES (2, '普通用户', 2, '-', '本级', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_role` VALUES (2, '普通用户', 2, '-', '本级', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_role` VALUES (7, 'test', 3, 'testtesttesttesttesttesttesttesttest', '全部', 'admin', 'admin', '2025-03-28 16:09:42', '2025-03-28 16:09:42'); INSERT INTO `sys_role` VALUES (7, 'test', 3, 'testtesttesttesttesttesttesttesttest', '全部', 'admin', 'admin', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
-- ---------------------------- -- ----------------------------
-- Table structure for sys_roles_depts -- Table structure for sys_roles_depts
@@ -583,10 +580,12 @@ INSERT INTO `sys_roles_menus` VALUES (10, 2);
INSERT INTO `sys_roles_menus` VALUES (11, 1); INSERT INTO `sys_roles_menus` VALUES (11, 1);
INSERT INTO `sys_roles_menus` VALUES (11, 2); INSERT INTO `sys_roles_menus` VALUES (11, 2);
INSERT INTO `sys_roles_menus` VALUES (14, 1); INSERT INTO `sys_roles_menus` VALUES (14, 1);
INSERT INTO `sys_roles_menus` VALUES (14, 7);
INSERT INTO `sys_roles_menus` VALUES (15, 1); INSERT INTO `sys_roles_menus` VALUES (15, 1);
INSERT INTO `sys_roles_menus` VALUES (15, 2); INSERT INTO `sys_roles_menus` VALUES (15, 2);
INSERT INTO `sys_roles_menus` VALUES (18, 1); INSERT INTO `sys_roles_menus` VALUES (18, 1);
INSERT INTO `sys_roles_menus` VALUES (18, 2); INSERT INTO `sys_roles_menus` VALUES (18, 2);
INSERT INTO `sys_roles_menus` VALUES (18, 7);
INSERT INTO `sys_roles_menus` VALUES (21, 1); INSERT INTO `sys_roles_menus` VALUES (21, 1);
INSERT INTO `sys_roles_menus` VALUES (21, 2); INSERT INTO `sys_roles_menus` VALUES (21, 2);
INSERT INTO `sys_roles_menus` VALUES (22, 1); INSERT INTO `sys_roles_menus` VALUES (22, 1);
@@ -605,6 +604,7 @@ INSERT INTO `sys_roles_menus` VALUES (34, 2);
INSERT INTO `sys_roles_menus` VALUES (35, 1); INSERT INTO `sys_roles_menus` VALUES (35, 1);
INSERT INTO `sys_roles_menus` VALUES (36, 1); INSERT INTO `sys_roles_menus` VALUES (36, 1);
INSERT INTO `sys_roles_menus` VALUES (36, 2); INSERT INTO `sys_roles_menus` VALUES (36, 2);
INSERT INTO `sys_roles_menus` VALUES (36, 7);
INSERT INTO `sys_roles_menus` VALUES (37, 1); INSERT INTO `sys_roles_menus` VALUES (37, 1);
INSERT INTO `sys_roles_menus` VALUES (39, 1); INSERT INTO `sys_roles_menus` VALUES (39, 1);
INSERT INTO `sys_roles_menus` VALUES (41, 1); INSERT INTO `sys_roles_menus` VALUES (41, 1);
@@ -631,10 +631,13 @@ INSERT INTO `sys_roles_menus` VALUES (74, 1);
INSERT INTO `sys_roles_menus` VALUES (75, 1); INSERT INTO `sys_roles_menus` VALUES (75, 1);
INSERT INTO `sys_roles_menus` VALUES (77, 1); INSERT INTO `sys_roles_menus` VALUES (77, 1);
INSERT INTO `sys_roles_menus` VALUES (77, 2); INSERT INTO `sys_roles_menus` VALUES (77, 2);
INSERT INTO `sys_roles_menus` VALUES (77, 7);
INSERT INTO `sys_roles_menus` VALUES (78, 1); INSERT INTO `sys_roles_menus` VALUES (78, 1);
INSERT INTO `sys_roles_menus` VALUES (78, 2); INSERT INTO `sys_roles_menus` VALUES (78, 2);
INSERT INTO `sys_roles_menus` VALUES (78, 7);
INSERT INTO `sys_roles_menus` VALUES (79, 1); INSERT INTO `sys_roles_menus` VALUES (79, 1);
INSERT INTO `sys_roles_menus` VALUES (79, 2); INSERT INTO `sys_roles_menus` VALUES (79, 2);
INSERT INTO `sys_roles_menus` VALUES (79, 7);
INSERT INTO `sys_roles_menus` VALUES (80, 1); INSERT INTO `sys_roles_menus` VALUES (80, 1);
INSERT INTO `sys_roles_menus` VALUES (80, 2); INSERT INTO `sys_roles_menus` VALUES (80, 2);
INSERT INTO `sys_roles_menus` VALUES (83, 1); INSERT INTO `sys_roles_menus` VALUES (83, 1);
@@ -681,12 +684,13 @@ CREATE TABLE `sys_user` (
INDEX `idx_dept_id`(`dept_id`) USING BTREE, INDEX `idx_dept_id`(`dept_id`) USING BTREE,
INDEX `idx_enabled`(`enabled`) USING BTREE, INDEX `idx_enabled`(`enabled`) USING BTREE,
INDEX `uniq_phone`(`phone`) USING BTREE INDEX `uniq_phone`(`phone`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统用户' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB AUTO_INCREMENT = 4 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '系统用户' ROW_FORMAT = Dynamic;
-- ---------------------------- -- ----------------------------
-- Records of sys_user -- Records of sys_user
-- ---------------------------- -- ----------------------------
INSERT INTO `sys_user` VALUES (1, 2, 'admin', '管理员', '男', '18888888888', '1943815081@qq.com', '', '', '$2a$10$Egp1/gvFlt7zhlXVfEFw4OfWQCGPw0ClmMcc6FjTnvXNRVf9zdMRa', b'1', b'1', 'admin', 'admin', '2020-05-03 16:38:31', '2025-01-05 00:00:00', '2025-01-05 00:00:00'); INSERT INTO `sys_user` VALUES (1, 2, 'admin', '管理员', '男', '18888888888', '1943815081@qq.com', '', '', '$2a$10$Egp1/gvFlt7zhlXVfEFw4OfWQCGPw0ClmMcc6FjTnvXNRVf9zdMRa', b'1', b'1', 'admin', 'admin', '2020-05-03 16:38:31', '2025-01-05 00:00:00', '2025-01-05 00:00:00');
INSERT INTO `sys_user` VALUES (3, 2, '测试', '测试', '男', '18888888881', '188888@qq.com', NULL, NULL, '$2a$10$DpAGWp3CYtYySPqJe.CnL.c/OCR0kkPLLAwAyID0yFHLamtYdYsvy', b'0', b'1', 'admin', 'admin', NULL, '2025-01-05 00:00:00', '2025-01-05 00:00:00');
-- ---------------------------- -- ----------------------------
-- Table structure for sys_users_jobs -- Table structure for sys_users_jobs
@@ -704,6 +708,7 @@ CREATE TABLE `sys_users_jobs` (
-- Records of sys_users_jobs -- Records of sys_users_jobs
-- ---------------------------- -- ----------------------------
INSERT INTO `sys_users_jobs` VALUES (1, 11); INSERT INTO `sys_users_jobs` VALUES (1, 11);
INSERT INTO `sys_users_jobs` VALUES (3, 11);
-- ---------------------------- -- ----------------------------
-- Table structure for sys_users_roles -- Table structure for sys_users_roles
@@ -721,6 +726,7 @@ CREATE TABLE `sys_users_roles` (
-- Records of sys_users_roles -- Records of sys_users_roles
-- ---------------------------- -- ----------------------------
INSERT INTO `sys_users_roles` VALUES (1, 1); INSERT INTO `sys_users_roles` VALUES (1, 1);
INSERT INTO `sys_users_roles` VALUES (3, 2);
-- ---------------------------- -- ----------------------------
-- Table structure for tool_email_config -- Table structure for tool_email_config
@@ -757,11 +763,12 @@ CREATE TABLE `tool_local_storage` (
`create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期', `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建日期',
`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间', `update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '本地存储' ROW_FORMAT = Dynamic; ) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '本地存储' ROW_FORMAT = Dynamic;
-- ---------------------------- -- ----------------------------
-- Records of tool_local_storage -- Records of tool_local_storage
-- ---------------------------- -- ----------------------------
INSERT INTO `tool_local_storage` VALUES (11, 'bg-202504100131576.jpg', 'bg', 'jpg', 'C:\\cutejava\\file\\image\\bg-202504100131576.jpg', 'image', '20.20MB ', 'admin', 'admin', '2025-04-10 13:32:00', '2025-04-10 13:32:00');
-- ---------------------------- -- ----------------------------
-- Table structure for tool_qiniu_config -- Table structure for tool_qiniu_config
Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB