5 Commits

57 changed files with 279 additions and 388 deletions

View File

@@ -44,12 +44,12 @@
<dependency> <dependency>
<groupId>xyz.zhouxy.plusone</groupId> <groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-validator</artifactId> <artifactId>plusone-validator</artifactId>
<version>0.1.3-SNAPSHOT</version> <version>0.1.2-SNAPSHOT</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>xyz.zhouxy.plusone</groupId> <groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-exception-handler</artifactId> <artifactId>plusone-exception-handler</artifactId>
<version>0.0.8-SNAPSHOT</version> <version>0.0.6-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -2,8 +2,4 @@ package xyz.zhouxy.plusone.constant;
public class ErrorCodeConsts { public class ErrorCodeConsts {
public static final int DEFAULT_ERROR_CODE = 9999999; public static final int DEFAULT_ERROR_CODE = 9999999;
private ErrorCodeConsts() {
throw new IllegalStateException("Utility class");
}
} }

View File

@@ -1,18 +0,0 @@
package xyz.zhouxy.plusone.util;
import java.util.concurrent.ThreadLocalRandom;
public final class RandomUtil {
private RandomUtil() {
throw new IllegalStateException("Utility class");
}
public static String randomStr(char[] sourceCharacters, int length) {
ThreadLocalRandom random = ThreadLocalRandom.current();
char[] result = new char[length];
for (int i = 0; i < length; i++) {
result[i] = sourceCharacters[random.nextInt(sourceCharacters.length)];
}
return String.valueOf(result);
}
}

View File

@@ -1,23 +0,0 @@
package xyz.zhouxy.plusone.util;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
import lombok.extern.slf4j.Slf4j;
@Slf4j
class RandomUtilTests {
@Test
void testRandom() {
String[] s = new String[20];
for (int i = 0; i < 20; i++) {
s[i] = RandomUtil.randomStr(
"0123456789qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM~`!@#$%^&*()_-+={[\\|/:;\"',.<>?]}"
.toCharArray(),
28);
}
log.info("{}", Arrays.toString(s));
}
}

View File

@@ -15,6 +15,11 @@
<groupId>xyz.zhouxy</groupId> <groupId>xyz.zhouxy</groupId>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.projectlombok</groupId> <groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId> <artifactId>lombok</artifactId>
@@ -23,10 +28,12 @@
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId> <artifactId>jackson-core</artifactId>
<version>2.13.4</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.fasterxml.jackson.core</groupId> <groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId> <artifactId>jackson-annotations</artifactId>
</dependency> <version>2.13.4</version>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -1,9 +1,5 @@
package xyz.zhouxy.plusone.constant; package xyz.zhouxy.plusone.constant;
import java.util.Collection;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.util.Enumeration; import xyz.zhouxy.plusone.commons.util.Enumeration;
/** /**
@@ -11,26 +7,26 @@ import xyz.zhouxy.plusone.commons.util.Enumeration;
* *
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a> * @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/ */
public final class EntityStatus extends Enumeration<EntityStatus> { public class EntityStatus extends Enumeration<EntityStatus> {
private EntityStatus(int id, @Nonnull String name) { private EntityStatus(int value, String name) {
super(id, name); super(value, name);
} }
// 常量 // 常量
public static final EntityStatus AVAILABLE = new EntityStatus(0, "正常"); public static final EntityStatus AVAILABLE = new EntityStatus(0, "正常");
public static final EntityStatus DISABLED = new EntityStatus(1, "禁用"); public static final EntityStatus DISABLED = new EntityStatus(1, "禁用");
private static final ValueSet<EntityStatus> VALUE_SET = new ValueSet<>( private static final EnumerationValuesHolder<EntityStatus> ENUMERATION_VALUES = new EnumerationValuesHolder<>(
AVAILABLE, DISABLED); AVAILABLE,
DISABLED);
@Nonnull public static EntityStatus of(int value) {
public static EntityStatus of(int id) { return ENUMERATION_VALUES.get(value);
return VALUE_SET.get(id);
} }
@Nonnull @Override
public static Collection<EntityStatus> constants() { public String toString() {
return VALUE_SET.getValues(); return "EntityStatus" + super.toString();
} }
} }

View File

@@ -0,0 +1,27 @@
package xyz.zhouxy.plusone.constant;
/**
* 正则表达式常量
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public final class RegexConsts {
public static final String DATE = "^\\d{4}-\\d{2}-\\d{2}";
public static final String PASSWORD = "^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z])[\\w\\\\!#$%&'*\\+\\-/=?^`{|}~@\\(\\)\\[\\]\",\\.;':><]{8,32}$";
public static final String CAPTCHA = "^[0-9A-Za-z]{4,6}$";
public static final String EMAIL = "^\\w+([-+.]\\w+)*@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})*(\\.(?![0-9]+$)[a-zA-Z0-9][-0-9A-Za-z]{0,62})$";
public static final String MOBILE_PHONE = "^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\\d{8}$";
public static final String USERNAME = "^[\\da-zA-Z_.@\\\\]{4,36}$";
public static final String NICKNAME = "^[\\da-zA-Z_.@\\\\]{4,36}$";
private RegexConsts() {
throw new IllegalStateException("Utility class");
}
}

View File

@@ -1,7 +1,6 @@
package xyz.zhouxy.plusone.domain; package xyz.zhouxy.plusone.domain;
import java.util.UUID; import cn.hutool.core.lang.UUID;
import lombok.Getter; import lombok.Getter;
/** /**
@@ -21,7 +20,7 @@ public abstract class DomainEvent {
private long happenedAt; private long happenedAt;
protected DomainEvent() { protected DomainEvent() {
this.identifier = UUID.randomUUID().toString(); this.identifier = UUID.randomUUID().toString(true);
this.happenedAt = System.currentTimeMillis(); this.happenedAt = System.currentTimeMillis();
} }
} }

View File

@@ -1,7 +1,6 @@
package xyz.zhouxy.plusone.domain; package xyz.zhouxy.plusone.domain;
import java.util.Optional; import java.util.Optional;
import java.util.regex.Pattern;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue; import com.fasterxml.jackson.annotation.JsonValue;
@@ -14,15 +13,15 @@ import com.fasterxml.jackson.annotation.JsonValue;
public abstract class ValidatableStringRecord implements IValueObject { public abstract class ValidatableStringRecord implements IValueObject {
protected String value; protected String value;
protected final Pattern format; protected final String format;
protected ValidatableStringRecord(Pattern format) { protected ValidatableStringRecord(String format) {
this.format = format; this.format = format;
} }
@JsonIgnore @JsonIgnore
protected boolean isValid() { protected boolean isValid() {
return format.matcher(value).matches(); return value.matches(format);
} }
@JsonValue @JsonValue
@@ -36,6 +35,6 @@ public abstract class ValidatableStringRecord implements IValueObject {
} }
public static String getValueOrNull(Optional<? extends ValidatableStringRecord> s) { public static String getValueOrNull(Optional<? extends ValidatableStringRecord> s) {
return s.isPresent() ? s.get().value() : null; return s.map(ValidatableStringRecord::value).orElse(null);
} }
} }

View File

@@ -14,7 +14,6 @@ import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.util.CollectionUtils;
import xyz.zhouxy.plusone.commons.util.NumberUtil; import xyz.zhouxy.plusone.commons.util.NumberUtil;
import xyz.zhouxy.plusone.exception.DataOperationResultException; import xyz.zhouxy.plusone.exception.DataOperationResultException;
@@ -69,13 +68,13 @@ public abstract class PlusoneJdbcDaoSupport {
return queryForStream(sql, new MapSqlParameterSource(paramName, value), elementType); return queryForStream(sql, new MapSqlParameterSource(paramName, value), elementType);
} }
protected final boolean queryForBool(String sql, SqlParameterSource parameterSource) { protected final boolean queryExists(String sql, SqlParameterSource parameterSource) {
Boolean result = this.jdbc.queryForObject(sql, parameterSource, Boolean.TYPE); Boolean isExists = this.jdbc.queryForObject(sql, parameterSource, Boolean.TYPE);
return Boolean.TRUE.equals(result); return Boolean.TRUE.equals(isExists);
} }
protected final boolean queryForBool(String sql, String paramName, Object value) { protected final boolean queryExists(String sql, String paramName, Object value) {
return queryForBool(sql, new MapSqlParameterSource(paramName, value)); return queryExists(sql, new MapSqlParameterSource(paramName, value));
} }
protected final int update(String sql, SqlParameterSource parameterSource) { protected final int update(String sql, SqlParameterSource parameterSource) {
@@ -86,18 +85,18 @@ public abstract class PlusoneJdbcDaoSupport {
return update(sql, new MapSqlParameterSource(paramName, value)); return update(sql, new MapSqlParameterSource(paramName, value));
} }
protected final long batchUpdate(String sql, SqlParameterSource[] batchArgs) { protected final int batchUpdate(String sql, SqlParameterSource[] batchArgs) {
int[] i = this.jdbc.batchUpdate(sql, batchArgs); int[] i = this.jdbc.batchUpdate(sql, batchArgs);
return NumberUtil.sum(i); return NumberUtil.sum(i);
} }
protected final <T> long batchUpdate(String sql, Stream<T> c, protected final <T> int batchUpdate(String sql, Stream<T> c,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) { @Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder)); int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder));
return NumberUtil.sum(i); return NumberUtil.sum(i);
} }
protected final <T> long batchUpdate(String sql, Collection<T> c, protected final <T> int batchUpdate(String sql, Collection<T> c,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) { @Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder)); int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder));
return NumberUtil.sum(i); return NumberUtil.sum(i);
@@ -157,7 +156,7 @@ public abstract class PlusoneJdbcDaoSupport {
protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray( protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray(
Collection<T> c, Collection<T> c,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) { @Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
if (CollectionUtils.isEmpty(c)) { if (c == null || c.isEmpty()) {
return new SqlParameterSource[] {}; return new SqlParameterSource[] {};
} }
return buildSqlParameterSourceArray(c.stream(), paramSourceBuilder); return buildSqlParameterSourceArray(c.stream(), paramSourceBuilder);

View File

@@ -6,7 +6,6 @@ package xyz.zhouxy.plusone.oss;
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a> * @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/ */
public class FastDFSException extends Exception { public class FastDFSException extends Exception {
private static final long serialVersionUID = 7871031982887742468L;
public FastDFSException() { public FastDFSException() {
} }

View File

@@ -1,7 +1,5 @@
package xyz.zhouxy.plusone.sms; package xyz.zhouxy.plusone.sms;
import org.springframework.stereotype.Service;
import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException; import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile; import com.tencentcloudapi.common.profile.ClientProfile;
@@ -10,8 +8,11 @@ import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest; import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse; import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import org.springframework.stereotype.Service;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.exception.SysException; import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.exception.BizException;
import xyz.zhouxy.plusone.sms.SmsProperties.SmsCredentialProperties; import xyz.zhouxy.plusone.sms.SmsProperties.SmsCredentialProperties;
import xyz.zhouxy.plusone.sms.SmsProperties.SmsHttpProperties; import xyz.zhouxy.plusone.sms.SmsProperties.SmsHttpProperties;
import xyz.zhouxy.plusone.sms.SmsProperties.SmsProxyProperties; import xyz.zhouxy.plusone.sms.SmsProperties.SmsProxyProperties;
@@ -61,13 +62,14 @@ public class TencentSmsServiceImpl implements SmsService {
var res = client.SendSms(req); var res = client.SendSms(req);
// 输出json格式的字符串回包 // 输出json格式的字符串回包
log.info(SendSmsResponse.toJsonString(res)); System.out.println(SendSmsResponse.toJsonString(res));
// 也可以取出单个值你可以通过官网接口文档或跳转到response对象的定义处查看返回字段的定义 // 也可以取出单个值你可以通过官网接口文档或跳转到response对象的定义处查看返回字段的定义
// System.out.println(res.getRequestId()); // System.out.println(res.getRequestId());
} catch (TencentCloudSDKException e) { } catch (TencentCloudSDKException e) {
throw new SysException(e); log.error(e.getMessage(), e);
throw new BizException(ErrorCodeConsts.DEFAULT_ERROR_CODE, e);
} }
} }

View File

@@ -7,7 +7,9 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
</parent> </parent>
<groupId>xyz.zhouxy</groupId>
<artifactId>plusone-basic</artifactId> <artifactId>plusone-basic</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>

View File

@@ -7,7 +7,10 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
</parent> </parent>
<groupId>xyz.zhouxy</groupId>
<artifactId>plusone-start</artifactId> <artifactId>plusone-start</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>plusone-start</name> <name>plusone-start</name>
<description>参考 DDD 落地的脚手架</description> <description>参考 DDD 落地的脚手架</description>

View File

@@ -1,7 +1,5 @@
package xyz.zhouxy.plusone; package xyz.zhouxy.plusone;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -27,7 +25,6 @@ class TestAop {
command.setPrincipal("Code108"); command.setPrincipal("Code108");
command.setPassword("2333"); command.setPassword("2333");
command.setRememberMe(false); command.setRememberMe(false);
assertNotNull(service);
LoginInfoViewObject loginInfo = service.loginByPassword(command); LoginInfoViewObject loginInfo = service.loginByPassword(command);
System.err.println(loginInfo); System.err.println(loginInfo);
} }

View File

@@ -9,13 +9,10 @@ import xyz.zhouxy.plusone.exception.BizException;
*/ */
public class UnsupportedPrincipalTypeException extends BizException { public class UnsupportedPrincipalTypeException extends BizException {
private static final long serialVersionUID = 5207757290868470762L;
public static final int ERR_CODE = 4040201; public static final int ERR_CODE = 4040201;
private static final String DEFAULT_ERROR_MSG = "不支持的 PrincipalType";
public UnsupportedPrincipalTypeException() { public UnsupportedPrincipalTypeException() {
super(ERR_CODE, DEFAULT_ERROR_MSG); super(ERR_CODE, "不支持的 PrincipalType");
} }
public UnsupportedPrincipalTypeException(String msg) { public UnsupportedPrincipalTypeException(String msg) {

View File

@@ -1,20 +1,18 @@
package xyz.zhouxy.plusone.system.application.common.util; package xyz.zhouxy.plusone.system.application.common.util;
import java.util.regex.Pattern;
import lombok.Getter; import lombok.Getter;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
public enum PrincipalType { public enum PrincipalType {
EMAIL(PatternConsts.EMAIL), EMAIL(RegexConsts.EMAIL),
MOBILE_PHONE(PatternConsts.MOBILE_PHONE), MOBILE_PHONE(RegexConsts.MOBILE_PHONE),
USERNAME(PatternConsts.USERNAME) USERNAME(RegexConsts.USERNAME)
; ;
@Getter @Getter
private final Pattern regex; private final String regex;
PrincipalType(Pattern regex) { PrincipalType(String regex) {
this.regex = regex; this.regex = regex;
} }
} }

View File

@@ -30,7 +30,7 @@ public class PrincipalUtil {
} }
PrincipalType[] principalTypes = PrincipalType.values(); PrincipalType[] principalTypes = PrincipalType.values();
for (var principalType : principalTypes) { for (var principalType : principalTypes) {
if (principalType.getRegex().matcher(principal).matches()) { if (principal.matches(principalType.getRegex())) {
return principalType; return principalType;
} }
} }

View File

@@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import xyz.zhouxy.plusone.system.application.query.params.MenuQueryParams;
import xyz.zhouxy.plusone.system.application.service.MenuManagementService; import xyz.zhouxy.plusone.system.application.service.MenuManagementService;
import xyz.zhouxy.plusone.system.application.service.command.CreateMenuCommand; import xyz.zhouxy.plusone.system.application.service.command.CreateMenuCommand;
import xyz.zhouxy.plusone.system.application.service.command.UpdateMenuCommand; import xyz.zhouxy.plusone.system.application.service.command.UpdateMenuCommand;
@@ -67,14 +66,7 @@ public class MenuManagementController {
public RestfulResult findById(@PathVariable("id") Long id) { public RestfulResult findById(@PathVariable("id") Long id) {
adminAuthLogic.checkPermission("sys-menu-details"); adminAuthLogic.checkPermission("sys-menu-details");
var result = service.findById(id); var result = service.findById(id);
return success("查询成功", result); return RestfulResult.success("查询成功", result);
}
@GetMapping
public RestfulResult queryMenuTree(MenuQueryParams queryParams) {
adminAuthLogic.checkPermission("sys-menu-query");
var result = service.queryMenuTree(queryParams);
return success("查询成功", result);
} }
@GetMapping("queryByAccountId") @GetMapping("queryByAccountId")

View File

@@ -1,23 +0,0 @@
package xyz.zhouxy.plusone.system.application.query;
import java.util.List;
import org.springframework.stereotype.Component;
import xyz.zhouxy.plusone.system.application.query.params.MenuQueryParams;
import xyz.zhouxy.plusone.system.application.query.result.MenuViewObject;
/**
*
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
@Component
public class MenuQueries {
public List<MenuViewObject> queryMenuTree(MenuQueryParams queryParams) {
// TODO【添加】 实现该查询
return null;
}
}

View File

@@ -0,0 +1,10 @@
package xyz.zhouxy.plusone.system.application.query;
/**
*
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public interface PermissionQueries {
// TODO【添加】 权限信息查询器
}

View File

@@ -1,18 +0,0 @@
package xyz.zhouxy.plusone.system.application.query.params;
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import xyz.zhouxy.plusone.constant.EntityStatus;
@ToString
public class MenuQueryParams {
private @Getter @Setter String name;
private @Getter @Setter String path;
private @Getter @Setter String title;
private @Getter @Setter Boolean hidden;
private @Getter @Setter EntityStatus status;
private @Getter @Setter String component;
private @Getter @Setter Boolean cache;
private @Getter @Setter String resource;
}

View File

@@ -25,28 +25,60 @@ import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType;
@JsonInclude(JsonInclude.Include.NON_NULL) @JsonInclude(JsonInclude.Include.NON_NULL)
public class MenuViewObject implements IWithOrderNumber { public class MenuViewObject implements IWithOrderNumber {
private @Getter @Setter Integer type; @Getter
@Setter
Integer type;
private @Getter @Setter String typeName; @Getter
@Setter
String typeName;
private @Getter @Setter Long id; @Getter
private @Getter @Setter Long parentId; @Setter
Long id;
@Getter
@Setter
Long parentId;
private @Getter @Setter String name; @Getter
@Setter
String name;
// 若 type 为 MENU_ITEM 且 path 以 http:// 或 https:// 开头则被识别为外链 // 若 type 为 MENU_ITEM 且 path 以 http:// 或 https:// 开头则被识别为外链
private @Getter @Setter String path; @Getter
private @Getter @Setter String title; @Setter
private @Getter @Setter String icon; String path;
private @Getter @Setter boolean hidden; @Getter
private @Getter @Setter int orderNumber; @Setter
private @Getter @Setter Integer status; String title;
private @Getter @Setter String remarks; @Getter
@Setter
String icon;
@Getter
@Setter
boolean hidden;
@Getter
@Setter
int orderNumber;
@Getter
@Setter
Integer status;
@Getter
@Setter
String remarks;
// MENU_ITEM // MENU_ITEM
private @Getter @Setter String component; @Getter
private @Getter @Setter Boolean cache; @Setter
private @Getter @Setter String resource; String component;
private @Getter @Setter List<Action> actions; @Getter
@Setter
Boolean cache;
@Getter
@Setter
String resource;
@Getter
@Setter
List<Action> actions;
// MENU_LIST // MENU_LIST
List<MenuViewObject> children; List<MenuViewObject> children;
@@ -77,7 +109,7 @@ public class MenuViewObject implements IWithOrderNumber {
viewObject.icon = menu.getIcon(); viewObject.icon = menu.getIcon();
viewObject.hidden = menu.isHidden(); viewObject.hidden = menu.isHidden();
viewObject.orderNumber = menu.getOrderNumber(); viewObject.orderNumber = menu.getOrderNumber();
viewObject.status = menu.getStatus().getId(); viewObject.status = menu.getStatus().getValue();
viewObject.remarks = menu.getRemarks(); viewObject.remarks = menu.getRemarks();
if (viewObject.type == MenuType.MENU_ITEM.ordinal()) { if (viewObject.type == MenuType.MENU_ITEM.ordinal()) {
viewObject.component = menu.getComponent(); viewObject.component = menu.getComponent();

View File

@@ -26,10 +26,8 @@ import xyz.zhouxy.plusone.system.application.service.command.UpdateAccountComman
import xyz.zhouxy.plusone.system.domain.model.account.Account; import xyz.zhouxy.plusone.system.domain.model.account.Account;
import xyz.zhouxy.plusone.system.domain.model.account.AccountInfo; import xyz.zhouxy.plusone.system.domain.model.account.AccountInfo;
import xyz.zhouxy.plusone.system.domain.model.account.AccountRepository; import xyz.zhouxy.plusone.system.domain.model.account.AccountRepository;
import xyz.zhouxy.plusone.system.domain.model.account.AccountStatus;
import xyz.zhouxy.plusone.system.domain.model.account.Email; import xyz.zhouxy.plusone.system.domain.model.account.Email;
import xyz.zhouxy.plusone.system.domain.model.account.MobilePhone; import xyz.zhouxy.plusone.system.domain.model.account.MobilePhone;
import xyz.zhouxy.plusone.system.domain.model.account.Sex;
import xyz.zhouxy.plusone.system.domain.model.account.Username; import xyz.zhouxy.plusone.system.domain.model.account.Username;
import xyz.zhouxy.plusone.util.AssertResult; import xyz.zhouxy.plusone.util.AssertResult;
@@ -69,13 +67,9 @@ public class AccountManagementService {
mobilePhone, mobilePhone,
command.getPassword(), command.getPassword(),
command.getPasswordConfirmation(), command.getPasswordConfirmation(),
AccountStatus.of(command.getStatus()), command.getStatus(),
command.getRoleRefs(), command.getRoleRefs(),
AccountInfo.builder() AccountInfo.of(command.getNickname(), command.getAvatar(), command.getSex()),
.nickname(command.getNickname())
.avatar(command.getAvatar())
.sex(Sex.of(command.getSex()))
.build(),
adminAuthLogic.getLoginIdAsLong()); adminAuthLogic.getLoginIdAsLong());
accountRepository.save(account); accountRepository.save(account);
} }
@@ -93,7 +87,7 @@ public class AccountManagementService {
Assert.isTrue(Objects.equals(id, command.getId()), "参数错误: id 不匹配"); Assert.isTrue(Objects.equals(id, command.getId()), "参数错误: id 不匹配");
Account account = accountRepository.find(id) Account account = accountRepository.find(id)
.orElseThrow(() -> new DataNotExistException("该账号不存在")); .orElseThrow(() -> new DataNotExistException("该账号不存在"));
account.setAccountInfo(command.getNickname(), command.getAvatar(), Sex.of(command.getSex())); account.setAccountInfo(command.getNickname(), command.getAvatar(), command.getSex());
account.setUpdatedBy(adminAuthLogic.getLoginIdAsLong()); account.setUpdatedBy(adminAuthLogic.getLoginIdAsLong());
accountRepository.save(account); accountRepository.save(account);
} }

View File

@@ -13,12 +13,9 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.domain.IWithOrderNumber; import xyz.zhouxy.plusone.domain.IWithOrderNumber;
import xyz.zhouxy.plusone.exception.DataNotExistException; import xyz.zhouxy.plusone.exception.DataNotExistException;
import xyz.zhouxy.plusone.system.application.exception.UnsupportedMenuTypeException; import xyz.zhouxy.plusone.system.application.exception.UnsupportedMenuTypeException;
import xyz.zhouxy.plusone.system.application.query.MenuQueries;
import xyz.zhouxy.plusone.system.application.query.params.MenuQueryParams;
import xyz.zhouxy.plusone.system.application.query.result.MenuViewObject; import xyz.zhouxy.plusone.system.application.query.result.MenuViewObject;
import xyz.zhouxy.plusone.system.application.service.command.CreateMenuCommand; import xyz.zhouxy.plusone.system.application.service.command.CreateMenuCommand;
import xyz.zhouxy.plusone.system.application.service.command.UpdateMenuCommand; import xyz.zhouxy.plusone.system.application.service.command.UpdateMenuCommand;
@@ -38,12 +35,10 @@ public class MenuManagementService {
private final MenuService menuService; private final MenuService menuService;
private final MenuRepository menuRepository; private final MenuRepository menuRepository;
private final MenuQueries menuQueries;
MenuManagementService(MenuService menuService, MenuRepository menuRepository, MenuQueries menuQueries) { MenuManagementService(MenuService roleRepository, MenuRepository menuRepository) {
this.menuService = menuService; this.menuService = roleRepository;
this.menuRepository = menuRepository; this.menuRepository = menuRepository;
this.menuQueries = menuQueries;
} }
// ==================== create ==================== // ==================== create ====================
@@ -71,7 +66,7 @@ public class MenuManagementService {
command.getIcon(), command.getIcon(),
command.getHidden(), command.getHidden(),
command.getOrderNumber(), command.getOrderNumber(),
EntityStatus.of(command.getStatus()), command.getStatus(),
command.getRemarks()); command.getRemarks());
} }
@@ -84,7 +79,7 @@ public class MenuManagementService {
command.getIcon(), command.getIcon(),
command.getHidden(), command.getHidden(),
command.getOrderNumber(), command.getOrderNumber(),
EntityStatus.of(command.getStatus()), command.getStatus(),
command.getComponent(), command.getComponent(),
command.getResource(), command.getResource(),
command.getCache(), command.getCache(),
@@ -112,7 +107,7 @@ public class MenuManagementService {
command.getIcon(), command.getIcon(),
command.getHidden(), command.getHidden(),
command.getOrderNumber(), command.getOrderNumber(),
EntityStatus.of(command.getStatus()), command.getStatus(),
command.getComponent(), command.getComponent(),
command.getResource(), command.getResource(),
command.getCache(), command.getCache(),
@@ -127,11 +122,6 @@ public class MenuManagementService {
return MenuViewObject.of(menu.orElseThrow(DataNotExistException::new)); return MenuViewObject.of(menu.orElseThrow(DataNotExistException::new));
} }
@Transactional(propagation = Propagation.SUPPORTS)
public List<MenuViewObject> queryMenuTree(MenuQueryParams queryParams) {
return menuQueries.queryMenuTree(queryParams);
}
@Transactional(propagation = Propagation.SUPPORTS) @Transactional(propagation = Propagation.SUPPORTS)
public List<MenuViewObject> queryByAccountId(Long accountId) { public List<MenuViewObject> queryByAccountId(Long accountId) {
var menus = menuService.queryAllMenuListByAccountId(accountId); var menus = menuService.queryAllMenuListByAccountId(accountId);

View File

@@ -17,6 +17,7 @@ import xyz.zhouxy.plusone.system.domain.model.account.AccountStatus;
import xyz.zhouxy.plusone.system.domain.model.account.Email; import xyz.zhouxy.plusone.system.domain.model.account.Email;
import xyz.zhouxy.plusone.system.domain.model.account.MobilePhone; import xyz.zhouxy.plusone.system.domain.model.account.MobilePhone;
import xyz.zhouxy.plusone.system.domain.model.account.Password; import xyz.zhouxy.plusone.system.domain.model.account.Password;
import xyz.zhouxy.plusone.system.domain.model.account.Sex;
import xyz.zhouxy.plusone.system.domain.model.account.Username; import xyz.zhouxy.plusone.system.domain.model.account.Username;
/** /**
@@ -81,9 +82,7 @@ public class RegisterAccountService {
Password.newPassword(command.getPassword(), command.getReenteredPassword()), Password.newPassword(command.getPassword(), command.getReenteredPassword()),
AccountStatus.AVAILABLE, AccountStatus.AVAILABLE,
Set.of(DEFAULT_ROLE_ID), Set.of(DEFAULT_ROLE_ID),
AccountInfo.builder() AccountInfo.of(command.getNickname(), null, Sex.UNSET));
.nickname(command.getNickname())
.build());
accountRepository.save(accountToSave); accountRepository.save(accountToSave);
} }

View File

@@ -10,7 +10,6 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.exception.DataNotExistException; import xyz.zhouxy.plusone.exception.DataNotExistException;
import xyz.zhouxy.plusone.system.application.query.RoleQueries; import xyz.zhouxy.plusone.system.application.query.RoleQueries;
import xyz.zhouxy.plusone.system.application.query.params.RoleQueryParams; import xyz.zhouxy.plusone.system.application.query.params.RoleQueryParams;
@@ -55,7 +54,7 @@ public class RoleManagementService {
Role roleToCreate = Role.newInstance( Role roleToCreate = Role.newInstance(
command.getName(), command.getName(),
command.getIdentifier(), command.getIdentifier(),
EntityStatus.of(command.getStatus()), command.getStatus(),
command.getRemarks(), command.getRemarks(),
menuRefs, menuRefs,
permissionRefs); permissionRefs);
@@ -68,7 +67,7 @@ public class RoleManagementService {
roleToUpdate.update( roleToUpdate.update(
command.getName(), command.getName(),
command.getIdentifier(), command.getIdentifier(),
EntityStatus.of(command.getStatus()), command.getStatus(),
command.getRemarks(), command.getRemarks(),
Set.copyOf(_menuRepository.findByIdIn(command.getMenus())), Set.copyOf(_menuRepository.findByIdIn(command.getMenus())),
Set.copyOf(_menuRepository.findPermissionsByIdIn(command.getPermissions()))); Set.copyOf(_menuRepository.findPermissionsByIdIn(command.getPermissions())));

View File

@@ -10,8 +10,10 @@ import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.URL; import org.hibernate.validator.constraints.URL;
import lombok.Data; import lombok.Data;
import xyz.zhouxy.plusone.commons.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
import xyz.zhouxy.plusone.system.domain.model.account.AccountStatus;
import xyz.zhouxy.plusone.system.domain.model.account.Sex;
/** /**
* 创建账号命令 * 创建账号命令
@@ -39,7 +41,7 @@ public class CreateAccountCommand implements ICommand {
String passwordConfirmation; String passwordConfirmation;
@NotNull @NotNull
Integer status; AccountStatus status;
Set<Long> roleRefs; Set<Long> roleRefs;
@@ -50,5 +52,5 @@ public class CreateAccountCommand implements ICommand {
@URL @URL
String avatar; String avatar;
Integer sex; Sex sex;
} }

View File

@@ -5,6 +5,7 @@ import javax.validation.constraints.NotNull;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType; import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType;
@@ -41,7 +42,7 @@ public class CreateMenuCommand implements ICommand {
private Integer orderNumber; private Integer orderNumber;
@NotNull @NotNull
private Integer status; private EntityStatus status;
private String component; private String component;

View File

@@ -6,6 +6,7 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
/** /**
@@ -22,7 +23,7 @@ public class CreateRoleCommand implements ICommand {
String identifier; String identifier;
@NotNull @NotNull
Integer status; EntityStatus status;
String remarks; String remarks;
Set<Long> menus; Set<Long> menus;

View File

@@ -4,7 +4,7 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern; import javax.validation.constraints.Pattern;
import lombok.Data; import lombok.Data;
import xyz.zhouxy.plusone.commons.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
/** /**

View File

@@ -6,8 +6,9 @@ import javax.validation.constraints.Pattern;
import org.hibernate.validator.constraints.URL; import org.hibernate.validator.constraints.URL;
import lombok.Data; import lombok.Data;
import xyz.zhouxy.plusone.commons.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
import xyz.zhouxy.plusone.system.domain.model.account.Sex;
/** /**
* 更新账号信息命令 * 更新账号信息命令
@@ -26,5 +27,5 @@ public class UpdateAccountCommand implements ICommand {
@URL @URL
String avatar; String avatar;
Integer sex; Sex sex;
} }

View File

@@ -5,6 +5,7 @@ import javax.validation.constraints.NotNull;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType; import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType;
@@ -45,7 +46,7 @@ public class UpdateMenuCommand implements ICommand {
private Integer orderNumber; private Integer orderNumber;
@NotNull @NotNull
private Integer status; private EntityStatus status;
private String component; private String component;

View File

@@ -6,6 +6,7 @@ import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import lombok.Data; import lombok.Data;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.domain.ICommand; import xyz.zhouxy.plusone.domain.ICommand;
/** /**
@@ -26,7 +27,7 @@ public class UpdateRoleCommand implements ICommand {
String identifier; String identifier;
@NotNull @NotNull
Integer status; EntityStatus status;
@NotBlank @NotBlank
String remarks; String remarks;

View File

@@ -14,6 +14,10 @@
<groupId>xyz.zhouxy</groupId> <groupId>xyz.zhouxy</groupId>
<artifactId>plusone-basic-common</artifactId> <artifactId>plusone-basic-common</artifactId>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@@ -1,14 +1,11 @@
package xyz.zhouxy.plusone.system.util; package xyz.zhouxy.plusone.system.util;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.exception.SysException; import cn.hutool.core.util.RandomUtil;
import xyz.zhouxy.plusone.util.RandomUtil; import cn.hutool.crypto.digest.DigestUtil;
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.exception.BizException;
/** /**
* 密码工具类 * 密码工具类
@@ -16,8 +13,7 @@ import xyz.zhouxy.plusone.util.RandomUtil;
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a> * @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/ */
public final class PasswordUtil { public final class PasswordUtil {
private static final char[] SALT_BASE_CHAR_ARRAY = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+={}[]|\\:;\"',.<>?/" private static final String SALT_BASE_STRING = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+={}[]|\\:;\"',.<>?/";
.toCharArray();
/** /**
* 将密码和随机盐混合,并进行哈希加密。 * 将密码和随机盐混合,并进行哈希加密。
@@ -32,12 +28,12 @@ public final class PasswordUtil {
int i = length > 0 ? length / 2 : 0; int i = length > 0 ? length / 2 : 0;
var passwordWithSalt = salt.substring(0, i) var passwordWithSalt = salt.substring(0, i)
+ password + password
+ salt.substring(i); + salt.substring(1);
try { String sha512Hex = DigestUtil.sha512Hex(passwordWithSalt);
return sha512Hex(passwordWithSalt); if (sha512Hex == null) {
} catch (NoSuchAlgorithmException e) { throw new BizException(ErrorCodeConsts.DEFAULT_ERROR_CODE, "未知错误:哈希加密失败!");
throw new SysException(e);
} }
return sha512Hex;
} }
/** /**
@@ -46,20 +42,11 @@ public final class PasswordUtil {
* @return 生成的随机盐 * @return 生成的随机盐
*/ */
public static String generateRandomSalt() { public static String generateRandomSalt() {
return RandomUtil.randomStr(SALT_BASE_CHAR_ARRAY, 24); return RandomUtil.randomString(SALT_BASE_STRING, 24);
} }
private PasswordUtil() { private PasswordUtil() {
// 不允许实例化 // 不允许实例化
throw new IllegalStateException("Utility class"); throw new IllegalStateException("Utility class");
} }
@Nonnull
@SuppressWarnings("null")
private static String sha512Hex(String data) throws NoSuchAlgorithmException {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
messageDigest.update(data.getBytes(StandardCharsets.UTF_8));
byte[] result = messageDigest.digest();
return new BigInteger(1, result).toString(16);
}
} }

View File

@@ -93,19 +93,11 @@ public class Account extends AggregateRoot<Long> implements IWithVersion {
} }
public void setAccountInfo(Nickname nickname, URL avatar, Sex sex) { public void setAccountInfo(Nickname nickname, URL avatar, Sex sex) {
this.accountInfo = AccountInfo.builder() this.accountInfo = AccountInfo.of(nickname, avatar, sex);
.nickname(nickname)
.avatar(avatar)
.sex(sex)
.build();
} }
public void setAccountInfo(String nickname, String avatar, Sex sex) { public void setAccountInfo(String nickname, String avatar, Sex sex) {
this.accountInfo = AccountInfo.builder() this.accountInfo = AccountInfo.of(nickname, avatar, sex);
.nickname(nickname)
.avatar(avatar)
.sex(sex)
.build();
} }
/** /**

View File

@@ -5,9 +5,7 @@ import java.net.URL;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull; import lombok.Getter;
import javax.annotation.Nullable;
import lombok.ToString; import lombok.ToString;
import xyz.zhouxy.plusone.domain.IValueObject; import xyz.zhouxy.plusone.domain.IValueObject;
@@ -19,19 +17,30 @@ import xyz.zhouxy.plusone.domain.IValueObject;
@ToString @ToString
public class AccountInfo implements IValueObject { public class AccountInfo implements IValueObject {
@Nullable
private final Nickname nickname; private final Nickname nickname;
@Nullable
private final URL avatar; private final URL avatar;
@Nonnull private final @Getter Sex sex;
private final Sex sex;
private AccountInfo(@Nullable Nickname nickname, @Nullable URL avatar, @Nullable Sex sex) { private AccountInfo(Nickname nickname, URL avatar, Sex sex) {
this.nickname = nickname; this.nickname = nickname;
this.avatar = avatar; this.avatar = avatar;
this.sex = Objects.nonNull(sex) ? sex : Sex.UNSET; this.sex = Objects.nonNull(sex) ? sex : Sex.UNSET;
} }
public static AccountInfo of(Nickname nickname, URL avatar, Sex sex) {
return new AccountInfo(nickname, avatar, sex);
}
public static AccountInfo of(String nickname, String avatar, Sex sex) {
URL avatarURL;
try {
avatarURL = Objects.nonNull(avatar) ? new URL(avatar) : null;
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
return new AccountInfo(Nickname.ofNullable(nickname), avatarURL, sex);
}
public Optional<Nickname> getNickname() { public Optional<Nickname> getNickname() {
return Optional.ofNullable(nickname); return Optional.ofNullable(nickname);
} }
@@ -39,54 +48,4 @@ public class AccountInfo implements IValueObject {
public Optional<URL> getAvatar() { public Optional<URL> getAvatar() {
return Optional.ofNullable(avatar); return Optional.ofNullable(avatar);
} }
@Nonnull
public Sex getSex() {
return this.sex;
}
// Builder
public static Builder builder() {
return new Builder();
}
public static class Builder {
private Nickname nickname;
private URL avatar;
private Sex sex;
public Builder nickname(@Nullable Nickname nickname) {
this.nickname = nickname;
return this;
}
public Builder nickname(@Nullable String nickname) {
return nickname(Nickname.ofNullable(nickname));
}
public Builder avatar(@Nullable URL avatar) {
this.avatar = avatar;
return this;
}
public Builder avatar(@Nullable String avatar) {
URL avatarURL;
try {
avatarURL = Objects.nonNull(avatar) ? new URL(avatar) : null;
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
return avatar(avatarURL);
}
public Builder sex(@Nullable Sex sex) {
this.sex = sex;
return this;
}
public AccountInfo build() {
return new AccountInfo(this.nickname, this.avatar, this.sex);
}
}
} }

View File

@@ -1,9 +1,5 @@
package xyz.zhouxy.plusone.system.domain.model.account; package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Collection;
import javax.annotation.Nonnull;
import lombok.Getter; import lombok.Getter;
import xyz.zhouxy.plusone.commons.util.Enumeration; import xyz.zhouxy.plusone.commons.util.Enumeration;
import xyz.zhouxy.plusone.domain.IValueObject; import xyz.zhouxy.plusone.domain.IValueObject;
@@ -14,25 +10,20 @@ import xyz.zhouxy.plusone.domain.IValueObject;
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a> * @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/ */
@Getter @Getter
public final class AccountStatus extends Enumeration<AccountStatus> implements IValueObject { public class AccountStatus extends Enumeration<AccountStatus> implements IValueObject {
private AccountStatus(int id, @Nonnull String name) { private AccountStatus(int value, String name) {
super(id, name); super(value, name);
} }
public static final AccountStatus AVAILABLE = new AccountStatus(0, "账号正常"); public static final AccountStatus AVAILABLE = new AccountStatus(0, "账号正常");
public static final AccountStatus LOCKED = new AccountStatus(1, "账号被锁定"); public static final AccountStatus LOCKED = new AccountStatus(1, "账号被锁定");
private static final ValueSet<AccountStatus> VALUE_SET = new ValueSet<>( private static final EnumerationValuesHolder<AccountStatus> ENUMERATION_VALUES = new EnumerationValuesHolder<>(
AVAILABLE, AVAILABLE,
LOCKED); LOCKED);
public static AccountStatus of(int id) { public static AccountStatus of(int value) {
return VALUE_SET.get(id); return ENUMERATION_VALUES.get(value);
}
@Nonnull
public static Collection<AccountStatus> constants() {
return VALUE_SET.getValues();
} }
} }

View File

@@ -1,10 +1,9 @@
package xyz.zhouxy.plusone.system.domain.model.account; package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern;
import cn.hutool.core.util.DesensitizedUtil; import cn.hutool.core.util.DesensitizedUtil;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
/** /**
* 值对象:电子邮箱地址 * 值对象:电子邮箱地址
@@ -13,7 +12,7 @@ import xyz.zhouxy.plusone.commons.constant.PatternConsts;
*/ */
public class Email extends Principal { public class Email extends Principal {
public static final Pattern REGEX = PatternConsts.EMAIL; public static final String REGEX = RegexConsts.EMAIL;
private Email(String email) { private Email(String email) {
super(REGEX); super(REGEX);

View File

@@ -1,10 +1,9 @@
package xyz.zhouxy.plusone.system.domain.model.account; package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern;
import cn.hutool.core.util.DesensitizedUtil; import cn.hutool.core.util.DesensitizedUtil;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
/** /**
* 值对象:手机号码 * 值对象:手机号码
@@ -13,7 +12,7 @@ import xyz.zhouxy.plusone.commons.constant.PatternConsts;
*/ */
public class MobilePhone extends Principal { public class MobilePhone extends Principal {
public static final Pattern REGEX = PatternConsts.MOBILE_PHONE; public static final String REGEX = RegexConsts.MOBILE_PHONE;
private MobilePhone(String mobilePhone) { private MobilePhone(String mobilePhone) {
super(REGEX); super(REGEX);

View File

@@ -1,9 +1,8 @@
package xyz.zhouxy.plusone.system.domain.model.account; package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.domain.ValidatableStringRecord; import xyz.zhouxy.plusone.domain.ValidatableStringRecord;
/** /**
@@ -13,7 +12,7 @@ import xyz.zhouxy.plusone.domain.ValidatableStringRecord;
*/ */
public class Nickname extends ValidatableStringRecord { public class Nickname extends ValidatableStringRecord {
public static final Pattern REGEX = PatternConsts.NICKNAME; public static final String REGEX = RegexConsts.NICKNAME;
private Nickname(String value) { private Nickname(String value) {
super(REGEX); super(REGEX);

View File

@@ -7,9 +7,10 @@ import javax.annotation.Nonnull;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.domain.IValueObject; import xyz.zhouxy.plusone.domain.IValueObject;
import xyz.zhouxy.plusone.exception.SysException; import xyz.zhouxy.plusone.exception.BizException;
import xyz.zhouxy.plusone.system.util.PasswordUtil; import xyz.zhouxy.plusone.system.util.PasswordUtil;
/** /**
@@ -19,7 +20,7 @@ import xyz.zhouxy.plusone.system.util.PasswordUtil;
*/ */
public class Password implements IValueObject { public class Password implements IValueObject {
private static final Pattern PATTERN = PatternConsts.PASSWORD; private static final Pattern PATTERN = Pattern.compile(RegexConsts.PASSWORD);
private static final String DEFAULT_PASSWORD = "A1b2C3d4"; private static final String DEFAULT_PASSWORD = "A1b2C3d4";
@Nonnull @Nonnull
@@ -36,7 +37,7 @@ public class Password implements IValueObject {
} }
var salt = PasswordUtil.generateRandomSalt(); var salt = PasswordUtil.generateRandomSalt();
if (salt == null) { if (salt == null) {
throw new SysException("未知错误:生成随机盐失败"); throw new BizException(ErrorCodeConsts.DEFAULT_ERROR_CODE, "未知错误:生成随机盐失败");
} }
this.saltVal = salt; this.saltVal = salt;
this.passwordVal = PasswordUtil.hashPassword(password, salt); this.passwordVal = PasswordUtil.hashPassword(password, salt);

View File

@@ -1,7 +1,5 @@
package xyz.zhouxy.plusone.system.domain.model.account; package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.regex.Pattern;
import xyz.zhouxy.plusone.domain.ValidatableStringRecord; import xyz.zhouxy.plusone.domain.ValidatableStringRecord;
/** /**
@@ -10,7 +8,7 @@ import xyz.zhouxy.plusone.domain.ValidatableStringRecord;
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a> * @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/ */
public abstract class Principal extends ValidatableStringRecord { public abstract class Principal extends ValidatableStringRecord {
protected Principal(Pattern format) { protected Principal(String format) {
super(format); super(format);
} }
} }

View File

@@ -1,9 +1,5 @@
package xyz.zhouxy.plusone.system.domain.model.account; package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Collection;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.util.Enumeration; import xyz.zhouxy.plusone.commons.util.Enumeration;
import xyz.zhouxy.plusone.domain.IValueObject; import xyz.zhouxy.plusone.domain.IValueObject;
@@ -12,27 +8,21 @@ import xyz.zhouxy.plusone.domain.IValueObject;
* *
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a> * @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/ */
public final class Sex extends Enumeration<Sex> implements IValueObject { public class Sex extends Enumeration<Sex> implements IValueObject {
@Nonnull
public static final Sex UNSET = new Sex(0, "未设置"); public static final Sex UNSET = new Sex(0, "未设置");
@Nonnull
public static final Sex MALE = new Sex(1, "男性"); public static final Sex MALE = new Sex(1, "男性");
@Nonnull
public static final Sex FEMALE = new Sex(2, "女性"); public static final Sex FEMALE = new Sex(2, "女性");
private Sex(int id, @Nonnull String name) { private Sex(int value, String name) {
super(id, name); super(value, name);
} }
private static final ValueSet<Sex> VALUE_SET = new ValueSet<>(UNSET, MALE, FEMALE); private static EnumerationValuesHolder<Sex> values = new EnumerationValuesHolder<>(
UNSET,
MALE,
FEMALE);
@Nonnull
public static Sex of(int value) { public static Sex of(int value) {
return VALUE_SET.get(value); return values.get(value);
}
@Nonnull
public static Collection<Sex> constants() {
return VALUE_SET.getValues();
} }
} }

View File

@@ -1,8 +1,6 @@
package xyz.zhouxy.plusone.system.domain.model.account; package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.regex.Pattern; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
/** /**
* 值对象:用户名 * 值对象:用户名
@@ -11,7 +9,7 @@ import xyz.zhouxy.plusone.commons.constant.PatternConsts;
*/ */
public class Username extends Principal { public class Username extends Principal {
public static final Pattern REGEX = PatternConsts.USERNAME; public static final String REGEX = RegexConsts.USERNAME;
private Username(String username) { private Username(String username) {
super(REGEX); super(REGEX);

View File

@@ -94,26 +94,26 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
@Override @Override
public boolean exists(Long id) { public boolean exists(Long id) {
return queryForBool("SELECT EXISTS (SELECT 1 FROM sys_account WHERE id = :id AND deleted = 0 LIMIT 1)", return queryExists("SELECT EXISTS (SELECT 1 FROM sys_account WHERE id = :id AND deleted = 0 LIMIT 1)",
"id", id); "id", id);
} }
@Override @Override
public boolean existsUsername(Username username) { public boolean existsUsername(Username username) {
return queryForBool( return queryExists(
"SELECT EXISTS (SELECT 1 FROM sys_account WHERE username = :username AND deleted = 0 LIMIT 1)", "SELECT EXISTS (SELECT 1 FROM sys_account WHERE username = :username AND deleted = 0 LIMIT 1)",
"username", username.value()); "username", username.value());
} }
@Override @Override
public boolean existsEmail(Email email) { public boolean existsEmail(Email email) {
return queryForBool("SELECT EXISTS (SELECT 1 FROM sys_account WHERE email = :email AND deleted = 0 LIMIT 1)", return queryExists("SELECT EXISTS (SELECT 1 FROM sys_account WHERE email = :email AND deleted = 0 LIMIT 1)",
"email", email.value()); "email", email.value());
} }
@Override @Override
public boolean existsMobilePhone(MobilePhone mobilePhone) { public boolean existsMobilePhone(MobilePhone mobilePhone) {
return queryForBool( return queryExists(
"SELECT EXISTS (SELECT 1 FROM sys_account WHERE mobile_phone = :mobile_phone AND deleted = 0 LIMIT 1)", "SELECT EXISTS (SELECT 1 FROM sys_account WHERE mobile_phone = :mobile_phone AND deleted = 0 LIMIT 1)",
"mobile_phone", mobilePhone.value()); "mobile_phone", mobilePhone.value());
} }
@@ -176,6 +176,10 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
@Override @Override
protected final Account mapRow(ResultSet rs) throws SQLException { protected final Account mapRow(ResultSet rs) throws SQLException {
long accountId = rs.getLong("id"); long accountId = rs.getLong("id");
AccountInfo accountInfo = AccountInfo.of(
rs.getString("nickname"),
rs.getString("avatar"),
Sex.of(rs.getInt("sex")));
return new Account( return new Account(
accountId, accountId,
rs.getString("username"), rs.getString("username"),
@@ -183,11 +187,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
rs.getString("mobile_phone"), rs.getString("mobile_phone"),
Password.of(rs.getString("password"), rs.getString("salt")), Password.of(rs.getString("password"), rs.getString("salt")),
AccountStatus.of(rs.getInt("status")), AccountStatus.of(rs.getInt("status")),
AccountInfo.builder() accountInfo,
.nickname(rs.getString("nickname"))
.avatar(rs.getString("avatar"))
.sex(Sex.of(rs.getInt("sex")))
.build(),
this.accountRoleDAO.selectRoleIdsByAccountId(accountId), this.accountRoleDAO.selectRoleIdsByAccountId(accountId),
rs.getLong("created_by"), rs.getLong("created_by"),
rs.getLong("updated_by"), rs.getLong("updated_by"),
@@ -206,9 +206,9 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
.addValue("password", entity.getPassword().value()) .addValue("password", entity.getPassword().value())
.addValue("salt", entity.getPassword().getSalt()) .addValue("salt", entity.getPassword().getSalt())
.addValue("avatar", accountInfo.getAvatar().toString()) .addValue("avatar", accountInfo.getAvatar().toString())
.addValue("sex", accountInfo.getSex().getId()) .addValue("sex", accountInfo.getSex().getValue())
.addValue("nickname", getValueOrNull(accountInfo.getNickname())) .addValue("nickname", getValueOrNull(accountInfo.getNickname()))
.addValue("status", entity.getStatus().getId()) .addValue("status", entity.getStatus().getValue())
.addValue("createdBy", entity.getCreatedBy()) .addValue("createdBy", entity.getCreatedBy())
.addValue("createTime", now) .addValue("createTime", now)
.addValue("updatedBy", entity.getUpdatedBy()) .addValue("updatedBy", entity.getUpdatedBy())

View File

@@ -31,7 +31,7 @@ class AccountRoleRefDAO extends PlusoneJdbcDaoSupport {
} }
void insertAccountRoleRefs(Long accountId, Set<Long> roleRefs) { void insertAccountRoleRefs(Long accountId, Set<Long> roleRefs) {
long i = batchUpdate( int i = batchUpdate(
"INSERT INTO sys_account_role (account_id, role_id) VALUES (:accountId, :roleId)", "INSERT INTO sys_account_role (account_id, role_id) VALUES (:accountId, :roleId)",
roleRefs, roleRefs,
(Long roleId) -> new MapSqlParameterSource() (Long roleId) -> new MapSqlParameterSource()

View File

@@ -83,7 +83,7 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
@Override @Override
public boolean exists(Long id) { public boolean exists(Long id) {
return queryForBool("SELECT EXISTS (SELECT 1 FROM sys_dict_type WHERE id = :id AND deleted = 0 LIMIT 1)", return queryExists("SELECT EXISTS (SELECT 1 FROM sys_dict_type WHERE id = :id AND deleted = 0 LIMIT 1)",
new MapSqlParameterSource("id", id)); new MapSqlParameterSource("id", id));
} }

View File

@@ -21,11 +21,11 @@ class DictValueDAO extends PlusoneJdbcDaoSupport {
void updateDictValues(Dict entity) { void updateDictValues(Dict entity) {
update("DELETE FROM sys_dict_value WHERE dict_type = :dictType", update("DELETE FROM sys_dict_value WHERE dict_type = :dictType",
"dictType", entity.getId().orElseThrow()); "dictType", entity.getId().orElseThrow());
long i = insertDictValues(entity.getId().orElseThrow(), entity); int i = insertDictValues(entity.getId().orElseThrow(), entity);
assertResultEquals(i, entity.count()); assertResultEquals(i, entity.count());
} }
long insertDictValues(Long dictId, Dict entity) { int insertDictValues(Long dictId, Dict entity) {
if (Objects.isNull(dictId) || Objects.isNull(entity) || CollectionUtils.isEmpty(entity.getValues())) { if (Objects.isNull(dictId) || Objects.isNull(entity) || CollectionUtils.isEmpty(entity.getValues())) {
return 0; return 0;
} }

View File

@@ -8,6 +8,7 @@ import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -15,7 +16,6 @@ import javax.annotation.Nonnull;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import xyz.zhouxy.plusone.jdbc.JdbcEntityDaoSupport; import xyz.zhouxy.plusone.jdbc.JdbcEntityDaoSupport;
@@ -80,7 +80,7 @@ class ActionDAO extends JdbcEntityDaoSupport<Action, Long> {
} }
Collection<Action> selectActionsByIdIn(Collection<Long> actionIds) { Collection<Action> selectActionsByIdIn(Collection<Long> actionIds) {
if (CollectionUtils.isEmpty(actionIds)) { if (Objects.isNull(actionIds) || actionIds.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
return queryForList(""" return queryForList("""

View File

@@ -7,6 +7,7 @@ import java.sql.SQLException;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
@@ -14,7 +15,6 @@ import javax.annotation.Nonnull;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource; import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.IdUtil;
import xyz.zhouxy.plusone.commons.util.EnumUtil; import xyz.zhouxy.plusone.commons.util.EnumUtil;
@@ -115,13 +115,13 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
@Override @Override
public boolean exists(Long id) { public boolean exists(Long id) {
return queryForBool("SELECT EXISTS (SELECT 1 FROM sys_menu WHERE id = :id AND deleted = 0 LIMIT 1)", return queryExists("SELECT EXISTS (SELECT 1 FROM sys_menu WHERE id = :id AND deleted = 0 LIMIT 1)",
"id", id); "id", id);
} }
@Override @Override
public Collection<Menu> findByIdIn(Collection<Long> ids) { public Collection<Menu> findByIdIn(Collection<Long> ids) {
if (CollectionUtils.isEmpty(ids)) { if (Objects.isNull(ids) || ids.isEmpty()) {
return Collections.emptyList(); return Collections.emptyList();
} }
return queryForList(""" return queryForList("""
@@ -188,7 +188,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
.addValue("icon", entity.getIcon()) .addValue("icon", entity.getIcon())
.addValue("hidden", entity.isHidden()) .addValue("hidden", entity.isHidden())
.addValue("orderNumber", entity.getOrderNumber()) .addValue("orderNumber", entity.getOrderNumber())
.addValue("status", entity.getStatus().getId()) .addValue("status", entity.getStatus().getValue())
.addValue("remarks", entity.getRemarks()) .addValue("remarks", entity.getRemarks())
.addValue("component", entity.getComponent()) .addValue("component", entity.getComponent())
.addValue("cache", entity.getCache()) .addValue("cache", entity.getCache())

View File

@@ -29,7 +29,7 @@ class RoleMenuRefDAO extends PlusoneJdbcDaoSupport {
} }
void saveRoleMenuRefs(Long roleId, Role entity) { void saveRoleMenuRefs(Long roleId, Role entity) {
long i = batchUpdate( int i = batchUpdate(
"INSERT INTO sys_role_menu(role_id, menu_id) VALUES (:roleId, :menuId)", "INSERT INTO sys_role_menu(role_id, menu_id) VALUES (:roleId, :menuId)",
entity.getMenus(), entity.getMenus(),
menuRef -> new MapSqlParameterSource() menuRef -> new MapSqlParameterSource()

View File

@@ -30,7 +30,7 @@ class RolePermissionRefDAO extends PlusoneJdbcDaoSupport {
} }
void saveRolePermissionRefs(Long roleId, Role entity) { void saveRolePermissionRefs(Long roleId, Role entity) {
long i = batchUpdate( int i = batchUpdate(
"INSERT INTO sys_role_permission(role_id, permission_id) VALUES (:roleId, :permissionId)", "INSERT INTO sys_role_permission(role_id, permission_id) VALUES (:roleId, :permissionId)",
entity.getPermissions(), entity.getPermissions(),
actionRef -> new MapSqlParameterSource() actionRef -> new MapSqlParameterSource()

View File

@@ -60,7 +60,7 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
@Override @Override
public boolean exists(Long id) { public boolean exists(Long id) {
return queryForBool("SELECT EXISTS (SELECT 1 FROM sys_role WHERE id = :id AND deleted = 0 LIMIT 1)", return queryExists("SELECT EXISTS (SELECT 1 FROM sys_role WHERE id = :id AND deleted = 0 LIMIT 1)",
"id", id); "id", id);
} }
@@ -135,7 +135,7 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
.addValue("id", id) .addValue("id", id)
.addValue("name", entity.getName()) .addValue("name", entity.getName())
.addValue("identifier", entity.getIdentifier()) .addValue("identifier", entity.getIdentifier())
.addValue("status", entity.getStatus().getId()) .addValue("status", entity.getStatus().getValue())
.addValue("remarks", entity.getRemarks()) .addValue("remarks", entity.getRemarks())
.addValue("createTime", now) .addValue("createTime", now)
.addValue("createdBy", loginId) .addValue("createdBy", loginId)

View File

@@ -7,7 +7,9 @@
<version>1.0.0-SNAPSHOT</version> <version>1.0.0-SNAPSHOT</version>
</parent> </parent>
<groupId>xyz.zhouxy</groupId>
<artifactId>plusone-system</artifactId> <artifactId>plusone-system</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>plusone-system</name> <name>plusone-system</name>
@@ -67,10 +69,6 @@
</dependencyManagement> </dependencyManagement>
<dependencies> <dependencies>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId> <artifactId>junit-jupiter-api</artifactId>

22
pom.xml
View File

@@ -25,15 +25,15 @@
<maven.compiler.source>17</maven.compiler.source> <maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target> <maven.compiler.target>17</maven.compiler.target>
<spring-boot.version>2.7.10</spring-boot.version> <spring-boot.version>2.7.8</spring-boot.version>
<sa-token.version>1.34.0</sa-token.version> <sa-token.version>1.34.0</sa-token.version>
<hutool.version>5.8.16</hutool.version> <hutool.version>5.8.12</hutool.version>
<mybatis-starter.version>3.0.1</mybatis-starter.version> <mybatis-starter.version>3.0.1</mybatis-starter.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version> <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<commons-io.version>2.11.0</commons-io.version> <commons-io.version>2.11.0</commons-io.version>
<mica.version>2.7.5</mica.version> <mica.version>2.7.5</mica.version>
<mapstruct.version>1.5.3.Final</mapstruct.version> <mapstruct.version>1.5.3.Final</mapstruct.version>
<guava.version>30.1-jre</guava.version> <guava.version>31.1-jre</guava.version>
<commons-lang3.version>3.12.0</commons-lang3.version> <commons-lang3.version>3.12.0</commons-lang3.version>
<commons-collections4.version>4.4</commons-collections4.version> <commons-collections4.version>4.4</commons-collections4.version>
<commons-math3.version>3.6.1</commons-math3.version> <commons-math3.version>3.6.1</commons-math3.version>
@@ -91,7 +91,16 @@
<artifactId>hutool-core</artifactId> <artifactId>hutool-core</artifactId>
<version>${hutool.version}</version> <version>${hutool.version}</version>
</dependency> </dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-captcha</artifactId>
<version>${hutool.version}</version>
</dependency>
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
@@ -177,6 +186,11 @@
<groupId>ch.qos.logback</groupId> <groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId> <artifactId>logback-classic</artifactId>
</dependency> </dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>3.0.2</version>
</dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>