merge 合并5.x分支代码

This commit is contained in:
gssong
2023-07-29 13:41:38 +08:00
370 changed files with 9390 additions and 41015 deletions

View File

@@ -34,6 +34,11 @@
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--常用工具类 -->
<dependency>
<groupId>org.apache.commons</groupId>

View File

@@ -2,16 +2,14 @@ package org.dromara.common.core.config;
import cn.hutool.core.util.ArrayUtil;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.SpringUtils;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.scheduling.annotation.AsyncConfigurer;
import org.springframework.scheduling.annotation.EnableAsync;
import java.util.Arrays;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
/**
* 异步配置
@@ -22,16 +20,12 @@ import java.util.concurrent.ScheduledExecutorService;
@AutoConfiguration
public class AsyncConfig implements AsyncConfigurer {
@Autowired
@Qualifier("scheduledExecutorService")
private ScheduledExecutorService scheduledExecutorService;
/**
* 自定义 @Async 注解使用系统线程池
*/
@Override
public Executor getAsyncExecutor() {
return scheduledExecutorService;
return SpringUtils.getBean("scheduledExecutorService");
}
/**

View File

@@ -22,18 +22,19 @@ public class ValidatorConfig {
*/
@Bean
public Validator validator(MessageSource messageSource) {
LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean();
// 国际化
factoryBean.setValidationMessageSource(messageSource);
// 设置使用 HibernateValidator 校验器
factoryBean.setProviderClass(HibernateValidator.class);
Properties properties = new Properties();
// 设置 快速异常返回
properties.setProperty("hibernate.validator.fail_fast", "true");
factoryBean.setValidationProperties(properties);
// 加载配置
factoryBean.afterPropertiesSet();
return factoryBean.getValidator();
try (LocalValidatorFactoryBean factoryBean = new LocalValidatorFactoryBean()) {
// 国际化
factoryBean.setValidationMessageSource(messageSource);
// 设置使用 HibernateValidator 校验器
factoryBean.setProviderClass(HibernateValidator.class);
Properties properties = new Properties();
// 设置 快速异常返回
properties.setProperty("hibernate.validator.fail_fast", "true");
factoryBean.setValidationProperties(properties);
// 加载配置
factoryBean.afterPropertiesSet();
return factoryBean.getValidator();
}
}
}

View File

@@ -31,4 +31,9 @@ public interface GlobalConstants {
* 登录账户密码错误次数 redis key
*/
String PWD_ERR_CNT_KEY = GLOBAL_REDIS_KEY + "pwd_err_cnt:";
/**
* 三方认证 redis key
*/
String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:";
}

View File

@@ -1,7 +1,9 @@
package org.dromara.common.core.domain.model;
import jakarta.validation.constraints.Email;
import org.dromara.common.core.constant.UserConstants;
import lombok.Data;
import org.dromara.common.core.validate.auth.*;
import org.hibernate.validator.constraints.Length;
import jakarta.validation.constraints.NotBlank;
@@ -15,6 +17,28 @@ import jakarta.validation.constraints.NotBlank;
@Data
public class LoginBody {
/**
* 客户端id
*/
@NotBlank(message = "{auth.clientid.not.blank}")
private String clientId;
/**
* 客户端key
*/
private String clientKey;
/**
* 客户端秘钥
*/
private String clientSecret;
/**
* 授权类型
*/
@NotBlank(message = "{auth.grant.type.not.blank}")
private String grantType;
/**
* 租户ID
*/
@@ -24,15 +48,15 @@ public class LoginBody {
/**
* 用户名
*/
@NotBlank(message = "{user.username.not.blank}")
@Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}")
@NotBlank(message = "{user.username.not.blank}", groups = {PasswordGroup.class})
@Length(min = UserConstants.USERNAME_MIN_LENGTH, max = UserConstants.USERNAME_MAX_LENGTH, message = "{user.username.length.valid}", groups = {PasswordGroup.class})
private String username;
/**
* 用户密码
*/
@NotBlank(message = "{user.password.not.blank}")
@Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}")
@NotBlank(message = "{user.password.not.blank}", groups = {PasswordGroup.class})
@Length(min = UserConstants.PASSWORD_MIN_LENGTH, max = UserConstants.PASSWORD_MAX_LENGTH, message = "{user.password.length.valid}", groups = {PasswordGroup.class})
private String password;
/**
@@ -45,4 +69,52 @@ public class LoginBody {
*/
private String uuid;
/**
* 手机号
*/
@NotBlank(message = "{user.phonenumber.not.blank}", groups = {SmsGroup.class})
private String phonenumber;
/**
* 短信code
*/
@NotBlank(message = "{sms.code.not.blank}", groups = {SmsGroup.class})
private String smsCode;
/**
* 邮箱
*/
@NotBlank(message = "{user.email.not.blank}", groups = {EmailGroup.class})
@Email(message = "{user.email.not.valid}")
private String email;
/**
* 邮箱code
*/
@NotBlank(message = "{email.code.not.blank}", groups = {EmailGroup.class})
private String emailCode;
/**
* 小程序code
*/
@NotBlank(message = "{xcx.code.not.blank}", groups = {WechatGroup.class})
private String xcxCode;
/**
* 第三方登录平台
*/
@NotBlank(message = "{social.source.not.blank}" , groups = {SocialGroup.class})
private String source;
/**
* 第三方登录code
*/
@NotBlank(message = "{social.code.not.blank}" , groups = {SocialGroup.class})
private String socialCode;
/**
* 第三方登录socialState
*/
@NotBlank(message = "{social.state.not.blank}" , groups = {SocialGroup.class})
private String socialState;
}

View File

@@ -0,0 +1,21 @@
package org.dromara.common.core.domain.model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
/**
* 第三方登录用户身份权限
*
* @author thiszhc is 三三
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
public class SocialLogin extends LoginUser{
/**
* openid
*/
private String openid;
}

View File

@@ -26,7 +26,12 @@ public enum DeviceType {
/**
* 小程序端
*/
XCX("xcx");
XCX("xcx"),
/**
* social第三方端
*/
SOCIAL("social");
private final String device;
}

View File

@@ -1,5 +1,10 @@
package org.dromara.common.core.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.io.Serial;
/**
@@ -7,6 +12,10 @@ import java.io.Serial;
*
* @author ruoyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class GlobalException extends RuntimeException {
@Serial
@@ -22,12 +31,6 @@ public class GlobalException extends RuntimeException {
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public GlobalException() {
}
public GlobalException(String message) {
this.message = message;
}

View File

@@ -1,5 +1,10 @@
package org.dromara.common.core.exception;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import java.io.Serial;
/**
@@ -7,6 +12,10 @@ import java.io.Serial;
*
* @author ruoyi
*/
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public final class ServiceException extends RuntimeException {
@Serial
@@ -27,12 +36,6 @@ public final class ServiceException extends RuntimeException {
*/
private String detailMessage;
/**
* 空构造方法,避免反序列化问题
*/
public ServiceException() {
}
public ServiceException(String message) {
this.message = message;
}

View File

@@ -1,5 +1,6 @@
package org.dromara.common.core.exception.base;
import lombok.AllArgsConstructor;
import org.dromara.common.core.utils.MessageUtils;
import org.dromara.common.core.utils.StringUtils;
import lombok.Data;
@@ -16,6 +17,7 @@ import java.io.Serial;
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
@AllArgsConstructor
public class BaseException extends RuntimeException {
@Serial
@@ -41,13 +43,6 @@ public class BaseException extends RuntimeException {
*/
private String defaultMessage;
public BaseException(String module, String code, Object[] args, String defaultMessage) {
this.module = module;
this.code = code;
this.args = args;
this.defaultMessage = defaultMessage;
}
public BaseException(String module, String code, Object[] args) {
this(module, code, args, null);
}

View File

@@ -0,0 +1,31 @@
package org.dromara.common.core.factory;
import org.dromara.common.core.utils.StringUtils;
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.DefaultPropertySourceFactory;
import org.springframework.core.io.support.EncodedResource;
import java.io.IOException;
/**
* yml 配置源工厂
*
* @author Lion Li
*/
public class YmlPropertySourceFactory extends DefaultPropertySourceFactory {
@Override
public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
String sourceName = resource.getResource().getFilename();
if (StringUtils.isNotBlank(sourceName) && StringUtils.endsWithAny(sourceName, ".yml", ".yaml")) {
YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean();
factory.setResources(resource.getResource());
factory.afterPropertiesSet();
return new PropertiesPropertySource(sourceName, factory.getObject());
}
return super.createPropertySource(name, resource);
}
}

View File

@@ -1,5 +1,7 @@
package org.dromara.common.core.service;
import java.util.Map;
/**
* 通用 字典服务
*
@@ -54,4 +56,12 @@ public interface DictService {
*/
String getDictValue(String dictType, String dictLabel, String separator);
/**
* 获取字典下所有的字典值与标签
*
* @param dictType 字典类型
* @return dictValue为keydictLabel为值组成的Map
*/
Map<String, String> getAllDictByDictType(String dictType);
}

View File

@@ -3,6 +3,7 @@ package org.dromara.common.core.utils;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.context.MessageSource;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.i18n.LocaleContextHolder;
/**
@@ -23,6 +24,10 @@ public class MessageUtils {
* @return 获取国际化翻译值
*/
public static String message(String code, Object... args) {
return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale());
try {
return MESSAGE_SOURCE.getMessage(code, args, LocaleContextHolder.getLocale());
} catch (NoSuchMessageException e) {
return code;
}
}
}

View File

@@ -10,6 +10,7 @@ import jakarta.servlet.http.HttpSession;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.util.LinkedCaseInsensitiveMap;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
@@ -19,6 +20,7 @@ import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
@@ -101,14 +103,22 @@ public class ServletUtils extends JakartaServletUtil {
* 获取request
*/
public static HttpServletRequest getRequest() {
return getRequestAttributes().getRequest();
try {
return getRequestAttributes().getRequest();
} catch (Exception e) {
return null;
}
}
/**
* 获取response
*/
public static HttpServletResponse getResponse() {
return getRequestAttributes().getResponse();
try {
return getRequestAttributes().getResponse();
} catch (Exception e) {
return null;
}
}
/**
@@ -119,8 +129,33 @@ public class ServletUtils extends JakartaServletUtil {
}
public static ServletRequestAttributes getRequestAttributes() {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
try {
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
return (ServletRequestAttributes) attributes;
} catch (Exception e) {
return null;
}
}
public static String getHeader(HttpServletRequest request, String name) {
String value = request.getHeader(name);
if (StringUtils.isEmpty(value)) {
return StringUtils.EMPTY;
}
return urlDecode(value);
}
public static Map<String, String> getHeaders(HttpServletRequest request) {
Map<String, String> map = new LinkedCaseInsensitiveMap<>();
Enumeration<String> enumeration = request.getHeaderNames();
if (enumeration != null) {
while (enumeration.hasMoreElements()) {
String key = enumeration.nextElement();
String value = request.getHeader(key);
map.put(key, value);
}
}
return map;
}
/**

View File

@@ -72,7 +72,7 @@ public class StreamUtils {
return CollUtil.newArrayList();
}
// 注意此处不要使用 .toList() 新语法 因为返回的是不可变List 会导致序列化问题
return collection.stream().sorted(comparing).collect(Collectors.toList());
return collection.stream().filter(Objects::nonNull).sorted(comparing).collect(Collectors.toList());
}
/**
@@ -89,7 +89,7 @@ public class StreamUtils {
if (CollUtil.isEmpty(collection)) {
return MapUtil.newHashMap();
}
return collection.stream().collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
return collection.stream().filter(Objects::nonNull).collect(Collectors.toMap(key, Function.identity(), (l, r) -> l));
}
/**
@@ -108,7 +108,7 @@ public class StreamUtils {
if (CollUtil.isEmpty(collection)) {
return MapUtil.newHashMap();
}
return collection.stream().collect(Collectors.toMap(key, value, (l, r) -> l));
return collection.stream().filter(Objects::nonNull).collect(Collectors.toMap(key, value, (l, r) -> l));
}
/**
@@ -126,7 +126,7 @@ public class StreamUtils {
return MapUtil.newHashMap();
}
return collection
.stream()
.stream().filter(Objects::nonNull)
.collect(Collectors.groupingBy(key, LinkedHashMap::new, Collectors.toList()));
}
@@ -147,7 +147,7 @@ public class StreamUtils {
return MapUtil.newHashMap();
}
return collection
.stream()
.stream().filter(Objects::nonNull)
.collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.groupingBy(key2, LinkedHashMap::new, Collectors.toList())));
}
@@ -168,7 +168,7 @@ public class StreamUtils {
return MapUtil.newHashMap();
}
return collection
.stream()
.stream().filter(Objects::nonNull)
.collect(Collectors.groupingBy(key1, LinkedHashMap::new, Collectors.toMap(key2, Function.identity(), (l, r) -> l)));
}

View File

@@ -0,0 +1,7 @@
package org.dromara.common.core.validate.auth;
/**
* @Author Michelle.Chung
*/
public interface EmailGroup {
}

View File

@@ -0,0 +1,7 @@
package org.dromara.common.core.validate.auth;
/**
* @Author Michelle.Chung
*/
public interface PasswordGroup {
}

View File

@@ -0,0 +1,7 @@
package org.dromara.common.core.validate.auth;
/**
* @Author Michelle.Chung
*/
public interface SmsGroup {
}

View File

@@ -0,0 +1,4 @@
package org.dromara.common.core.validate.auth;
public interface SocialGroup {
}

View File

@@ -0,0 +1,7 @@
package org.dromara.common.core.validate.auth;
/**
* @Author Michelle.Chung
*/
public interface WechatGroup {
}