11 Commits

58 changed files with 198 additions and 484 deletions

View File

@@ -18,11 +18,4 @@
目前项目还没完成,开发中…… 目前项目还没完成,开发中……
相关的文档和介绍完善中…… 相关的文档和介绍完善中……
## 编码规约
### 关于 null
1. 方法默认参数不为 `null`**可以**在 Javadoc 中对参数进行说明,如“...(must not be {@code null}[ or empty string])”。方法内部**必须**做参数校验,如使用 Assert 等工具类。
2. 如果参数允许为空,**必须**为参数添加 `@Nullable` 注解,并在 Javadoc 中对参数进行说明,如“...(may be {@code null})”。
3. 除极特殊的情况,方法默认**不返回 `null`**,如可能返回一个对象表示值的缺失,则**必须**使用 `Optional`**绝不在返回类型为 Optional 的方法中返回 `null`**。
4. 在极其特殊的情况下,方法需要返回 `null`**必须**给方法加上 `@Nullable` 注解,并在 Javadoc 中详细说明。

View File

@@ -1,13 +1,10 @@
package xyz.zhouxy.plusone.exception.handler; package xyz.zhouxy.plusone.exception.handler;
import javax.annotation.Nonnull;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import xyz.zhouxy.plusone.commons.exception.handler.AllExceptionHandler; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
/** /**
* AllExceptionHandlerConfig * AllExceptionHandlerConfig
@@ -17,7 +14,7 @@ import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler.Excepti
public class AllExceptionHandlerConfig { public class AllExceptionHandlerConfig {
@Bean @Bean
AllExceptionHandler getAllExceptionHandler(@Nonnull ExceptionInfoHolder exceptionInfoHolder) { AllExceptionHandler getAllExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
return new AllExceptionHandler(exceptionInfoHolder); return new AllExceptionHandler(exceptionInfoHolder);
} }
} }

View File

@@ -1,7 +1,5 @@
package xyz.zhouxy.plusone.exception.handler; package xyz.zhouxy.plusone.exception.handler;
import javax.annotation.Nonnull;
import org.springframework.context.support.DefaultMessageSourceResolvable; import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
@@ -13,7 +11,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.commons.util.RestfulResult; import xyz.zhouxy.plusone.commons.util.RestfulResult;
/** /**
@@ -43,7 +40,7 @@ import xyz.zhouxy.plusone.commons.util.RestfulResult;
@Order(Ordered.LOWEST_PRECEDENCE - 1) @Order(Ordered.LOWEST_PRECEDENCE - 1)
@Slf4j @Slf4j
public class DefaultExceptionHandler extends BaseExceptionHandler { public class DefaultExceptionHandler extends BaseExceptionHandler {
public DefaultExceptionHandler(@Nonnull ExceptionInfoHolder exceptionInfoHolder) { public DefaultExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
super(exceptionInfoHolder); super(exceptionInfoHolder);
set(IllegalArgumentException.class, 4010000, "格式错误", HttpStatus.FORBIDDEN); set(IllegalArgumentException.class, 4010000, "格式错误", HttpStatus.FORBIDDEN);
set(DataAccessException.class, 6030000, "数据库错误", HttpStatus.INTERNAL_SERVER_ERROR, true); set(DataAccessException.class, 6030000, "数据库错误", HttpStatus.INTERNAL_SERVER_ERROR, true);

View File

@@ -8,7 +8,6 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.commons.util.RestfulResult; import xyz.zhouxy.plusone.commons.util.RestfulResult;
import xyz.zhouxy.plusone.exception.SysException; import xyz.zhouxy.plusone.exception.SysException;
@@ -16,7 +15,7 @@ import xyz.zhouxy.plusone.exception.SysException;
@Slf4j @Slf4j
public class SysExceptionHandler extends BaseExceptionHandler { public class SysExceptionHandler extends BaseExceptionHandler {
public SysExceptionHandler(@Nonnull ExceptionInfoHolder exceptionInfoHolder) { public SysExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
super(exceptionInfoHolder); super(exceptionInfoHolder);
} }

View File

@@ -49,7 +49,7 @@
<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.9-SNAPSHOT</version> <version>0.0.8-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> </dependencies>

View File

@@ -2,8 +2,6 @@ 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;
public static final int DEFAULT_SYS_ERROR_CODE = 5000000;
public static final int DEFAULT_BIZ_ERROR_CODE = 4000000;
private ErrorCodeConsts() { private ErrorCodeConsts() {
throw new IllegalStateException("Utility class"); throw new IllegalStateException("Utility class");

View File

@@ -1,6 +1,6 @@
package xyz.zhouxy.plusone.util; package xyz.zhouxy.plusone.util;
import java.security.SecureRandom; import java.util.concurrent.ThreadLocalRandom;
public final class RandomUtil { public final class RandomUtil {
private RandomUtil() { private RandomUtil() {
@@ -8,7 +8,7 @@ public final class RandomUtil {
} }
public static String randomStr(char[] sourceCharacters, int length) { public static String randomStr(char[] sourceCharacters, int length) {
SecureRandom random = new SecureRandom(); ThreadLocalRandom random = ThreadLocalRandom.current();
char[] result = new char[length]; char[] result = new char[length];
for (int i = 0; i < length; i++) { for (int i = 0; i < length; i++) {
result[i] = sourceCharacters[random.nextInt(sourceCharacters.length)]; result[i] = sourceCharacters[random.nextInt(sourceCharacters.length)];

View File

@@ -24,10 +24,12 @@ public final class EntityStatus extends Enumeration<EntityStatus> {
private static final ValueSet<EntityStatus> VALUE_SET = new ValueSet<>( private static final ValueSet<EntityStatus> VALUE_SET = new ValueSet<>(
AVAILABLE, DISABLED); AVAILABLE, DISABLED);
@Nonnull
public static EntityStatus of(int id) { public static EntityStatus of(int id) {
return VALUE_SET.get(id); return VALUE_SET.get(id);
} }
@Nonnull
public static Collection<EntityStatus> constants() { public static Collection<EntityStatus> constants() {
return VALUE_SET.getValues(); return VALUE_SET.getValues();
} }

View File

@@ -5,7 +5,7 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import xyz.zhouxy.plusone.constant.ErrorCodeConsts; import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler.ExceptionInfoHolder; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
@Configuration @Configuration
public class PlusoneExceptionHandlerConfig { public class PlusoneExceptionHandlerConfig {

View File

@@ -8,7 +8,7 @@ import java.sql.SQLException;
* *
* <p> * <p>
* 通过在 {@link #map(ResultSet)} 中配置 {@link ResultSet} 到对象的映射, * 通过在 {@link #map(ResultSet)} 中配置 {@link ResultSet} 到对象的映射,
* 可将 {@link #rowMapper(ResultSet, int)} 的方法用, * 可将 {@link #rowMapper(ResultSet, int)} 的方法用,
* 直接当成 {@link org.springframework.jdbc.core.RowMapper} 对象传给 * 直接当成 {@link org.springframework.jdbc.core.RowMapper} 对象传给
* {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate} * {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}
* 的查询方法, * 的查询方法,

View File

@@ -1,17 +1,8 @@
package xyz.zhouxy.plusone.oss; package xyz.zhouxy.plusone.oss;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Objects;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import org.csource.common.MyException; import org.csource.common.MyException;
import org.csource.common.NameValuePair; import org.csource.common.NameValuePair;
@@ -23,11 +14,7 @@ import org.csource.fastdfs.TrackerServer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.common.io.Files;
import lombok.Getter; import lombok.Getter;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.exception.SysException;
public class FastDFSUtil { public class FastDFSUtil {
@@ -57,7 +44,7 @@ public class FastDFSUtil {
* @throws FastDFSException * @throws FastDFSException
*/ */
public String[] upload(FastDFSFile file) throws FastDFSException { public String[] upload(FastDFSFile file) throws FastDFSException {
logger.info("File Name: {}, File Length: {}", file.getFileName(), file.getContent().length); logger.info("File Name: {}, File Length: {}", file.getName(), file.getContent().length);
NameValuePair[] metaList = new NameValuePair[1]; NameValuePair[] metaList = new NameValuePair[1];
metaList[0] = new NameValuePair("author", file.getAuthor()); metaList[0] = new NameValuePair("author", file.getAuthor());
@@ -76,7 +63,7 @@ public class FastDFSUtil {
uploadResults[0], uploadResults[1], System.currentTimeMillis() - startTime); uploadResults[0], uploadResults[1], System.currentTimeMillis() - startTime);
} catch (IOException e) { } catch (IOException e) {
throw new FastDFSException("IO Exception when uploadind the file:" + file.getFileName(), e); throw new FastDFSException("IO Exception when uploadind the file:" + file.getName(), e);
} catch (MyException e) { } catch (MyException e) {
throw new FastDFSException(e); throw new FastDFSException(e);
} }
@@ -122,72 +109,18 @@ public class FastDFSUtil {
} }
} }
@Getter
public static final class FastDFSFile { public static final class FastDFSFile {
@Getter private String name;
private final String fileName; private byte[] content;
private final byte[] content; private String ext;
@Getter private String md5;
private final String ext; private String author;
@Getter
private final String md5;
@Getter
private final String author;
private FastDFSFile(@Nonnull File file, @Nullable String author) throws IOException { public FastDFSFile(String name, byte[] content, String ext) {
this.fileName = file.getName(); this.name = name;
this.content = Files.toByteArray(file);
this.ext = Files.getFileExtension(fileName);
this.md5 = md5Hex(content);
this.author = author;
}
private FastDFSFile(@Nonnull String fileName, @Nonnull byte[] content, @Nullable String author) {
this.fileName = fileName;
this.content = content; this.content = content;
this.ext = Files.getFileExtension(fileName); this.ext = ext;
this.md5 = md5Hex(content);
this.author = author;
}
@Nonnull
@StaticFactoryMethod(FastDFSFile.class)
public static FastDFSFile of(@Nonnull File file) throws IOException {
return new FastDFSFile(file, null);
}
@Nonnull
@StaticFactoryMethod(FastDFSFile.class)
public static FastDFSFile of(@Nonnull File file, @Nullable String author) throws IOException {
return new FastDFSFile(file, author);
}
@Nonnull
@StaticFactoryMethod(FastDFSFile.class)
public static FastDFSFile of(@Nonnull String fileName, @Nonnull byte[] content) {
return new FastDFSFile(fileName, content, null);
}
@Nonnull
@StaticFactoryMethod(FastDFSFile.class)
public static FastDFSFile of(@Nonnull String fileName, @Nonnull byte[] content, @Nullable String author) {
return new FastDFSFile(fileName, content, author);
}
public byte[] getContent() {
return Arrays.copyOf(content, content.length);
}
@Nonnull
private static String md5Hex(byte[] data) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
messageDigest.update(data);
byte[] result = messageDigest.digest();
var sha512Hex = new BigInteger(1, result).toString(16);
return Objects.requireNonNull(sha512Hex);
} catch (NoSuchAlgorithmException e) {
throw new SysException(e);
}
} }
} }
} }

View File

@@ -1,5 +1,7 @@
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;
@@ -8,11 +10,8 @@ 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.constant.ErrorCodeConsts; import xyz.zhouxy.plusone.exception.SysException;
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;
@@ -62,14 +61,13 @@ public class TencentSmsServiceImpl implements SmsService {
var res = client.SendSms(req); var res = client.SendSms(req);
// 输出json格式的字符串回包 // 输出json格式的字符串回包
System.out.println(SendSmsResponse.toJsonString(res)); log.info(SendSmsResponse.toJsonString(res));
// 也可以取出单个值你可以通过官网接口文档或跳转到response对象的定义处查看返回字段的定义 // 也可以取出单个值你可以通过官网接口文档或跳转到response对象的定义处查看返回字段的定义
// System.out.println(res.getRequestId()); // System.out.println(res.getRequestId());
} catch (TencentCloudSDKException e) { } catch (TencentCloudSDKException e) {
log.error(e.getMessage(), e); throw new SysException(e);
throw new BizException(ErrorCodeConsts.DEFAULT_ERROR_CODE, e);
} }
} }

View File

@@ -1,15 +1,13 @@
package xyz.zhouxy.plusone.validator; package xyz.zhouxy.plusone.validator;
import javax.annotation.Nonnull;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
@RestControllerAdvice @RestControllerAdvice
public class InvalidInputExceptionHandler extends BaseExceptionHandler { public class InvalidInputExceptionHandler extends BaseExceptionHandler {
public InvalidInputExceptionHandler(@Nonnull ExceptionInfoHolder exceptionInfoHolder) { public InvalidInputExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
super(exceptionInfoHolder); super(exceptionInfoHolder);
set(InvalidInputException.class, InvalidInputException.ERROR_CODE, "无效的用户输入"); set(InvalidInputException.class, InvalidInputException.ERROR_CODE, "无效的用户输入");
} }

View File

@@ -3,10 +3,14 @@ package xyz.zhouxy.plusone;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import lombok.extern.slf4j.Slf4j;
@SpringBootApplication @SpringBootApplication
@Slf4j
public class PlusoneApplication { public class PlusoneApplication {
public static void main(String[] args) { public static void main(String[] args) {
log.debug("Plusone started!");
SpringApplication.run(PlusoneApplication.class, args); SpringApplication.run(PlusoneApplication.class, args);
} }

View File

@@ -1,11 +1,12 @@
package xyz.zhouxy.plusone; package xyz.zhouxy.plusone;
import java.io.File; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import javax.annotation.Resource; import javax.annotation.Resource;
import org.apache.commons.io.IOUtils;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest;
@@ -23,7 +24,10 @@ class FastDFSTests {
@Test @Test
void testOSS() throws FileNotFoundException, IOException, FastDFSException { void testOSS() throws FileNotFoundException, IOException, FastDFSException {
String[] upload = fastDFSUtil.upload(FastDFSFile.of(new File("D:\\ZhouXY\\Desktop\\666.png"))); try (FileInputStream in = new FileInputStream("D:\\ZhouXY\\Desktop\\666.png");) {
log.info(String.join("/", upload)); byte[] content = IOUtils.toByteArray(in);
String[] upload = fastDFSUtil.upload(new FastDFSFile("666.png", content, "png"));
log.info(String.join("/", upload));
}
} }
} }

View File

@@ -1,138 +0,0 @@
package xyz.zhouxy.plusone.system.application.common.model;
import java.util.Map;
import java.util.Optional;
import java.util.OptionalInt;
import java.util.OptionalLong;
import java.util.OptionalDouble;
import java.util.concurrent.ConcurrentHashMap;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import xyz.zhouxy.plusone.exception.BizException;
public class AuthenticationInfo<T> {
/** token 值 */
private final String token;
/** 此 token 对应的LoginId未登录时不会构建此类的实例 */
private final T loginId;
/** 账号类型 */
private final String loginType;
/** 登录设备类型 */
private final String deviceType;
/** 自定义数据 */
@Nonnull
private final Map<String, Object> metadata;
private AuthenticationInfo(String token, T loginId, String loginType, String deviceType,
@Nonnull Map<String, Object> metadata) {
this.token = token;
this.loginId = loginId;
this.loginType = loginType;
this.deviceType = deviceType;
this.metadata = metadata;
}
public String getToken() {
return token;
}
public T getLoginId() {
return loginId;
}
public String getLoginType() {
return loginType;
}
public String getDeviceType() {
return deviceType;
}
private Object getObjFromMetadata(String key) {
if (this.metadata.containsKey(key)) {
return this.metadata.get(key);
}
throw new BizException(String.format("不存在 key 为 \"%s\"的元数据。", key));
}
public OptionalDouble getMetadataAsDouble(String key) {
Object valObj = getObjFromMetadata(key);
if (valObj instanceof Double val) {
return OptionalDouble.of(val.doubleValue());
}
return OptionalDouble.empty();
}
public OptionalLong getMetadataAsLong(String key) {
Object valObj = getObjFromMetadata(key);
if (valObj instanceof Long val) {
return OptionalLong.of(val.longValue());
}
return OptionalLong.empty();
}
public OptionalInt getMetadataAsInt(String key) {
Object valObj = getObjFromMetadata(key);
if (valObj instanceof Integer val) {
return OptionalInt.of(val.intValue());
}
return OptionalInt.empty();
}
public Optional<String> getMetadataAsString(String key) {
Object valObj = getObjFromMetadata(key);
if (valObj instanceof String val) {
return Optional.of(val);
}
return Optional.empty();
}
@SuppressWarnings("unchecked")
public <C> Optional<C> getMetadata(String key, Class<C> type) {
Object valObj = getObjFromMetadata(key);
if (valObj == null || !type.isAssignableFrom(valObj.getClass())) {
return Optional.empty();
}
return Optional.of((C) valObj);
}
// ==========================================
// builder
public static <T> Builder<T> builder(String token, T loginId, String loginType, String deviceType) {
return new Builder<>(token, loginId, loginType, deviceType);
}
public static final class Builder<T> {
private final String token;
private final T loginId;
private final String loginType;
private final String deviceType;
@Nonnull
private final Map<String, Object> meta = new ConcurrentHashMap<>();
private Builder(String token, T loginId, String loginType, String deviceType) {
this.token = token;
this.loginId = loginId;
this.loginType = loginType;
this.deviceType = deviceType;
}
public <C> Builder<T> putMetadata(String key, @Nullable C value) {
this.meta.put(key, value);
return this;
}
public AuthenticationInfo<T> build() {
return new AuthenticationInfo<>(token, loginId, loginType, deviceType, meta);
}
}
}

View File

@@ -1,21 +0,0 @@
package xyz.zhouxy.plusone.system.application.common.model;
public class PlusoneContext {
private static final ThreadLocal<AuthenticationInfo<Long>> context = new ThreadLocal<>();
public static void setContext(AuthenticationInfo<Long> value) {
context.set(value);
}
public static AuthenticationInfo<Long> getContext() {
return context.get();
}
public static void remove() {
context.remove();
}
private PlusoneContext() {
throw new IllegalStateException("Utility class");
}
}

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.web.controller; package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic; import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.web.controller; package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic; import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success; import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.web.controller; package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success; import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.web.controller; package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic; import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success; import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.web.controller; package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic; import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success; import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;
@@ -15,6 +15,7 @@ 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;
@@ -66,7 +67,14 @@ 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 RestfulResult.success("查询成功", result); return 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,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.web.controller; package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success; import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.web.controller; package xyz.zhouxy.plusone.system.application.controller;
import javax.validation.Valid; import javax.validation.Valid;
import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic; import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.common.exception; package xyz.zhouxy.plusone.system.application.exception;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.common.exception; package xyz.zhouxy.plusone.system.application.exception;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.ResponseStatus;

View File

@@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.common.exception; package xyz.zhouxy.plusone.system.application.exception;
import xyz.zhouxy.plusone.validator.InvalidInputException; import xyz.zhouxy.plusone.validator.InvalidInputException;

View File

@@ -1,12 +1,14 @@
package xyz.zhouxy.plusone.system.application.common.exception.handler; package xyz.zhouxy.plusone.system.application.exception.handler;
import javax.annotation.Nonnull;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.system.application.exception.AccountLoginException;
import xyz.zhouxy.plusone.commons.util.RestfulResult; import xyz.zhouxy.plusone.commons.util.RestfulResult;
import xyz.zhouxy.plusone.system.application.common.exception.AccountLoginException;
@RestControllerAdvice @RestControllerAdvice
public class AccountLoginExceptionHandler extends BaseExceptionHandler { public class AccountLoginExceptionHandler extends BaseExceptionHandler {
@@ -16,7 +18,7 @@ public class AccountLoginExceptionHandler extends BaseExceptionHandler {
} }
@ExceptionHandler({ AccountLoginException.class }) @ExceptionHandler({ AccountLoginException.class })
public ResponseEntity<RestfulResult> handleException(Exception e) { public ResponseEntity<RestfulResult> handleException(@Nonnull Exception e) {
return buildExceptionResponse(e); return buildExceptionResponse(e);
} }
} }

View File

@@ -1,6 +1,4 @@
package xyz.zhouxy.plusone.system.application.common.exception.handler; package xyz.zhouxy.plusone.system.application.exception.handler;
import javax.annotation.Nonnull;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -16,7 +14,7 @@ import cn.dev33.satoken.exception.NotSafeException;
import cn.dev33.satoken.exception.SaTokenException; import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.exception.SameTokenInvalidException; import cn.dev33.satoken.exception.SameTokenInvalidException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.commons.util.RestfulResult; import xyz.zhouxy.plusone.commons.util.RestfulResult;
/** /**
@@ -29,7 +27,7 @@ import xyz.zhouxy.plusone.commons.util.RestfulResult;
public class SaTokenExceptionHandler extends BaseExceptionHandler { public class SaTokenExceptionHandler extends BaseExceptionHandler {
public SaTokenExceptionHandler(@Nonnull ExceptionInfoHolder exceptionInfoHolder) { public SaTokenExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
super(exceptionInfoHolder); super(exceptionInfoHolder);
set(NotPermissionException.class, 4030103, "会话未能通过权限认证", HttpStatus.FORBIDDEN); set(NotPermissionException.class, 4030103, "会话未能通过权限认证", HttpStatus.FORBIDDEN);
set(NotRoleException.class, 4030103, "会话未能通过角色认证", HttpStatus.FORBIDDEN); set(NotRoleException.class, 4030103, "会话未能通过角色认证", HttpStatus.FORBIDDEN);

View File

@@ -2,8 +2,6 @@ package xyz.zhouxy.plusone.system.application.query;
import java.util.List; import java.util.List;
import javax.annotation.Nonnull;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
import xyz.zhouxy.plusone.commons.util.PageDTO; import xyz.zhouxy.plusone.commons.util.PageDTO;
@@ -25,7 +23,6 @@ public interface AccountQueries {
return PageDTO.of(content, total); return PageDTO.of(content, total);
} }
@Nonnull
List<AccountOverview> queryAccountOverview(AccountQueryParams queryParams); List<AccountOverview> queryAccountOverview(AccountQueryParams queryParams);
long count(AccountQueryParams queryParams); long count(AccountQueryParams queryParams);

View File

@@ -0,0 +1,23 @@
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

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

View File

@@ -0,0 +1,18 @@
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,60 +25,28 @@ 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 {
@Getter private @Getter @Setter Integer type;
@Setter
Integer type;
@Getter private @Getter @Setter String typeName;
@Setter
String typeName;
@Getter private @Getter @Setter Long id;
@Setter private @Getter @Setter Long parentId;
Long id;
@Getter
@Setter
Long parentId;
@Getter private @Getter @Setter String name;
@Setter
String name;
// 若 type 为 MENU_ITEM 且 path 以 http:// 或 https:// 开头则被识别为外链 // 若 type 为 MENU_ITEM 且 path 以 http:// 或 https:// 开头则被识别为外链
@Getter private @Getter @Setter String path;
@Setter private @Getter @Setter String title;
String path; private @Getter @Setter String icon;
@Getter private @Getter @Setter boolean hidden;
@Setter private @Getter @Setter int orderNumber;
String title; private @Getter @Setter Integer status;
@Getter private @Getter @Setter String remarks;
@Setter
String icon;
@Getter
@Setter
boolean hidden;
@Getter
@Setter
int orderNumber;
@Getter
@Setter
Integer status;
@Getter
@Setter
String remarks;
// MENU_ITEM // MENU_ITEM
@Getter private @Getter @Setter String component;
@Setter private @Getter @Setter Boolean cache;
String component; private @Getter @Setter String resource;
@Getter private @Getter @Setter List<Action> actions;
@Setter
Boolean cache;
@Getter
@Setter
String resource;
@Getter
@Setter
List<Action> actions;
// MENU_LIST // MENU_LIST
List<MenuViewObject> children; List<MenuViewObject> children;

View File

@@ -8,9 +8,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import cn.dev33.satoken.stp.StpLogic; import cn.dev33.satoken.stp.StpLogic;
import xyz.zhouxy.plusone.system.application.common.exception.AccountLoginException;
import xyz.zhouxy.plusone.system.application.common.exception.UnsupportedPrincipalTypeException; import xyz.zhouxy.plusone.system.application.common.exception.UnsupportedPrincipalTypeException;
import xyz.zhouxy.plusone.system.application.common.util.PrincipalUtil; import xyz.zhouxy.plusone.system.application.common.util.PrincipalUtil;
import xyz.zhouxy.plusone.system.application.exception.AccountLoginException;
import xyz.zhouxy.plusone.system.application.query.AccountQueries; import xyz.zhouxy.plusone.system.application.query.AccountQueries;
import xyz.zhouxy.plusone.system.application.query.result.AccountDetails; import xyz.zhouxy.plusone.system.application.query.result.AccountDetails;
import xyz.zhouxy.plusone.system.application.query.result.MenuViewObject; import xyz.zhouxy.plusone.system.application.query.result.MenuViewObject;

View File

@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.PathVariable;
import xyz.zhouxy.plusone.commons.util.PageDTO; import xyz.zhouxy.plusone.commons.util.PageDTO;
import xyz.zhouxy.plusone.exception.DataNotExistException; import xyz.zhouxy.plusone.exception.DataNotExistException;
import xyz.zhouxy.plusone.system.application.common.exception.AccountRegisterException; import xyz.zhouxy.plusone.system.application.exception.AccountRegisterException;
import xyz.zhouxy.plusone.system.application.query.AccountQueries; import xyz.zhouxy.plusone.system.application.query.AccountQueries;
import xyz.zhouxy.plusone.system.application.query.params.AccountQueryParams; import xyz.zhouxy.plusone.system.application.query.params.AccountQueryParams;
import xyz.zhouxy.plusone.system.application.query.result.AccountDetails; import xyz.zhouxy.plusone.system.application.query.result.AccountDetails;
@@ -94,6 +94,7 @@ public class AccountManagementService {
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(), Sex.of(command.getSex()));
account.setUpdatedBy(adminAuthLogic.getLoginIdAsLong());
accountRepository.save(account); accountRepository.save(account);
} }

View File

@@ -6,10 +6,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import xyz.zhouxy.plusone.system.application.common.exception.AccountLoginException;
import xyz.zhouxy.plusone.system.application.common.exception.UnsupportedPrincipalTypeException; import xyz.zhouxy.plusone.system.application.common.exception.UnsupportedPrincipalTypeException;
import xyz.zhouxy.plusone.system.application.common.util.PrincipalType; import xyz.zhouxy.plusone.system.application.common.util.PrincipalType;
import xyz.zhouxy.plusone.system.application.common.util.PrincipalUtil; import xyz.zhouxy.plusone.system.application.common.util.PrincipalUtil;
import xyz.zhouxy.plusone.system.application.exception.AccountLoginException;
import xyz.zhouxy.plusone.system.application.query.AccountQueries; import xyz.zhouxy.plusone.system.application.query.AccountQueries;
import xyz.zhouxy.plusone.system.application.query.result.LoginInfoViewObject; import xyz.zhouxy.plusone.system.application.query.result.LoginInfoViewObject;
import xyz.zhouxy.plusone.system.application.service.command.LoginByOtpCommand; import xyz.zhouxy.plusone.system.application.service.command.LoginByOtpCommand;

View File

@@ -9,8 +9,8 @@ import org.springframework.util.Assert;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import xyz.zhouxy.plusone.mail.MailService; import xyz.zhouxy.plusone.mail.MailService;
import xyz.zhouxy.plusone.sms.SmsService; import xyz.zhouxy.plusone.sms.SmsService;
import xyz.zhouxy.plusone.system.application.common.exception.AccountLoginException; import xyz.zhouxy.plusone.system.application.exception.AccountLoginException;
import xyz.zhouxy.plusone.system.application.common.exception.AccountRegisterException; import xyz.zhouxy.plusone.system.application.exception.AccountRegisterException;
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.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;

View File

@@ -16,7 +16,9 @@ import org.springframework.util.Assert;
import xyz.zhouxy.plusone.constant.EntityStatus; 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.common.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;
@@ -36,10 +38,12 @@ 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 roleRepository, MenuRepository menuRepository) { MenuManagementService(MenuService menuService, MenuRepository menuRepository, MenuQueries menuQueries) {
this.menuService = roleRepository; this.menuService = menuService;
this.menuRepository = menuRepository; this.menuRepository = menuRepository;
this.menuQueries = menuQueries;
} }
// ==================== create ==================== // ==================== create ====================
@@ -123,6 +127,11 @@ 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

@@ -5,10 +5,10 @@ import java.util.Set;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import xyz.zhouxy.plusone.system.application.common.exception.AccountRegisterException;
import xyz.zhouxy.plusone.system.application.common.exception.UnsupportedPrincipalTypeException; import xyz.zhouxy.plusone.system.application.common.exception.UnsupportedPrincipalTypeException;
import xyz.zhouxy.plusone.system.application.common.util.PrincipalType; import xyz.zhouxy.plusone.system.application.common.util.PrincipalType;
import xyz.zhouxy.plusone.system.application.common.util.PrincipalUtil; import xyz.zhouxy.plusone.system.application.common.util.PrincipalUtil;
import xyz.zhouxy.plusone.system.application.exception.AccountRegisterException;
import xyz.zhouxy.plusone.system.application.service.command.RegisterAccountCommand; import xyz.zhouxy.plusone.system.application.service.command.RegisterAccountCommand;
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;

View File

@@ -1,20 +0,0 @@
package xyz.zhouxy.plusone.system.application.web.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
@Autowired
HandlerInterceptor[] interceptors;
@Override
public void addInterceptors(InterceptorRegistry registry) {
for (var interceptor : interceptors) {
registry.addInterceptor(interceptor);
}
}
}

View File

@@ -1,32 +0,0 @@
package xyz.zhouxy.plusone.system.application.web.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.system.application.common.model.PlusoneContext;
import static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic;;
@Slf4j
@Order(1)
@Component
public class HttpContextInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
log.info("" + adminAuthLogic.isLogin());
return true;
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
PlusoneContext.remove();
log.info("拦截器清理 ThreadLocal防止内存泄漏");
}
}

View File

@@ -1,7 +0,0 @@
/**
* 拦截器
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
* @since 1.0
*/
package xyz.zhouxy.plusone.system.application.web.interceptor;

View File

@@ -1,12 +1,13 @@
package xyz.zhouxy.plusone.system.util; package xyz.zhouxy.plusone.system.util;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.Arrays; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.springframework.util.Assert; import javax.annotation.Nonnull;
import com.google.common.hash.Hashing;
import xyz.zhouxy.plusone.exception.SysException;
import xyz.zhouxy.plusone.util.RandomUtil; import xyz.zhouxy.plusone.util.RandomUtil;
/** /**
@@ -25,18 +26,18 @@ public final class PasswordUtil {
* @param salt 随机盐 * @param salt 随机盐
* @return 哈希加密的结果 * @return 哈希加密的结果
*/ */
public static String hashPassword(String password, String salt) { @Nonnull
Assert.notNull(password, "Password must not be null"); public static String hashPassword(@Nonnull String password, @Nonnull String salt) {
Assert.notNull(salt, "Salt must not be null"); int length = salt.length();
return Hashing.sha512().newHasher() int i = length > 0 ? length / 2 : 0;
.putInt(Arrays.hashCode(salt.toCharArray())) var passwordWithSalt = salt.substring(0, i)
.putString(password, StandardCharsets.UTF_8) + password
.putInt(password.length()) + salt.substring(i);
.putBoolean(password.length() % 2 == 0) try {
.putString(salt, StandardCharsets.UTF_8) return sha512Hex(passwordWithSalt);
.putInt(Arrays.hashCode(password.toCharArray())) } catch (NoSuchAlgorithmException e) {
.hash() throw new SysException(e);
.toString(); }
} }
/** /**
@@ -52,4 +53,13 @@ public final class 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

@@ -6,7 +6,6 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import lombok.ToString; import lombok.ToString;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.domain.AggregateRoot; import xyz.zhouxy.plusone.domain.AggregateRoot;
import xyz.zhouxy.plusone.domain.IWithVersion; import xyz.zhouxy.plusone.domain.IWithVersion;
import xyz.zhouxy.plusone.exception.UserOperationException; import xyz.zhouxy.plusone.exception.UserOperationException;
@@ -165,7 +164,6 @@ public class Account extends AggregateRoot<Long> implements IWithVersion {
return newInstance; return newInstance;
} }
@StaticFactoryMethod(Account.class)
public static Account register( public static Account register(
Username username, Username username,
Email email, Email email,
@@ -195,7 +193,6 @@ public class Account extends AggregateRoot<Long> implements IWithVersion {
password, status, accountInfo, roleRefs, createdBy, updatedBy, version); password, status, accountInfo, roleRefs, createdBy, updatedBy, version);
} }
@StaticFactoryMethod(Account.class)
public static Account newInstance( public static Account newInstance(
String username, String username,
String email, String email,
@@ -213,7 +210,6 @@ public class Account extends AggregateRoot<Long> implements IWithVersion {
return newInstance; return newInstance;
} }
@StaticFactoryMethod(Account.class)
public static Account register( public static Account register(
String username, String username,
String email, String email,
@@ -269,6 +265,10 @@ public class Account extends AggregateRoot<Long> implements IWithVersion {
return Optional.ofNullable(updatedBy); return Optional.ofNullable(updatedBy);
} }
public void setUpdatedBy(long updatedBy) {
this.updatedBy = updatedBy;
}
@Override @Override
public long getVersion() { public long getVersion() {
return this.version; return this.version;

View File

@@ -31,6 +31,7 @@ public final class AccountStatus extends Enumeration<AccountStatus> implements I
return VALUE_SET.get(id); return VALUE_SET.get(id);
} }
@Nonnull
public static Collection<AccountStatus> constants() { public static Collection<AccountStatus> constants() {
return VALUE_SET.getValues(); return VALUE_SET.getValues();
} }

View File

@@ -4,7 +4,6 @@ import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import cn.hutool.core.util.DesensitizedUtil; import cn.hutool.core.util.DesensitizedUtil;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.commons.constant.PatternConsts;
/** /**
@@ -27,12 +26,10 @@ public class Email extends Principal {
} }
} }
@StaticFactoryMethod(Email.class)
public static Email of(String email) { public static Email of(String email) {
return new Email(email); return new Email(email);
} }
@StaticFactoryMethod(Email.class)
public static Email ofNullable(String email) { public static Email ofNullable(String email) {
return Objects.nonNull(email) ? new Email(email) : null; return Objects.nonNull(email) ? new Email(email) : null;
} }

View File

@@ -4,7 +4,6 @@ import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import cn.hutool.core.util.DesensitizedUtil; import cn.hutool.core.util.DesensitizedUtil;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.commons.constant.PatternConsts;
/** /**
@@ -27,12 +26,10 @@ public class MobilePhone extends Principal {
} }
} }
@StaticFactoryMethod(MobilePhone.class)
public static MobilePhone of(String mobilePhone) { public static MobilePhone of(String mobilePhone) {
return new MobilePhone(mobilePhone); return new MobilePhone(mobilePhone);
} }
@StaticFactoryMethod(MobilePhone.class)
public static MobilePhone ofNullable(String mobilePhone) { public static MobilePhone ofNullable(String mobilePhone) {
return Objects.nonNull(mobilePhone) ? new MobilePhone(mobilePhone) : null; return Objects.nonNull(mobilePhone) ? new MobilePhone(mobilePhone) : null;
} }

View File

@@ -3,7 +3,6 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.commons.constant.PatternConsts;
import xyz.zhouxy.plusone.domain.ValidatableStringRecord; import xyz.zhouxy.plusone.domain.ValidatableStringRecord;
@@ -27,12 +26,10 @@ public class Nickname extends ValidatableStringRecord {
} }
} }
@StaticFactoryMethod(Nickname.class)
public static Nickname of(String nickname) { public static Nickname of(String nickname) {
return new Nickname(nickname); return new Nickname(nickname);
} }
@StaticFactoryMethod(Nickname.class)
public static Nickname ofNullable(String nickname) { public static Nickname ofNullable(String nickname) {
return Objects.nonNull(nickname) ? new Nickname(nickname) : null; return Objects.nonNull(nickname) ? new Nickname(nickname) : null;
} }

View File

@@ -3,11 +3,13 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects; import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.annotation.Nonnull;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.commons.constant.PatternConsts;
import xyz.zhouxy.plusone.domain.IValueObject; import xyz.zhouxy.plusone.domain.IValueObject;
import xyz.zhouxy.plusone.exception.SysException;
import xyz.zhouxy.plusone.system.util.PasswordUtil; import xyz.zhouxy.plusone.system.util.PasswordUtil;
/** /**
@@ -20,35 +22,43 @@ public class Password implements IValueObject {
private static final Pattern PATTERN = PatternConsts.PASSWORD; private static final Pattern PATTERN = PatternConsts.PASSWORD;
private static final String DEFAULT_PASSWORD = "A1b2C3d4"; private static final String DEFAULT_PASSWORD = "A1b2C3d4";
@Nonnull
private final String passwordVal; private final String passwordVal;
@Nonnull
private final String saltVal; private final String saltVal;
private Password(String password) { private Password(String password) {
Assert.notNull(password, "密码不能为空"); if (password == null) {
Assert.isTrue(PATTERN.matcher(password).matches(), "密码格式不符合要求"); throw new IllegalArgumentException("密码不能为空");
String salt = PasswordUtil.generateRandomSalt(); }
if (!PATTERN.matcher(password).matches()) {
throw new IllegalArgumentException("密码格式不符合要求");
}
var salt = PasswordUtil.generateRandomSalt();
if (salt == null) {
throw new SysException("未知错误:生成随机盐失败");
}
this.saltVal = salt; this.saltVal = salt;
this.passwordVal = PasswordUtil.hashPassword(password, salt); this.passwordVal = PasswordUtil.hashPassword(password, salt);
} }
private Password(String password, String salt) { private Password(String password, String salt) {
Assert.isTrue(password != null && salt != null, "password 和 salt 不能为空"); if (password == null || salt == null) {
throw new IllegalArgumentException("password 和 salt 不能为空");
}
this.passwordVal = password; this.passwordVal = password;
this.saltVal = salt; this.saltVal = salt;
} }
@StaticFactoryMethod(Password.class)
public static Password of(String password, String salt) { public static Password of(String password, String salt) {
return new Password(password, salt); return new Password(password, salt);
} }
@StaticFactoryMethod(Password.class)
public static Password newPassword(String newPassword, String passwordConfirmation) { public static Password newPassword(String newPassword, String passwordConfirmation) {
Assert.isTrue(Objects.equals(newPassword, passwordConfirmation), "两次输入的密码不一致"); Assert.isTrue(Objects.equals(newPassword, passwordConfirmation), "两次输入的密码不一致");
return newPassword(newPassword); return newPassword(newPassword);
} }
@StaticFactoryMethod(Password.class)
public static Password newPassword(String newPassword) { public static Password newPassword(String newPassword) {
return new Password(newPassword); return new Password(newPassword);
} }
@@ -69,7 +79,6 @@ public class Password implements IValueObject {
return saltVal; return saltVal;
} }
@StaticFactoryMethod(Nickname.class)
public static Password newDefaultPassword() { public static Password newDefaultPassword() {
return newPassword(DEFAULT_PASSWORD); return newPassword(DEFAULT_PASSWORD);
} }

View File

@@ -4,7 +4,6 @@ import java.util.Collection;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
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;
@@ -27,11 +26,12 @@ public final class Sex extends Enumeration<Sex> implements IValueObject {
private static final ValueSet<Sex> VALUE_SET = new ValueSet<>(UNSET, MALE, FEMALE); private static final ValueSet<Sex> VALUE_SET = new ValueSet<>(UNSET, MALE, FEMALE);
@StaticFactoryMethod(Sex.class) @Nonnull
public static Sex of(int value) { public static Sex of(int value) {
return VALUE_SET.get(value); return VALUE_SET.get(value);
} }
@Nonnull
public static Collection<Sex> constants() { public static Collection<Sex> constants() {
return VALUE_SET.getValues(); return VALUE_SET.getValues();
} }

View File

@@ -2,7 +2,6 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.constant.PatternConsts; import xyz.zhouxy.plusone.commons.constant.PatternConsts;
/** /**
@@ -25,7 +24,6 @@ public class Username extends Principal {
} }
} }
@StaticFactoryMethod(Username.class)
public static Username of(String username) { public static Username of(String username) {
return new Username(username); return new Username(username);
} }

View File

@@ -8,7 +8,6 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import lombok.ToString; import lombok.ToString;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.domain.AggregateRoot; import xyz.zhouxy.plusone.domain.AggregateRoot;
import xyz.zhouxy.plusone.domain.IWithLabel; import xyz.zhouxy.plusone.domain.IWithLabel;
import xyz.zhouxy.plusone.domain.IWithVersion; import xyz.zhouxy.plusone.domain.IWithVersion;
@@ -71,14 +70,12 @@ public class Dict extends AggregateRoot<Long> implements IWithLabel, IWithVersio
this.version = version; this.version = version;
} }
@StaticFactoryMethod(Dict.class)
public static Dict newInstance( public static Dict newInstance(
String dictType, String dictType,
String dictLabel) { String dictLabel) {
return new Dict(null, dictType, dictLabel, Collections.emptySet(), 0); return new Dict(null, dictType, dictLabel, Collections.emptySet(), 0);
} }
@StaticFactoryMethod(Dict.class)
public static Dict newInstance( public static Dict newInstance(
String dictType, String dictType,
String dictLabel, String dictLabel,
@@ -86,7 +83,6 @@ public class Dict extends AggregateRoot<Long> implements IWithLabel, IWithVersio
return new Dict(null, dictType, dictLabel, values, 0); return new Dict(null, dictType, dictLabel, values, 0);
} }
@StaticFactoryMethod(Dict.class)
public static Dict newInstance( public static Dict newInstance(
String dictType, String dictType,
String dictLabel, String dictLabel,

View File

@@ -4,7 +4,6 @@ import java.util.Objects;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.domain.IValueObject; import xyz.zhouxy.plusone.domain.IValueObject;
/** /**
@@ -26,7 +25,6 @@ public class DictValue implements IValueObject {
this.label = label; this.label = label;
} }
@StaticFactoryMethod(DictValue.class)
public static DictValue of(int key, String label) { public static DictValue of(int key, String label) {
return new DictValue(key, label); return new DictValue(key, label);
} }

View File

@@ -2,7 +2,6 @@ package xyz.zhouxy.plusone.system.domain.model.menu;
import java.util.List; import java.util.List;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.constant.EntityStatus; import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType; import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType;
@@ -17,7 +16,6 @@ public class MenuConstructor {
throw new IllegalStateException("Utility class"); throw new IllegalStateException("Utility class");
} }
@StaticFactoryMethod(Menu.class)
public static Menu newMenuItem( public static Menu newMenuItem(
long parentId, long parentId,
String path, String path,
@@ -41,7 +39,6 @@ public class MenuConstructor {
remarks, component, cache, resource, actions, 0L); remarks, component, cache, resource, actions, 0L);
} }
@StaticFactoryMethod(Menu.class)
public static Menu newMenuList( public static Menu newMenuList(
long parentId, long parentId,
String path, String path,

View File

@@ -3,7 +3,6 @@ package xyz.zhouxy.plusone.system.domain.model.permission;
import java.util.Optional; import java.util.Optional;
import lombok.Getter; import lombok.Getter;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.domain.Entity; import xyz.zhouxy.plusone.domain.Entity;
import xyz.zhouxy.plusone.domain.IWithLabel; import xyz.zhouxy.plusone.domain.IWithLabel;
import xyz.zhouxy.plusone.domain.IWithVersion; import xyz.zhouxy.plusone.domain.IWithVersion;
@@ -21,7 +20,7 @@ public class Action extends Entity<Long> implements IWithLabel, IWithVersion {
@Getter String label; @Getter String label;
@Getter long version; @Getter long version;
private Action(Long id, String resource, String identifier, String label, long version) { public Action(Long id, String resource, String identifier, String label, long version) {
this.id = id; this.id = id;
this.resource = resource; this.resource = resource;
this.identifier = identifier; this.identifier = identifier;
@@ -29,12 +28,10 @@ public class Action extends Entity<Long> implements IWithLabel, IWithVersion {
this.version = version; this.version = version;
} }
@StaticFactoryMethod(Action.class)
static Action newInstance(String resource, String identifier, String label) { static Action newInstance(String resource, String identifier, String label) {
return new Action(null, resource, identifier, label, 0L); return new Action(null, resource, identifier, label, 0L);
} }
@StaticFactoryMethod(Action.class)
static Action existingInstance(Long id, String resource, String action, String label, Long version) { static Action existingInstance(Long id, String resource, String action, String label, Long version) {
return new Action(id, resource, action, label, version); return new Action(id, resource, action, label, version);
} }

View File

@@ -6,7 +6,6 @@ import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import lombok.Getter; import lombok.Getter;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.domain.AggregateRoot; import xyz.zhouxy.plusone.domain.AggregateRoot;
import xyz.zhouxy.plusone.domain.IWithVersion; import xyz.zhouxy.plusone.domain.IWithVersion;
@@ -38,7 +37,6 @@ public class Permission extends AggregateRoot<Long> implements IWithVersion {
// ==================== 实例化 ==================== // ==================== 实例化 ====================
@StaticFactoryMethod(Permission.class)
public static Permission newInstance(String resource) { public static Permission newInstance(String resource) {
return new Permission( return new Permission(
null, resource, null, resource,

View File

@@ -25,7 +25,7 @@
<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.11</spring-boot.version> <spring-boot.version>2.7.10</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.16</hutool.version>
<mybatis-starter.version>3.0.1</mybatis-starter.version> <mybatis-starter.version>3.0.1</mybatis-starter.version>