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 lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* 文件上传配置
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "file")
public class FileProperties {
public class FileUploadSettingModel {
/**
* 文件大小限制
*/
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 org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* Jwt参数配置
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "jwt")
public class SecurityProperties {
public class JwtAuthSettingModel {
/**
* 必须使用最少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.util.StringUtil;
import com.wf.captcha.ArithmeticCaptcha;
@@ -10,22 +10,13 @@ import com.wf.captcha.GifCaptcha;
import com.wf.captcha.SpecCaptcha;
import com.wf.captcha.base.Captcha;
import lombok.Data;
import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import java.awt.*;
/**
* 登录验证码配置信息
* 验证码配置
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "login.code")
public class CaptchaProperties {
/**
* 验证码配置
*/
@Getter
public class UserLoginCaptchaSettingModel {
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.metadata.IPage;
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.toolkit.ChainWrappers;
import org.apache.ibatis.annotations.Param;
import org.springframework.data.domain.Pageable;
import java.lang.reflect.Field;
@@ -60,22 +56,6 @@ public interface EasyMapper<E> extends BaseMapper<E> {
*/
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 值对应的列名称
* @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);
List<E> list = this.selectList(wrapper);
if (CollUtil.isEmpty(list)) {
@@ -123,7 +103,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型
* @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);
if (CollUtil.isEmpty(list)) {
return new ArrayList<>();
@@ -138,7 +118,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型
* @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();
if (CollUtil.isEmpty(list)) {
return new ArrayList<>();
@@ -154,7 +134,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型
* @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 pageSize = pageable.getPageSize();
pageNumber = pageNumber <= 0 ? 1 : pageNumber;
@@ -174,7 +154,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型
* @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 pageSize = pageable.getPageSize();
pageNumber = pageNumber <= 0 ? 1 : pageNumber;
@@ -193,7 +173,7 @@ public interface EasyMapper<E> extends BaseMapper<E> {
* @param clazz 期望的对象类型
* @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);
if (e == null) {
return null;
@@ -31,41 +31,39 @@ import java.util.List;
* @date 2022-04-03
*/
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 quickDelete(LambdaQueryWrapper<T> wrapper);
int removeClazzByArgs(LambdaQueryWrapper<T> wrapper);
}
@@ -39,16 +39,12 @@ import java.util.List;
* @date 2022-04-03
*/
public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M, T> {
public LambdaQueryWrapper<T> quick() {
return new LambdaQueryWrapper<>();
}
/**
* 快速插入
*
* @param resources /
*/
public <G> int quickSave(G resources) {
public <G> int saveFeatureClazz(G resources) {
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 /
*/
public <G> int quickSaveBatch(List<G> resources) {
public <G> int saveFeatureClazzList(List<G> resources) {
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 /
*/
public <G> int quickModifyById(G resources) {
public <G> int modifyFeatureClazzById(G resources) {
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 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);
return this.executeBatch(resources, batchSize, (sqlSession, entity) -> {
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 targetClazz 目标类型
*/
public <G> G quickGetOneById(Serializable id, Class<G> targetClazz) {
public <G> G describeFeatureClazzById(Serializable id, Class<G> targetClazz) {
T entity = this.getById(id);
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 制造条件
*/
public T quickGetOne(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn) {
public T describeClazzByArgs(LambdaQueryWrapper<T> wrapper, SFunction<T, ?> orderColumn) {
if (orderColumn == null) {
throw new BadRequestException("参数orderColumn(排序的列)必填");
}
@@ -117,7 +113,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
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) {
throw new BadRequestException("参数orderColumn(排序的列)必填");
}
@@ -139,7 +135,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param ids /
* @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);
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 动态条件
*/
public <Q> List<T> quickList(Q criteria) {
public <Q> List<T> describeClazzListByArgs(Q criteria) {
QueryWrapper<T> predicate = MybatisHelper.build(criteria);
return baseMapper.selectList(predicate);
}
@@ -159,7 +155,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
*
* @param wrapper 制造条件
*/
public List<T> quickList(LambdaQueryWrapper<T> wrapper) {
public List<T> describeClazzListByArgs(LambdaQueryWrapper<T> wrapper) {
if (wrapper == null) {
wrapper = new LambdaQueryWrapper<>();
}
@@ -172,7 +168,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param criteria 动态条件
* @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);
List<T> data = baseMapper.selectList(predicate);
return BeanUtil.copyToList(data, targetClazz);
@@ -184,7 +180,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param wrapper 制造条件
* @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) {
wrapper = new LambdaQueryWrapper<>();
}
@@ -197,7 +193,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param wrapper 制造条件
* @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) {
wrapper = new LambdaQueryWrapper<>();
}
@@ -212,7 +208,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
* @param pageable 分页参数
* @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) {
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());
}
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);
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
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);
IPage<T> originPageData = baseMapper.selectPage(pageable, wrapper);
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 entity 更新内容
*/
public int quickUpdate(LambdaQueryWrapper<T> wrapper, T entity) {
public int modifyClazzByArgs(LambdaQueryWrapper<T> wrapper, T entity) {
if (wrapper == null) {
throw new BadRequestException("参数wrapper必填");
}
@@ -250,7 +246,7 @@ public class EasyServiceImpl<M extends EasyMapper<T>, T> extends ServiceImpl<M,
*
* @param wrapper 制造条件
*/
public int quickDelete(LambdaQueryWrapper<T> wrapper) {
public int removeClazzByArgs(LambdaQueryWrapper<T> wrapper) {
if (wrapper == null) {
throw new BadRequestException("参数wrapper必填");
}
@@ -36,20 +36,17 @@ public class MybatisHelper {
try {
List<Field> fields = getAllFields(clazz, new ArrayList<>());
for (Field field : fields) {
if (!field.canAccess(clazz)) {
if (!field.canAccess(query)) {
field.setAccessible(true);
MpQuery q = field.getAnnotation(MpQuery.class);
if (q != null) {
String propName = q.propName();
String blurry = q.blurry();
String attributeName = StrUtil.isBlank(propName) ? field.getName() : propName;
attributeName = humpToUnderline(attributeName);
String attributeName = getAttributeName(q, field);
Object fieldVal = field.get(query);
if (ObjectUtil.isNull(fieldVal) || "".equals(fieldVal)) {
continue;
}
if (ObjectUtil.isNotEmpty(blurry)) {
handleBlurryQuery(queryWrapper, blurry, fieldVal);
if (StrUtil.isNotBlank(q.blurry())) {
handleBlurryQuery(queryWrapper, q.blurry(), fieldVal);
continue;
}
handleWrapper(q, queryWrapper, attributeName, fieldVal);
@@ -58,11 +55,16 @@ public class MybatisHelper {
}
}
} catch (Exception e) {
log.error("组装SQL失败", e);
log.error("Failed to build query wrapper for class: {}", clazz.getName(), e);
}
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) {
switch (q.type()) {
case EQUAL:
@@ -87,10 +89,10 @@ public class MybatisHelper {
queryWrapper.likeRight(attributeName, fieldVal);
break;
case IN:
handleInQuery(queryWrapper, attributeName, fieldVal);
handleInOrNotQuery(true, queryWrapper, attributeName, fieldVal);
break;
case NOT_IN:
handleNotInQuery(queryWrapper, attributeName, fieldVal);
handleInOrNotQuery(false, queryWrapper, attributeName, fieldVal);
break;
case NOT_EQUAL:
queryWrapper.ne(attributeName, fieldVal);
@@ -109,61 +111,42 @@ public class MybatisHelper {
}
}
private static <R> void handleBetweenQuery(QueryWrapper<R> queryWrapper, Object fieldVal, String finalAttributeName) {
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) {
private static <R> void handleInOrNotQuery(boolean b, QueryWrapper<R> queryWrapper, String attributeName, Object fieldVal) {
Collection<?> wrapNotInVal = (Collection<?>) fieldVal;
if (CollectionUtil.isNotEmpty(wrapNotInVal)) {
Optional<?> anyValOptional = wrapNotInVal.stream().findAny();
if (anyValOptional.isPresent()) {
Object o = anyValOptional.get();
if (o instanceof Long) {
queryWrapper.notIn(finalAttributeName, fieldVal);
if (b) {
queryWrapper.in(attributeName, fieldVal);
} else {
queryWrapper.notIn(attributeName, fieldVal);
}
} else if (o instanceof Integer) {
queryWrapper.notIn(finalAttributeName, fieldVal);
if (b) {
queryWrapper.in(attributeName, fieldVal);
} else {
queryWrapper.notIn(attributeName, fieldVal);
}
} else {
throw new BadRequestException("NOT_IN类型的对象属性值必须是Long/Integer类型集合");
throw new BadRequestException("InOrNotIn查询参数类型的对象属性值必须是Long/Integer类型集合");
}
}
}
}
/**
* IN查询
*
* @param queryWrapper /
* @param fieldVal /
* @param finalAttributeName /
* @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 {
throw new BadRequestException("IN类型的对象属性值必须是Long/Integer类型集合");
}
private static <R> void handleBetweenQuery(QueryWrapper<R> queryWrapper, Object fieldVal, String finalAttributeName) {
if (fieldVal instanceof List) {
List<Object> between = new ArrayList<>((List<?>) fieldVal);
int minLength = 2;
if (CollectionUtil.isNotEmpty(between) && between.size() >= minLength) {
queryWrapper.between(finalAttributeName, between.get(0), between.get(1));
} else {
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());
queryWrapper.and(wrapper -> {
for (String blurryItem : blurryList) {
String column = humpToUnderline(blurryItem);
String column = StrUtil.toUnderlineCase(blurryItem);
wrapper.or();
wrapper.like(column, fieldVal.toString());
}
@@ -194,16 +177,6 @@ public class MybatisHelper {
return fields;
}
/***
* 驼峰命名转为下划线命名
*
* @param para
* 驼峰命名的字符串
*/
private static String humpToUnderline(String para) {
return StrUtil.toUnderlineCase(para);
}
@TableName("test_domain")
private static class TestDomain {
@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;
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.support.config.FastJsonConfig;
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;
}
@@ -46,7 +47,7 @@ public class ConfigurerAdapter implements WebMvcConfigurer {
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
FileProperties.ElPath path = properties.getPath();
FileUploadSettingModel.ElPath path = properties.getFile().getPath();
String avatarUtl = "file:" + path.getAvatar().replace("\\", "/");
String pathUtl = "file:" + path.getPath().replace("\\", "/");
registry.addResourceHandler("/avatar/**").addResourceLocations(avatarUtl).setCachePeriod(0);
@@ -42,7 +42,7 @@ public class SwaggerConfig {
@Value("${server.servlet.context-path:}")
private String apiPath;
@Value("${swagger.enabled}")
@Value("${app.swagger.enabled}")
private Boolean enabled;
private final ApplicationContext applicationContext;
@@ -1,5 +1,7 @@
package cn.odboy.thread;
import cn.odboy.config.AppProperties;
import cn.odboy.config.model.QuartzTaskThreadPoolSettingModel;
import com.alibaba.ttl.TtlRunnable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -21,7 +23,7 @@ import java.util.concurrent.atomic.AtomicInteger;
@Configuration
public class AsyncExecutor implements AsyncConfigurer {
@Autowired
private AsyncTaskProperties properties;
private AppProperties properties;
/**
* 自定义线程池,用法 @Async
@@ -30,11 +32,12 @@ public class AsyncExecutor implements AsyncConfigurer {
*/
@Override
public Executor getAsyncExecutor() {
QuartzTaskThreadPoolSettingModel asyncTaskPool = properties.getAsyncTaskPool();
// 自定义工厂
ThreadFactory factory = r -> new Thread(r, "default-async-" + new AtomicInteger(1).getAndIncrement());
// 自定义线程池
return new ThreadPoolExecutor(properties.getCorePoolSize(), properties.getMaxPoolSize(), properties.getKeepAliveSeconds(),
TimeUnit.SECONDS, new ArrayBlockingQueue<>(properties.getQueueCapacity()), factory,
return new ThreadPoolExecutor(asyncTaskPool.getCorePoolSize(), asyncTaskPool.getMaxPoolSize(), asyncTaskPool.getKeepAliveSeconds(),
TimeUnit.SECONDS, new ArrayBlockingQueue<>(asyncTaskPool.getQueueCapacity()), factory,
new ThreadPoolExecutor.CallerRunsPolicy());
}
@@ -43,13 +46,14 @@ public class AsyncExecutor implements AsyncConfigurer {
*/
@Bean("taskAsync")
public ThreadPoolTaskExecutor taskAsync() {
QuartzTaskThreadPoolSettingModel asyncTaskPool = properties.getAsyncTaskPool();
// 用法 private ThreadPoolTaskExecutor taskExecutor
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(properties.getCorePoolSize());
executor.setMaxPoolSize(properties.getMaxPoolSize());
executor.setQueueCapacity(properties.getQueueCapacity());
executor.setCorePoolSize(asyncTaskPool.getCorePoolSize());
executor.setMaxPoolSize(asyncTaskPool.getMaxPoolSize());
executor.setQueueCapacity(asyncTaskPool.getQueueCapacity());
executor.setThreadNamePrefix("task-async-");
executor.setKeepAliveSeconds(properties.getKeepAliveSeconds());
executor.setKeepAliveSeconds(asyncTaskPool.getKeepAliveSeconds());
// DiscardOldestPolicy,抛弃最早的任务,将新任务加入队列。
// AbortPolicy,拒绝执行新任务,并抛出异常。
// 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;
public enum WebSocketMsgTypeEnum {
public enum WebSocketMessageBizTypeEnum {
/**
* 连接
*/
@@ -1,6 +1,6 @@
package cn.odboy.websocket.context;
import cn.odboy.websocket.dto.WebSocketMsgDto;
import cn.odboy.websocket.dto.WebSocketMessageDto;
import com.alibaba.fastjson2.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@@ -88,8 +88,8 @@ public class WebSocketServer {
/**
* 群发自定义消息
*/
public static void sendMessage(WebSocketMsgDto webSocketMsgDto, @PathParam("sid") String sid) throws IOException {
String message = JSON.toJSONString(webSocketMsgDto);
public static void sendMessage(WebSocketMessageDto webSocketMessageDto, @PathParam("sid") String sid) throws IOException {
String message = JSON.toJSONString(webSocketMessageDto);
log.info("推送消息到{},推送内容:{}", sid, message);
try {
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.monitor.service.HealthCheckPointService;
@@ -7,7 +7,7 @@ import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
@Component
public class HealthCheckPointer implements HealthCheckPointService {
public class HealthCheckPointerImpl implements HealthCheckPointService {
@Autowired
private DictService dictService;
@@ -157,59 +157,59 @@ mybatis-plus:
# 是否控制台 print mybatis-plus 的 LOGO
banner: true
# 登录
login:
# 是否限制单用户登录
single-login: false
# 验证码
code:
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
height: 36
# 内容长度
length: 2
# 字体名称,为空则使用默认字体
font-name:
# 字体大小
font-size: 25
# 鉴权
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
# 文件存储路径
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:
app:
# 文件存储路径
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: false
# 验证码
captchaSetting:
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
height: 36
# 内容长度
length: 2
# 字体名称,为空则使用默认字体
font-name:
# 字体大小
font-size: 25
# 是否开启 swagger-ui
swagger:
enabled: true
# 针对@Async
async-task-pool:
# 核心线程池大小
core-pool-size: 10
# 最大线程数
@@ -218,16 +218,13 @@ task:
keep-alive-seconds: 60
# 队列容量
queue-capacity: 50
# 七牛云
qiniu:
# 文件大小 /M
max-size: 15
# 邮箱验证码有效时间/秒
code:
expiration: 300
# 密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
# oss
oss:
# 七牛云
qiniu:
# 文件大小 /M
max-size: 15
email:
captchaSetting:
# 邮箱验证码有效时间/秒
expiration: 300
@@ -3,6 +3,21 @@ server:
http2:
# 启用 HTTP/2 支持,提升传输效率
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:
# 启用 GZIP 压缩,减少传输数据量
enabled: true
@@ -38,16 +53,16 @@ spring:
datasource:
druid:
db-type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/cutejava20250321?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
driverClassName: com.p6spy.engine.spy.P6SpyDriver
url: jdbc:p6spy:mysql://127.0.0.1:3306/cutejava20250321?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false
username: root
password: 123456
# 初始连接数,建议设置为与最小空闲连接数相同
initial-size: 20
initial-size: 2
# 最小空闲连接数,保持足够的空闲连接以应对请求
min-idle: 20
min-idle: 2
# 最大连接数,根据并发需求适当增加
max-active: 50
max-active: 8
# 获取连接超时时间(毫秒),调整以满足响应时间要求
max-wait: 3000
# 启用KeepAlive机制,保持长连接
@@ -110,7 +125,6 @@ spring:
max-idle: 20
# 连接池中的最小空闲连接数
min-idle: 1
# 持久层
mybatis-plus:
configuration:
@@ -143,59 +157,59 @@ mybatis-plus:
# 是否控制台 print mybatis-plus 的 LOGO
banner: true
# 登录
login:
# 是否限制单用户登录
single-login: true
# 验证码
code:
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
height: 36
# 内容长度
length: 2
# 字体名称,为空则使用默认字体
font-name:
# 字体大小
font-size: 25
# 鉴权
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
# 文件存储路径
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:
app:
# 文件存储路径
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: true
# 验证码
captchaSetting:
# 验证码类型配置 查看 LoginProperties 类
code-type: arithmetic
# 登录图形验证码有效时间/分钟
expiration: 2
# 验证码高度
width: 111
# 验证码宽度
height: 36
# 内容长度
length: 2
# 字体名称,为空则使用默认字体
font-name:
# 字体大小
font-size: 25
# 是否开启 swagger-ui
swagger:
enabled: false
# 针对@Async
async-task-pool:
# 核心线程池大小
core-pool-size: 10
# 最大线程数
@@ -204,16 +218,13 @@ task:
keep-alive-seconds: 60
# 队列容量
queue-capacity: 50
# 七牛云
qiniu:
# 文件大小 /M
max-size: 15
# 邮箱验证码有效时间/秒
code:
expiration: 300
# 密码加密传输,前端公钥加密,后端私钥解密
rsa:
private_key: MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEA0vfvyTdGJkdbHkB8mp0f3FE0GYP3AYPaJF7jUd1M0XxFSE2ceK3k2kw20YvQ09NJKk+OMjWQl9WitG9pB6tSCQIDAQABAkA2SimBrWC2/wvauBuYqjCFwLvYiRYqZKThUS3MZlebXJiLB+Ue/gUifAAKIg1avttUZsHBHrop4qfJCwAI0+YRAiEA+W3NK/RaXtnRqmoUUkb59zsZUBLpvZgQPfj1MhyHDz0CIQDYhsAhPJ3mgS64NbUZmGWuuNKp5coY2GIj/zYDMJp6vQIgUueLFXv/eZ1ekgz2Oi67MNCk5jeTF2BurZqNLR3MSmUCIFT3Q6uHMtsB9Eha4u7hS31tj1UWE+D+ADzp59MGnoftAiBeHT7gDMuqeJHPL4b+kC+gzV4FGTfhR9q3tTbklZkD2A==
# oss
oss:
# 七牛云
qiniu:
# 文件大小 /M
max-size: 15
email:
captchaSetting:
# 邮箱验证码有效时间/秒
expiration: 300
@@ -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;
import cn.odboy.application.core.config.SecurityProperties;
import cn.odboy.application.core.service.impl.UserOnlineServiceImpl;
import cn.odboy.constant.RequestMethodEnum;
import cn.odboy.util.AnonTagUtil;
@@ -31,7 +30,6 @@ public class SpringSecurityConfig {
private final JwtAuthenticationEntryPoint authenticationErrorHandler;
private final JwtAccessDeniedHandler jwtAccessDeniedHandler;
private final ApplicationContext applicationContext;
private final SecurityProperties securityProperties;
private final UserOnlineServiceImpl onlineUserService;
@Bean
@@ -3,7 +3,7 @@ package cn.odboy.application.core.context;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
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.SystemRedisKey;
import cn.odboy.model.system.model.UserJwtModel;
@@ -39,13 +39,13 @@ public class TokenProvider implements InitializingBean {
private JwtParser jwtParser;
private JwtBuilder jwtBuilder;
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_UID_KEY = "userId";
@Override
public void afterPropertiesSet() {
byte[] keyBytes = Decoders.BASE64.decode(properties.getBase64Secret());
byte[] keyBytes = Decoders.BASE64.decode(properties.getJwt().getBase64Secret());
Key key = Keys.hmacShaKeyFor(keyBytes);
jwtParser = Jwts.parserBuilder()
.setSigningKey(key)
@@ -103,8 +103,8 @@ public class TokenProvider implements InitializingBean {
// 判断当前时间与过期时间的时间差
long differ = expireDate.getTime() - System.currentTimeMillis();
// 如果在续期检查的范围内,则续期
if (differ <= properties.getDetect()) {
long renew = time + properties.getRenew();
if (differ <= properties.getJwt().getDetect()) {
long renew = time + properties.getJwt().getRenew();
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.util.IdUtil;
import cn.odboy.annotation.AnonymousPostMapping;
import cn.odboy.application.core.config.CaptchaProperties;
import cn.odboy.application.core.config.LoginProperties;
import cn.odboy.application.core.constant.LoginCodeEnum;
import cn.odboy.constant.LoginCodeEnum;
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.UserOnlineServiceImpl;
import cn.odboy.base.PageResult;
import cn.odboy.constant.SystemConst;
import cn.odboy.constant.SystemRedisKey;
import cn.odboy.config.AppProperties;
import cn.odboy.context.SecurityHelper;
import cn.odboy.exception.BadRequestException;
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.response.UserInfoResponse;
import cn.odboy.properties.RsaProperties;
import cn.odboy.redis.RedisHelper;
import cn.odboy.util.RsaEncryptUtil;
import cn.odboy.util.StringUtil;
@@ -28,10 +23,8 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
@@ -58,8 +51,7 @@ public class AuthController {
private final RedisHelper redisHelper;
private final UserOnlineServiceImpl onlineUserService;
private final TokenProvider tokenProvider;
private final CaptchaProperties captchaProperties;
private final LoginProperties loginProperties;
private final AppProperties properties;
private final PasswordEncoder passwordEncoder;
private final UserDetailsServiceImpl userDetailsService;
@@ -67,7 +59,7 @@ public class AuthController {
@AnonymousPostMapping(value = "/login")
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);
// 清除验证码
@@ -93,7 +85,7 @@ public class AuthController {
put("token", String.format("%s %s", SystemConst.TOKEN_PREFIX, token));
put("user", BeanUtil.copyProperties(jwtUser, UserInfoResponse.class));
}};
if (loginProperties.isSingleLogin()) {
if (properties.getLogin().isSingle()) {
// 踢掉之前已经登录的token
onlineUserService.kickOutByUsername(loginRequest.getUsername());
}
@@ -115,7 +107,7 @@ public class AuthController {
@AnonymousPostMapping(value = "/code")
public ResponseEntity<Object> getCode() {
// 获取运算的结果
Captcha captcha = captchaProperties.getCaptcha();
Captcha captcha = properties.getLogin().getCaptchaSetting().getCaptcha();
String uuid = SystemRedisKey.CAPTCHA_LOGIN + IdUtil.simpleUUID();
//当验证码类型为 arithmetic时且长度 >= 2 时,captcha.text()的结果有几率为浮点型
String captchaValue = captcha.text();
@@ -123,7 +115,7 @@ public class AuthController {
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) {{
put("img", captcha.toBase64());
@@ -1,9 +1,9 @@
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.service.UserOnlineService;
import cn.odboy.base.PageResult;
import cn.odboy.config.AppProperties;
import cn.odboy.constant.SystemRedisKey;
import cn.odboy.model.system.model.UserJwtModel;
import cn.odboy.model.system.model.UserOnlineModel;
@@ -34,7 +34,7 @@ import java.util.concurrent.TimeUnit;
@Slf4j
@AllArgsConstructor
public class UserOnlineServiceImpl implements UserOnlineService {
private final SecurityProperties properties;
private final AppProperties properties;
private final TokenProvider tokenProvider;
private final RedisHelper redisHelper;
@@ -61,7 +61,7 @@ public class UserOnlineServiceImpl implements UserOnlineService {
log.error(e.getMessage(), e);
}
String loginKey = tokenProvider.loginKey(token);
redisHelper.set(loginKey, userOnlineModel, properties.getTokenValidityInSeconds(), TimeUnit.MILLISECONDS);
redisHelper.set(loginKey, userOnlineModel, properties.getJwt().getTokenValidityInSeconds(), TimeUnit.MILLISECONDS);
}
@Override
@@ -2,8 +2,7 @@ package cn.odboy.application.system.rest;
import cn.odboy.application.tools.service.CaptchaService;
import cn.odboy.application.tools.service.EmailService;
import cn.odboy.constant.CodeBiEnum;
import cn.odboy.constant.CodeEnum;
import cn.odboy.constant.CaptchaBizEnum;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
@@ -31,27 +30,27 @@ public class CaptchaController {
@ApiOperation("重置邮箱,发送验证码")
@PostMapping(value = "/sendResetEmailCaptcha")
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);
}
@ApiOperation("重置密码,发送验证码")
@PostMapping(value = "/sendResetPasswordCaptcha")
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);
}
@ApiOperation("验证码验证")
@PostMapping(value = "/checkCodeAvailable")
public ResponseEntity<Object> checkCodeAvailable(@RequestParam String email, @RequestParam String code, @RequestParam Integer codeBi) {
CodeBiEnum biEnum = CodeBiEnum.find(codeBi);
public ResponseEntity<Object> checkCodeAvailable(@RequestParam String email, @RequestParam String code, @RequestParam String codeBi) {
CaptchaBizEnum biEnum = CaptchaBizEnum.getByBizCode(codeBi);
switch (Objects.requireNonNull(biEnum)) {
case ONE:
captchaService.checkCodeAvailable(CodeEnum.EMAIL_RESET_EMAIL_CODE.getKey(), email, code);
case EMAIL_RESET_EMAIL_CODE:
captchaService.checkCodeAvailable(CaptchaBizEnum.EMAIL_RESET_EMAIL_CODE.getBizCode(), email, code);
break;
case TWO:
captchaService.checkCodeAvailable(CodeEnum.EMAIL_RESET_PWD_CODE.getKey(), email, code);
case EMAIL_RESET_PWD_CODE:
captchaService.checkCodeAvailable(CaptchaBizEnum.EMAIL_RESET_PWD_CODE.getBizCode(), email, code);
break;
default:
break;
@@ -8,7 +8,8 @@ import cn.odboy.application.system.service.UserService;
import cn.odboy.application.tools.service.CaptchaService;
import cn.odboy.base.MyMetaOption;
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.exception.BadRequestException;
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.request.QueryUserRequest;
import cn.odboy.model.system.response.UpdateUserPasswordResponse;
import cn.odboy.properties.RsaProperties;
import cn.odboy.util.PageUtil;
import cn.odboy.util.RsaEncryptUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@@ -59,6 +59,7 @@ public class UserController {
private final DeptService deptService;
private final RoleService roleService;
private final CaptchaService verificationCodeService;
private final AppProperties properties;
@ApiOperation("导出用户数据")
@GetMapping(value = "/download")
@@ -144,8 +145,8 @@ public class UserController {
@ApiOperation("修改密码")
@PostMapping(value = "/modifyUserPasswordByUsername")
public ResponseEntity<Object> modifyUserPasswordByUsername(@RequestBody UpdateUserPasswordResponse passVo) throws Exception {
String oldPass = RsaEncryptUtil.decryptByPrivateKey(RsaProperties.privateKey, passVo.getOldPass());
String newPass = RsaEncryptUtil.decryptByPrivateKey(RsaProperties.privateKey, passVo.getNewPass());
String oldPass = RsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getOldPass());
String newPass = RsaEncryptUtil.decryptByPrivateKey(properties.getRsa().getPrivateKey(), passVo.getNewPass());
User user = userService.describeUserByUsername(SecurityHelper.getCurrentUsername());
if (!passwordEncoder.matches(oldPass, user.getPassword())) {
throw new BadRequestException("修改失败,旧密码错误");
@@ -174,12 +175,12 @@ public class UserController {
@ApiOperation("修改邮箱")
@PostMapping(value = "/modifyUserEmailByUsername/{code}")
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());
if (!passwordEncoder.matches(password, user.getPassword())) {
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());
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.service.UserService;
import cn.odboy.base.PageResult;
import cn.odboy.config.AppProperties;
import cn.odboy.constant.SystemRedisKey;
import cn.odboy.context.SecurityHelper;
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.User;
import cn.odboy.model.system.request.QueryUserRequest;
import cn.odboy.properties.FileProperties;
import cn.odboy.redis.RedisHelper;
import cn.odboy.util.FileUtil;
import cn.odboy.util.PageUtil;
@@ -47,7 +47,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
private final UserMapper userMapper;
private final UserJobMapper userJobMapper;
private final UserRoleMapper userRoleMapper;
private final FileProperties fileProperties;
private final AppProperties properties;
private final RedisHelper redisHelper;
private final UserCacheService userCacheService;
private final UserOnlineService userOnlineService;
@@ -211,7 +211,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
@Transactional(rollbackFor = Exception.class)
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 fileType = FileUtil.getSuffix(multipartFile.getOriginalFilename());
@@ -220,7 +220,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
}
User user = userMapper.getUserByUsername(SecurityHelper.getCurrentUsername());
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.setAvatarName(file.getName());
saveOrUpdate(user);
@@ -1,6 +1,6 @@
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.base.PageResult;
import cn.odboy.model.tools.domain.QiniuConfig;
@@ -38,7 +38,7 @@ import java.util.Map;
@Api(tags = "工具:七牛云存储管理")
public class QiniuController {
private final QiniuContentService qiniuContentService;
private final QiNiuConfigService qiNiuConfigService;
private final QiniuConfigService qiNiuConfigService;
@ApiOperation("查询七牛云存储配置")
@PostMapping(value = "/describeQiniuConfig")
@@ -4,7 +4,7 @@ import cn.odboy.model.tools.domain.QiniuConfig;
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
public class CaptchaServiceImpl implements CaptchaService {
private final RedisHelper redisHelper;
@Value("${code.expiration}")
@Value("${app.email.captchaSetting.expiration}")
private Long expiration;
@Override
@@ -4,10 +4,10 @@ import cn.hutool.core.util.ObjectUtil;
import cn.odboy.application.tools.mapper.LocalStorageMapper;
import cn.odboy.application.tools.service.LocalStorageService;
import cn.odboy.base.PageResult;
import cn.odboy.config.AppProperties;
import cn.odboy.exception.BadRequestException;
import cn.odboy.model.tools.domain.LocalStorage;
import cn.odboy.model.tools.request.QueryLocalStorageRequest;
import cn.odboy.properties.FileProperties;
import cn.odboy.util.FileUtil;
import cn.odboy.util.PageUtil;
import cn.odboy.util.StringUtil;
@@ -29,9 +29,8 @@ import java.util.Map;
@Service
@RequiredArgsConstructor
public class LocalStorageServiceImpl extends ServiceImpl<LocalStorageMapper, LocalStorage> implements LocalStorageService {
private final LocalStorageMapper localStorageMapper;
private final FileProperties properties;
private final AppProperties properties;
@Override
public PageResult<LocalStorage> describeLocalStoragePage(QueryLocalStorageRequest criteria, Page<Object> page) {
@@ -47,10 +46,10 @@ public class LocalStorageServiceImpl extends ServiceImpl<LocalStorageMapper, Loc
@Transactional(rollbackFor = Exception.class)
public LocalStorage uploadFile(String name, MultipartFile multipartFile) {
long size = multipartFile.getSize();
FileUtil.checkSize(properties.getMaxSize(), size);
FileUtil.checkSize(properties.getFile().getFileMaxSize(), size);
String suffix = FileUtil.getSuffix(multipartFile.getOriginalFilename());
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)) {
throw new BadRequestException("上传失败");
}
@@ -1,7 +1,7 @@
package cn.odboy.application.tools.service.impl;
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.exception.BadRequestException;
import cn.odboy.model.tools.domain.QiniuConfig;
@@ -17,7 +17,7 @@ import org.springframework.transaction.annotation.Transactional;
@Service
@RequiredArgsConstructor
@CacheConfig(cacheNames = "qiNiu")
public class QiNiuConfigServiceImpl extends ServiceImpl<QiniuConfigMapper, QiniuConfig> implements QiNiuConfigService {
public class QiniuConfigServiceImpl extends ServiceImpl<QiniuConfigMapper, QiniuConfig> implements QiniuConfigService {
@Override
@Cacheable(key = "'config'")
public QiniuConfig describeQiniuConfig() {
@@ -1,9 +1,9 @@
package cn.odboy.application.tools.service.impl;
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.util.QiNiuUtil;
import cn.odboy.application.tools.util.QiniuUtil;
import cn.odboy.base.PageResult;
import cn.odboy.exception.BadRequestException;
import cn.odboy.model.tools.domain.QiniuConfig;
@@ -40,9 +40,9 @@ import java.util.Map;
@CacheConfig(cacheNames = "qiNiu")
public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, QiniuContent> implements QiniuContentService {
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;
@Override
@@ -64,14 +64,14 @@ public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, Qin
throw new BadRequestException("请先添加相应配置,再操作");
}
// 构造一个带指定Zone对象的配置类
Configuration cfg = new Configuration(QiNiuUtil.getRegion(qiniuConfig.getZone()));
Configuration cfg = new Configuration(QiniuUtil.getRegion(qiniuConfig.getZone()));
UploadManager uploadManager = new UploadManager(cfg);
Auth auth = Auth.create(qiniuConfig.getAccessKey(), qiniuConfig.getSecretKey());
String upToken = auth.uploadToken(qiniuConfig.getBucket());
try {
String key = file.getOriginalFilename();
if (qiniuContentMapper.getQiniuContentByName(key) != null) {
key = QiNiuUtil.getKey(key);
key = QiniuUtil.getKey(key);
}
Response response = uploadManager.put(file.getBytes(), key, upToken);
// 解析上传成功的结果
@@ -120,7 +120,7 @@ public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, Qin
throw new BadRequestException("文件不存在");
}
// 构造一个带指定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());
BucketManager bucketManager = new BucketManager(auth, cfg);
try {
@@ -140,7 +140,7 @@ public class QiniuContentServiceImpl extends ServiceImpl<QiniuContentMapper, Qin
throw new BadRequestException("请先添加相应配置,再操作");
}
//构造一个带指定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());
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 = "华东";