Compare commits

..

No commits in common. "dev" and "main" have entirely different histories.
dev ... main

93 changed files with 551 additions and 851 deletions

View File

@ -19,10 +19,3 @@
目前项目还没完成,开发中……
相关的文档和介绍完善中……
## 编码规约
### 关于 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

@ -222,10 +222,6 @@
{
"code": 4040201,
"description": "不支持的 PrincipalType"
},
{
"code": 4040209,
"description": "不支持的菜单类型"
}
]
},

View File

@ -1,6 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone-basic</artifactId>

View File

@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.exception.handler.RestfulResult;
/**
*
@ -62,7 +62,7 @@ public class DefaultExceptionHandler extends BaseExceptionHandler {
DataAccessException.class,
MethodArgumentNotValidException.class
})
public ResponseEntity<UnifiedResponse> handleException(Exception e) {
public ResponseEntity<RestfulResult> handleException(Exception e) {
log.error(e.getMessage(), e);
return buildExceptionResponse(e);
}

View File

@ -9,7 +9,7 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
import xyz.zhouxy.plusone.exception.SysException;
@RestControllerAdvice
@ -21,9 +21,9 @@ public class SysExceptionHandler extends BaseExceptionHandler {
}
@ExceptionHandler({ SysException.class })
public ResponseEntity<UnifiedResponse> handleException(@Nonnull Exception e) {
public ResponseEntity<RestfulResult> handleException(@Nonnull Exception e) {
log.error(e.getMessage(), e);
HttpStatus httpStatus = getHttpStatus(e);
return new ResponseEntity<>(UnifiedResponse.error(getErrorCode(e), "系统错误"), httpStatus);
return new ResponseEntity<>(RestfulResult.error(getErrorCode(e), "系统错误"), httpStatus);
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone-basic</artifactId>

View File

@ -2,8 +2,6 @@ package xyz.zhouxy.plusone.constant;
public class ErrorCodeConsts {
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() {
throw new IllegalStateException("Utility class");

View File

@ -1,39 +1,39 @@
package xyz.zhouxy.plusone.exception;
import xyz.zhouxy.plusone.commons.exception.BaseRuntimeException;
import xyz.zhouxy.plusone.commons.exception.BaseException;
/**
*
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public class BizException extends BaseRuntimeException {
public class BizException extends BaseException {
@java.io.Serial
private static final long serialVersionUID = -5524759033245815405L;
public static final String DEFAULT_ERROR_CODE = "4000000";
public static final int DEFAULT_ERROR_CODE = 4000000;
public BizException(String code, String msg) {
public BizException(int code, String msg) {
super(code, msg);
}
public BizException(String code, Throwable cause) {
public BizException(int code, Throwable cause) {
super(code, cause);
}
public BizException(String code, String msg, Throwable cause) {
public BizException(int code, String msg, Throwable cause) {
super(code, msg, cause);
}
public static BizException of(String msg) {
return new BizException(DEFAULT_ERROR_CODE, msg);
public BizException(String msg) {
super(DEFAULT_ERROR_CODE, msg);
}
public static BizException of(Throwable cause) {
return new BizException(DEFAULT_ERROR_CODE, cause);
public BizException(Throwable cause) {
super(DEFAULT_ERROR_CODE, cause);
}
public static BizException of(String msg, Throwable cause) {
return new BizException(DEFAULT_ERROR_CODE, msg, cause);
public BizException(String msg, Throwable cause) {
super(DEFAULT_ERROR_CODE, msg, cause);
}
}

View File

@ -14,7 +14,7 @@ public class DataNotExistException extends BizException {
@java.io.Serial
private static final long serialVersionUID = 6536955800679703111L;
public static final String ERROR_CODE = "4110100";
public static final int ERROR_CODE = 4110100;
public DataNotExistException() {
super(ERROR_CODE, "数据不存在");

View File

@ -18,7 +18,7 @@ public class DataOperationResultException extends SysException {
@java.io.Serial
private static final long serialVersionUID = -9220765735990318186L;
public static final String ERROR_CODE = "4110200";
public static final int ERROR_CODE = 4110200;
public DataOperationResultException() {
super(ERROR_CODE, "数据操作结果不符合预期");

View File

@ -1,34 +1,34 @@
package xyz.zhouxy.plusone.exception;
import xyz.zhouxy.plusone.commons.exception.BaseRuntimeException;
import xyz.zhouxy.plusone.commons.exception.BaseException;
public class SysException extends BaseRuntimeException {
public class SysException extends BaseException {
@java.io.Serial
private static final long serialVersionUID = 8821240827443168118L;
public static final String DEFAULT_ERROR_CODE = "5000000";
public static final int DEFAULT_ERROR_CODE = 5000000;
public SysException(String code, String msg) {
public SysException(int code, String msg) {
super(code, msg);
}
public SysException(String code, Throwable cause) {
public SysException(int code, Throwable cause) {
super(code, cause);
}
public SysException(String code, String msg, Throwable cause) {
public SysException(int code, String msg, Throwable cause) {
super(code, msg, cause);
}
public static SysException of(String msg) {
return new SysException(DEFAULT_ERROR_CODE, msg);
public SysException(String msg) {
super(DEFAULT_ERROR_CODE, msg);
}
public static SysException of(Throwable cause) {
return new SysException(DEFAULT_ERROR_CODE, cause);
public SysException(Throwable cause) {
super(DEFAULT_ERROR_CODE, cause);
}
public static SysException of(String msg, Throwable cause) {
return new SysException(DEFAULT_ERROR_CODE, msg, cause);
public SysException(String msg, Throwable cause) {
super(DEFAULT_ERROR_CODE, msg, cause);
}
}

View File

@ -14,28 +14,28 @@ public class UserOperationException extends BizException {
@java.io.Serial
private static final long serialVersionUID = 4371055414421991940L;
public static final String DEFAULT_ERROR_CODE = "4040600";
public static final int DEFAULT_ERROR_CODE = 4040600;
public UserOperationException(String code, String msg) {
public UserOperationException(String msg) {
super(DEFAULT_ERROR_CODE, msg);
}
public UserOperationException(String msg, Throwable cause) {
super(DEFAULT_ERROR_CODE, msg, cause);
}
public UserOperationException(int code, String msg) {
super(code, msg);
}
public UserOperationException(String code, Throwable cause) {
public UserOperationException(int code, Throwable cause) {
super(code, cause);
}
public UserOperationException(String code, String msg, Throwable cause) {
public UserOperationException(int code, String msg, Throwable cause) {
super(code, msg, cause);
}
public static UserOperationException of(String msg) {
return new UserOperationException(DEFAULT_ERROR_CODE, msg);
}
public static UserOperationException of(String msg, Throwable cause) {
return new UserOperationException(DEFAULT_ERROR_CODE, msg, cause);
}
/**
*
*
@ -52,7 +52,7 @@ public class UserOperationException extends BizException {
* @return
*/
public static UserOperationException invalidOperation(String msg) {
return new UserOperationException("4040604", msg);
return new UserOperationException(4040604, msg);
}
}

View File

@ -1,5 +1,9 @@
package xyz.zhouxy.plusone.util;
import java.util.Objects;
import java.util.regex.Pattern;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -23,4 +27,17 @@ public class PlusoneStrUtil {
return StringUtils.hasLength(value) ? value : EMPTY_STR;
}
public static String checkString(String value, String regex, String message) {
Assert.notNull(value, message);
Assert.isTrue(Pattern.matches(regex, value), message);
return value;
}
public static String checkStringNullable(String value, String regex, String message) {
return Objects.nonNull(value) ? checkString(value, regex, message) : null;
}
public static String checkStringOrDefault(String value, String regex, String message) {
return StringUtils.hasText(value) ? checkString(value, regex, message) : "";
}
}

View File

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

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>xyz.zhouxy</groupId>

View File

@ -21,7 +21,8 @@ public final class EntityStatus extends Enumeration<EntityStatus> {
public static final EntityStatus AVAILABLE = new EntityStatus(0, "正常");
public static final EntityStatus DISABLED = new EntityStatus(1, "禁用");
private static final ValueSet<EntityStatus> VALUE_SET = ValueSet.of(AVAILABLE, DISABLED);
private static final ValueSet<EntityStatus> VALUE_SET = new ValueSet<>(
AVAILABLE, DISABLED);
public static EntityStatus of(int id) {
return VALUE_SET.get(id);

View File

@ -17,8 +17,8 @@ import lombok.Getter;
*/
@Getter
public abstract class DomainEvent {
private final String identifier;
private final long happenedAt;
private String identifier;
private long happenedAt;
protected DomainEvent() {
this.identifier = UUID.randomUUID().toString();

View File

@ -5,8 +5,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import xyz.zhouxy.plusone.commons.annotation.Overridable;
/**
*
*
@ -28,29 +26,7 @@ public abstract class Entity<ID extends Serializable> {
public abstract Optional<ID> getId();
protected final void addDomainEvent(DomainEvent domainEvent) {
protected void addDomainEvent(DomainEvent domainEvent) {
domainEvents.add(domainEvent);
}
public final List<DomainEvent> getDomainEvents() {
return List.copyOf(domainEvents);
}
@Override
@Overridable
public boolean equals(Object obj) {
return super.equals(obj);
}
@Override
@Overridable
public int hashCode() {
return super.hashCode();
}
@Override
@Overridable
public String toString() {
return super.toString();
}
}

View File

@ -1,8 +0,0 @@
package xyz.zhouxy.plusone.domain;
public interface IDomainEventPublisher {
void publish(DomainEvent domainEvent);
<T extends DomainEvent> void subsrcibe(IDomainEventSubscriber<T> subscriber);
}

View File

@ -1,11 +0,0 @@
package xyz.zhouxy.plusone.domain;
/**
*
*/
public interface IDomainEventSubscriber<T extends DomainEvent> {
void handleEvent(final T event);
Class<T> subscribedToEventType();
}

View File

@ -0,0 +1,41 @@
package xyz.zhouxy.plusone.domain;
import java.util.Optional;
import java.util.regex.Pattern;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonValue;
/**
*
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public abstract class ValidatableStringRecord implements IValueObject {
protected String value;
protected final Pattern format;
protected ValidatableStringRecord(Pattern format) {
this.format = format;
}
@JsonIgnore
protected boolean isValid() {
return format.matcher(value).matches();
}
@JsonValue
public String value() {
return value;
}
@Override
public String toString() {
return value;
}
public static String getValueOrNull(Optional<? extends ValidatableStringRecord> s) {
return s.isPresent() ? s.get().value() : null;
}
}

View File

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>xyz.zhouxy</groupId>

View File

@ -1,12 +1,8 @@
package xyz.zhouxy.plusone.jdbc;
import org.springframework.jdbc.core.namedparam.BeanPropertySqlParameterSource;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.lang.Nullable;
import xyz.zhouxy.plusone.commons.base.IWithCode;
import xyz.zhouxy.plusone.commons.base.IWithIntCode;
/**
* {@link BeanPropertySqlParameterSource} POJO
* {@link org.springframework.jdbc.core.namedparam.SqlParameterSource}
@ -21,23 +17,17 @@ import xyz.zhouxy.plusone.commons.base.IWithIntCode;
*/
public class BeanPropertyParamSource extends BeanPropertySqlParameterSource {
public BeanPropertyParamSource(Object object) {
super(object);
}
public BeanPropertyParamSource(Object object) {
super(object);
}
@Override
@Nullable
public Object getValue(String paramName) throws IllegalArgumentException {
Object value = super.getValue(paramName);
if (value instanceof Enum<?> e) {
if (value instanceof IWithCode<?> c) {
return c.getCode();
}
if (value instanceof IWithIntCode c) {
return c.getCode();
}
return e.ordinal();
}
return value;
}
@Override
@Nullable
public Object getValue(String paramName) throws IllegalArgumentException {
Object value = super.getValue(paramName);
if (value instanceof Enum) {
return ((Enum<?>) value).ordinal();
}
return value;
}
}

View File

@ -63,12 +63,10 @@ public abstract class JdbcEntityDaoSupport<T extends Entity<ID>, ID extends Seri
protected abstract T mapRow(ResultSet rs) throws SQLException;
@Deprecated
protected void setRowMapper(@Nonnull RowMapper<T> rowMapper) {
this.rowMapper = rowMapper;
}
@Deprecated
protected void setResultSetExtractor(@Nonnull ResultSetExtractor<Optional<T>> resultSetExtractor) {
this.resultSetExtractor = resultSetExtractor;
}

View File

@ -7,7 +7,8 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import xyz.zhouxy.plusone.spring.SpringContextHolder;
/**
* Spring {@link JdbcTemplate}
* Spring
* Spring {@link JdbcTemplate}
* {@link NamedParameterJdbcTemplate}
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
@ -16,19 +17,17 @@ import xyz.zhouxy.plusone.spring.SpringContextHolder;
*/
public final class JdbcFactory {
private static final ApplicationContext SPRING_APPLICATION_CONTEXT = SpringContextHolder.getContext();
private static final JdbcTemplate JDBC_TEMPLATE = SPRING_APPLICATION_CONTEXT.getBean(JdbcTemplate.class);
private static final NamedParameterJdbcTemplate NAMED_PARAMETER_JDBC_TEMPLATE = SPRING_APPLICATION_CONTEXT.getBean(NamedParameterJdbcTemplate.class);
private static final ApplicationContext CONTEXT = SpringContextHolder.getContext();
private JdbcFactory() {
throw new IllegalStateException("Utility class");
}
public static JdbcTemplate getJdbcTemplate() {
return JDBC_TEMPLATE;
return CONTEXT.getBean(JdbcTemplate.class);
}
public static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
return NAMED_PARAMETER_JDBC_TEMPLATE;
return CONTEXT.getBean(NamedParameterJdbcTemplate.class);
}
}

View File

@ -8,9 +8,6 @@ import javax.annotation.Nonnull;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import com.google.common.base.Preconditions;
import xyz.zhouxy.plusone.commons.annotation.Overridable;
import xyz.zhouxy.plusone.domain.AggregateRoot;
import xyz.zhouxy.plusone.domain.IRepository;
@ -22,33 +19,35 @@ public abstract class JdbcRepositorySupport<T extends AggregateRoot<ID>, ID exte
super(namedParameterJdbcTemplate);
}
@Overridable
protected abstract void doDelete(@Nonnull T entity);
@Overridable
protected abstract Optional<T> doFindById(@Nonnull ID id);
@Overridable
protected abstract T doInsert(@Nonnull T entity);
@Overridable
protected abstract T doUpdate(@Nonnull T entity);
@Override
public final void delete(T entity) {
Preconditions.checkArgument(entity != null, "Cannot delete null.");
if (entity == null) {
throw new IllegalArgumentException("Cannot delete null.");
}
doDelete(entity);
}
@Override
public final Optional<T> find(ID id) {
Preconditions.checkArgument(id != null, "Id cannot be null.");
if (id == null) {
throw new IllegalArgumentException("Id cannot be null.");
}
return doFindById(id);
}
@Override
public final T save(T entity) {
Preconditions.checkArgument(entity != null, "Cannot save null.");
if (entity == null) {
throw new IllegalArgumentException("Cannot save null.");
}
return entity.getId().isPresent() ? doUpdate(entity) : doInsert(entity);
}

View File

@ -16,7 +16,7 @@ import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.util.CollectionUtils;
import xyz.zhouxy.plusone.commons.util.Numbers;
import xyz.zhouxy.plusone.commons.util.NumberUtil;
import xyz.zhouxy.plusone.exception.DataOperationResultException;
public abstract class PlusoneJdbcDaoSupport {
@ -88,64 +88,64 @@ public abstract class PlusoneJdbcDaoSupport {
protected final long batchUpdate(String sql, SqlParameterSource[] batchArgs) {
int[] i = this.jdbc.batchUpdate(sql, batchArgs);
return Numbers.sum(i);
return NumberUtil.sum(i);
}
protected final <T> long batchUpdate(String sql, Stream<T> c,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder));
return Numbers.sum(i);
return NumberUtil.sum(i);
}
protected final <T> long batchUpdate(String sql, Collection<T> c,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder));
return Numbers.sum(i);
return NumberUtil.sum(i);
}
protected static <T> void assertResultEquals(T result, T expectedValue) {
protected static final <T> void assertResultEquals(T result, T expectedValue) {
if (!Objects.equals(result, expectedValue)) {
throw new DataOperationResultException();
}
}
protected static <T> void assertResultEquals(T result, T expectedValue, Function<T, String> errMsg) {
protected static final <T> void assertResultEquals(T result, T expectedValue, Function<T, String> errMsg) {
if (!Objects.equals(result, expectedValue)) {
throw new DataOperationResultException(errMsg.apply(result));
}
}
protected static <T> void assertResultEquals(T result, T expectedValue, String msgTemplate, Object... args) {
protected static final <T> void assertResultEquals(T result, T expectedValue, String msgTemplate, Object... args) {
if (!Objects.equals(result, expectedValue)) {
throw new DataOperationResultException(String.format(msgTemplate, args));
}
}
protected static <T, E extends Throwable> void assertResultEqualsOrThrow(T result, T expectedValue,
protected static final <T, E extends Throwable> void assertResultEqualsOrThrow(T result, T expectedValue,
Function<T, E> e) throws E {
if (!Objects.equals(result, expectedValue)) {
throw e.apply(result);
}
}
protected static void assertUpdateOneRow(int result) {
protected static final void assertUpdateOneRow(int result) {
assertResultEquals(result, 1);
}
protected static void assertUpdateOneRow(int result, Function<Integer, String> errMsg) {
protected static final void assertUpdateOneRow(int result, Function<Integer, String> errMsg) {
assertResultEquals(result, 1, errMsg);
}
protected static void assertUpdateOneRow(int result, String msgTemplate, Object... args) {
protected static final void assertUpdateOneRow(int result, String msgTemplate, Object... args) {
assertResultEquals(result, 1, msgTemplate, args);
}
protected static <E extends Throwable> void assertUpdateOneRowOrThrow(int result, Function<Integer, E> e)
protected static final <E extends Throwable> void assertUpdateOneRowOrThrow(int result, Function<Integer, E> e)
throws E {
assertResultEqualsOrThrow(result, 1, e);
}
protected static <T> SqlParameterSource[] buildSqlParameterSourceArray(
protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray(
T[] c,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
if (c == null || c.length == 0) {
@ -154,7 +154,7 @@ public abstract class PlusoneJdbcDaoSupport {
return buildSqlParameterSourceArray(Arrays.stream(c), paramSourceBuilder);
}
protected static <T> SqlParameterSource[] buildSqlParameterSourceArray(
protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray(
Collection<T> c,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
if (CollectionUtils.isEmpty(c)) {
@ -163,7 +163,7 @@ public abstract class PlusoneJdbcDaoSupport {
return buildSqlParameterSourceArray(c.stream(), paramSourceBuilder);
}
protected static <T> SqlParameterSource[] buildSqlParameterSourceArray(
protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray(
Stream<T> stream,
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
Objects.requireNonNull(stream);

View File

@ -8,7 +8,7 @@ import java.sql.SQLException;
*
* <p>
* {@link #map(ResultSet)} {@link ResultSet}
* {@link #rowMapper(ResultSet, int)}
* {@link #rowMapper(ResultSet, int)}
* {@link org.springframework.jdbc.core.RowMapper}
* {@link org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate}
*

View File

@ -1,17 +1,8 @@
package xyz.zhouxy.plusone.oss;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
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.NameValuePair;
@ -23,11 +14,7 @@ import org.csource.fastdfs.TrackerServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.io.Files;
import lombok.Getter;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.exception.SysException;
public class FastDFSUtil {
@ -57,7 +44,7 @@ public class FastDFSUtil {
* @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];
metaList[0] = new NameValuePair("author", file.getAuthor());
@ -76,7 +63,7 @@ public class FastDFSUtil {
uploadResults[0], uploadResults[1], System.currentTimeMillis() - startTime);
} 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) {
throw new FastDFSException(e);
}
@ -122,72 +109,18 @@ public class FastDFSUtil {
}
}
@Getter
public static final class FastDFSFile {
@Getter
private final String fileName;
private final byte[] content;
@Getter
private final String ext;
@Getter
private final String md5;
@Getter
private final String author;
private String name;
private byte[] content;
private String ext;
private String md5;
private String author;
private FastDFSFile(@Nonnull File file, @Nullable String author) throws IOException {
this.fileName = file.getName();
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;
public FastDFSFile(String name, byte[] content, String ext) {
this.name = name;
this.content = content;
this.ext = Files.getFileExtension(fileName);
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 SysException.of(e);
}
this.ext = ext;
}
}
}

View File

@ -1,7 +1,5 @@
package xyz.zhouxy.plusone.sms;
import org.springframework.stereotype.Service;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
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.SendSmsResponse;
import org.springframework.stereotype.Service;
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.SmsHttpProperties;
import xyz.zhouxy.plusone.sms.SmsProperties.SmsProxyProperties;
@ -68,7 +69,7 @@ public class TencentSmsServiceImpl implements SmsService {
} catch (TencentCloudSDKException e) {
log.error(e.getMessage(), e);
throw SysException.of(e);
throw new BizException(ErrorCodeConsts.DEFAULT_ERROR_CODE, e);
}
}

View File

@ -4,13 +4,15 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
public enum SpringContextHolder {
INSTANCE
;
public class SpringContextHolder {
private ApplicationContext context;
private static final SpringContextHolder INSTANCE = new SpringContextHolder();
private SpringContextHolder() {
}
public static ApplicationContext getContext() {
return INSTANCE.context;
}

View File

@ -12,7 +12,6 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebCorsConfig implements WebMvcConfigurer {
// TODO 不放行全部,通过配置文件配置允许访问的域名
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")

View File

@ -36,7 +36,7 @@ class LoginCommandValidator extends BaseValidator<LoginCommand> {
private LoginCommandValidator() {
ruleForString(LoginCommand::getAccount)
.notNull("邮箱地址不能为空")
.matchesOne(new Pattern[] { PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE },
.matchesOr(new Pattern[] { PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE },
value -> new RuntimeException('"' + value + "\" 不是邮箱地址或手机号"));
ruleForString(LoginCommand::getPwd)
.notNull("密码不能为空")

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone</artifactId>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone</artifactId>

View File

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

View File

@ -1,33 +0,0 @@
package xyz.zhouxy.plusone;
import java.util.Collections;
import java.util.List;
import javax.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.system.application.query.AccountQueries;
import xyz.zhouxy.plusone.system.application.query.params.AccountQueryParams;
import xyz.zhouxy.plusone.system.application.query.result.AccountOverview;
@Slf4j
@SpringBootTest(classes = PlusoneApplication.class)
class AccountQueriesTests {
@Resource
AccountQueries accountQueries;
@Test
void testQueryPage() {
AccountQueryParams queryParams = new AccountQueryParams();
// queryParams.setOrderBy(List.of("email", "mobile_phone", "id"));
queryParams.setSize(20);
queryParams.setPageNum(1L);
queryParams.setOrderBy(Collections.emptyList());
List<AccountOverview> l = accountQueries.queryAccountOverview(queryParams);
log.info("l: {}", l);
}
}

View File

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

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone-system</artifactId>

View File

@ -11,7 +11,7 @@ public class UnsupportedPrincipalTypeException extends BizException {
private static final long serialVersionUID = 5207757290868470762L;
public static final String ERR_CODE = "4040201";
public static final int ERR_CODE = 4040201;
private static final String DEFAULT_ERROR_MSG = "不支持的 PrincipalType";
public UnsupportedPrincipalTypeException() {

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 BizException.of(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

@ -0,0 +1,61 @@
package xyz.zhouxy.plusone.system.application.common.util;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import xyz.zhouxy.plusone.domain.IWithOrderNumber;
import xyz.zhouxy.plusone.system.application.query.result.MenuViewObject;
import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType;
/**
*
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public class MenuUtil {
private MenuUtil() {
throw new IllegalStateException("Utility class");
}
/**
*
*
* @param allMenus
* @return
*/
public static List<MenuViewObject> buildMenuTree(Collection<MenuViewObject> allMenus) {
// 先排序,保证添加到 rootMenus 中的顺序,以及 addChild 添加的子菜单的顺序
allMenus = allMenus.stream()
.sorted(Comparator.comparing(IWithOrderNumber::getOrderNumber))
.toList();
// 一级菜单
List<MenuViewObject> rootMenus = new ArrayList<>();
// key: 菜单 id; value: 菜单对象. 方便根据 id 查找相应对象。
Map<Long, MenuViewObject> menuListMap = new HashMap<>();
for (var menu : allMenus) {
// 添加 MENU_LIST 到 map 中,方便后面调用对象的方法
if (menu.getType() == MenuType.MENU_LIST.ordinal()) {
menuListMap.put(menu.getId(), menu);
}
// 一级菜单
if (menu.getParentId() == 0) {
rootMenus.add(menu);
}
}
for (var menu : allMenus) {
var parent = menuListMap.getOrDefault(menu.getParentId(), null);
// 父菜单存在于 map 中,调用父菜单的 addChild 方法将当前菜单添加为父菜单的子菜单。
if (parent != null) {
parent.addChild(menu);
}
}
return rootMenus;
}
}

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;
@ -7,7 +7,7 @@ import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
import xyz.zhouxy.plusone.system.application.service.AccountContextService;
import xyz.zhouxy.plusone.system.application.service.command.ChangePasswordCommand;
import xyz.zhouxy.plusone.system.application.service.command.ChangePasswordWithoutLoginCommand;
@ -28,34 +28,34 @@ public class AccountContextController {
}
@GetMapping("info")
public UnifiedResponse getAccountInfo() {
public RestfulResult getAccountInfo() {
adminAuthLogic.checkLogin();
var result = service.getAccountInfo();
return UnifiedResponse.success("查询成功", result);
return RestfulResult.success("查询成功", result);
}
@GetMapping("logout")
public UnifiedResponse logout() {
public RestfulResult logout() {
service.logout();
return UnifiedResponse.success("注销成功");
return RestfulResult.success("注销成功");
}
@GetMapping("menus")
public UnifiedResponse getMenuTree() {
public RestfulResult getMenuTree() {
adminAuthLogic.checkLogin();
var result = service.getMenuTree();
return UnifiedResponse.success("查询成功", result);
return RestfulResult.success("查询成功", result);
}
@PostMapping("changePassword")
public UnifiedResponse changePassword(ChangePasswordCommand command) {
public RestfulResult changePassword(ChangePasswordCommand command) {
service.changePassword(command);
return UnifiedResponse.success("修改成功,请重新登录。");
return RestfulResult.success("修改成功,请重新登录。");
}
@PostMapping("changePasswordWithoutLogin")
public UnifiedResponse changePasswordWithoutLogin(ChangePasswordWithoutLoginCommand command) {
public RestfulResult changePasswordWithoutLogin(ChangePasswordWithoutLoginCommand command) {
service.changePasswordWithoutLogin(command);
return UnifiedResponse.success("修改成功,请重新登录。");
return RestfulResult.success("修改成功,请重新登录。");
}
}

View File

@ -1,7 +1,7 @@
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.commons.util.UnifiedResponse.success;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;
import java.util.List;
@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
import xyz.zhouxy.plusone.system.application.query.params.AccountQueryParams;
import xyz.zhouxy.plusone.system.application.service.AccountManagementService;
import xyz.zhouxy.plusone.system.application.service.command.CreateAccountCommand;
@ -38,7 +38,7 @@ public class AccountManagementController {
}
@PostMapping
public UnifiedResponse createAccount(@RequestBody @Valid CreateAccountCommand command) {
public RestfulResult createAccount(@RequestBody @Valid CreateAccountCommand command) {
adminAuthLogic.checkLogin();
adminAuthLogic.checkPermission("sys-account-create");
service.createAccount(command);
@ -46,7 +46,7 @@ public class AccountManagementController {
}
@DeleteMapping
public UnifiedResponse deleteAccounts(@RequestBody List<Long> ids) {
public RestfulResult deleteAccounts(@RequestBody List<Long> ids) {
adminAuthLogic.checkLogin();
adminAuthLogic.checkPermission("sys-account-delete");
service.deleteAccounts(ids);
@ -54,7 +54,7 @@ public class AccountManagementController {
}
@PatchMapping("{id}")
public UnifiedResponse updateAccountInfo(
public RestfulResult updateAccountInfo(
@PathVariable("id") Long id,
@RequestBody @Valid UpdateAccountCommand command) {
adminAuthLogic.checkLogin();
@ -64,7 +64,7 @@ public class AccountManagementController {
}
@GetMapping("query")
public UnifiedResponse queryAccountOverviewList(AccountQueryParams queryParams) {
public RestfulResult queryAccountOverviewList(AccountQueryParams queryParams) {
adminAuthLogic.checkLogin();
adminAuthLogic.checkPermission("sys-account-list");
var accountOverviewList = service.queryAccountOverviewList(queryParams);
@ -72,7 +72,7 @@ public class AccountManagementController {
}
@GetMapping("{accountId}")
public UnifiedResponse queryAccountDetails(@PathVariable("accountId") Long accountId) {
public RestfulResult queryAccountDetails(@PathVariable("accountId") Long accountId) {
adminAuthLogic.checkLogin();
adminAuthLogic.checkPermission("sys-account-details");
var accountDetails = service.queryAccountDetails(accountId);

View File

@ -1,6 +1,6 @@
package xyz.zhouxy.plusone.system.application.web.controller;
package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.commons.util.UnifiedResponse.success;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -12,7 +12,7 @@ import org.springframework.web.bind.annotation.RestController;
import xyz.zhouxy.plusone.system.application.service.AdminLoginService;
import xyz.zhouxy.plusone.system.application.service.command.LoginByOtpCommand;
import xyz.zhouxy.plusone.system.application.service.command.LoginByPasswordCommand;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
/**
* Admin
@ -30,19 +30,19 @@ public class AdminLoginController {
}
@PostMapping("byPassword")
public UnifiedResponse loginByPassword(@RequestBody LoginByPasswordCommand command) {
public RestfulResult loginByPassword(@RequestBody LoginByPasswordCommand command) {
var loginInfo = service.loginByPassword(command);
return success("登录成功", loginInfo);
}
@PostMapping("byOtp")
public UnifiedResponse loginByOtp(@RequestBody LoginByOtpCommand command) {
public RestfulResult loginByOtp(@RequestBody LoginByOtpCommand command) {
var loginInfo = service.loginByOtp(command);
return success("登录成功", loginInfo);
}
@GetMapping("sendOtp")
public UnifiedResponse sendOtp(@RequestParam String principal) {
public RestfulResult sendOtp(@RequestParam String principal) {
service.sendOtp(principal);
return success("发送成功");
}

View File

@ -1,7 +1,7 @@
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.commons.util.UnifiedResponse.success;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;
import java.util.List;
@ -20,7 +20,7 @@ import xyz.zhouxy.plusone.system.application.query.params.DictQueryParams;
import xyz.zhouxy.plusone.system.application.service.DictManagementService;
import xyz.zhouxy.plusone.system.application.service.command.CreateDictCommand;
import xyz.zhouxy.plusone.system.application.service.command.UpdateDictCommand;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
/**
*
@ -38,21 +38,21 @@ public class DictManagementController {
}
@PostMapping
public UnifiedResponse createDict(@RequestBody @Valid CreateDictCommand command) {
public RestfulResult createDict(@RequestBody @Valid CreateDictCommand command) {
adminAuthLogic.checkPermission("sys-dict-create");
service.createDict(command);
return success();
}
@DeleteMapping
public UnifiedResponse deleteDicts(@RequestBody List<Long> ids) {
public RestfulResult deleteDicts(@RequestBody List<Long> ids) {
adminAuthLogic.checkPermission("sys-dict-delete");
service.deleteDicts(ids);
return success();
}
@PatchMapping("{id}")
public UnifiedResponse updateDict(
public RestfulResult updateDict(
@PathVariable("id") Long id,
@RequestBody @Valid UpdateDictCommand command) {
adminAuthLogic.checkPermission("sys-dict-update");
@ -61,21 +61,21 @@ public class DictManagementController {
}
@GetMapping("{dictId}")
public UnifiedResponse findDictDetails(@PathVariable("dictId") Long dictId) {
public RestfulResult findDictDetails(@PathVariable("dictId") Long dictId) {
adminAuthLogic.checkPermission("sys-dict-details");
var dictDetails = service.findDictDetails(dictId);
return success("查询成功", dictDetails);
}
@GetMapping("all")
public UnifiedResponse loadAllDicts() {
public RestfulResult loadAllDicts() {
adminAuthLogic.checkPermissionAnd("sys-dict-list", "sys-dict-details");
var dicts = service.loadAllDicts();
return success("查询成功", dicts);
}
@GetMapping("query")
public UnifiedResponse queryDictOverviewList(@Valid DictQueryParams queryParams) {
public RestfulResult queryDictOverviewList(@Valid DictQueryParams queryParams) {
adminAuthLogic.checkPermission("sys-dict-list");
var dicts = service.queryDictOverviewList(queryParams);
return success("查询成功", dicts);

View File

@ -1,7 +1,7 @@
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.commons.util.UnifiedResponse.success;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;
import javax.validation.Valid;
@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
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.UpdateMenuCommand;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
/**
*
@ -37,7 +37,7 @@ public class MenuManagementController {
// ==================== create ====================
@PostMapping
public UnifiedResponse createMenu(@RequestBody @Valid CreateMenuCommand command) {
public RestfulResult createMenu(@RequestBody @Valid CreateMenuCommand command) {
adminAuthLogic.checkPermission("sys-menu-create");
service.createMenu(command);
return success();
@ -45,7 +45,7 @@ public class MenuManagementController {
// ==================== delete ====================
@DeleteMapping("{id}")
public UnifiedResponse deleteMenu(@PathVariable("id") Long id) {
public RestfulResult deleteMenu(@PathVariable("id") Long id) {
adminAuthLogic.checkPermission("sys-menu-delete");
service.deleteMenu(id);
return success();
@ -53,7 +53,7 @@ public class MenuManagementController {
// ==================== update ====================
@PatchMapping("{id}")
public UnifiedResponse updateMenu(
public RestfulResult updateMenu(
@PathVariable("id") Long id,
@RequestBody @Valid UpdateMenuCommand command) {
adminAuthLogic.checkPermission("sys-menu-update");
@ -63,21 +63,21 @@ public class MenuManagementController {
// ==================== query ====================
@GetMapping("{id}")
public UnifiedResponse findById(@PathVariable("id") Long id) {
public RestfulResult findById(@PathVariable("id") Long id) {
adminAuthLogic.checkPermission("sys-menu-details");
var result = service.findById(id);
return UnifiedResponse.success("查询成功", result);
return RestfulResult.success("查询成功", result);
}
@GetMapping("queryByAccountId")
public UnifiedResponse queryByAccountId(@RequestParam Long accountId) {
public RestfulResult queryByAccountId(@RequestParam Long accountId) {
adminAuthLogic.checkPermission("sys-menu-details");
var result = service.queryByAccountId(accountId);
return success("查询成功", result);
}
@GetMapping("queryByRoleId")
public UnifiedResponse queryByRoleId(@RequestParam Long roleId) {
public RestfulResult queryByRoleId(@RequestParam Long roleId) {
adminAuthLogic.checkPermission("sys-menu-details");
var result = service.queryByRoleId(roleId);
return success("查询成功", result);

View File

@ -1,6 +1,6 @@
package xyz.zhouxy.plusone.system.application.web.controller;
package xyz.zhouxy.plusone.system.application.controller;
import static xyz.zhouxy.plusone.commons.util.UnifiedResponse.success;
import static xyz.zhouxy.plusone.commons.util.RestfulResult.success;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.RestController;
import xyz.zhouxy.plusone.system.application.service.RegisterAccountService;
import xyz.zhouxy.plusone.system.application.service.command.RegisterAccountCommand;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
/**
*
@ -29,13 +29,13 @@ public class RegisterAccountController {
}
@PostMapping
public UnifiedResponse registerAccount(@RequestBody RegisterAccountCommand command) {
public RestfulResult registerAccount(@RequestBody RegisterAccountCommand command) {
service.registerAccount(command);
return success("注册成功");
}
@GetMapping("sendCode")
public UnifiedResponse sendCode(@RequestParam String principal) {
public RestfulResult sendCode(@RequestParam String principal) {
service.sendCode(principal);
return 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 static xyz.zhouxy.plusone.system.constant.AuthLogic.adminAuthLogic;
@ -17,7 +17,7 @@ import xyz.zhouxy.plusone.system.application.query.params.RoleQueryParams;
import xyz.zhouxy.plusone.system.application.service.RoleManagementService;
import xyz.zhouxy.plusone.system.application.service.command.CreateRoleCommand;
import xyz.zhouxy.plusone.system.application.service.command.UpdateRoleCommand;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.util.RestfulResult;
/**
*
@ -35,44 +35,44 @@ public class RoleManagementController {
}
@PostMapping
public UnifiedResponse createRole(@RequestBody @Valid CreateRoleCommand command) {
public RestfulResult createRole(@RequestBody @Valid CreateRoleCommand command) {
adminAuthLogic.checkPermission("sys-role-create");
service.createRole(command);
return UnifiedResponse.success();
return RestfulResult.success();
}
@PatchMapping
public UnifiedResponse updateRole(@RequestBody @Valid UpdateRoleCommand command) {
public RestfulResult updateRole(@RequestBody @Valid UpdateRoleCommand command) {
adminAuthLogic.checkPermission("sys-role-update");
service.updateRole(command);
return UnifiedResponse.success();
return RestfulResult.success();
}
@DeleteMapping("{id}")
public UnifiedResponse delete(@PathVariable("id") Long id) {
public RestfulResult delete(@PathVariable("id") Long id) {
adminAuthLogic.checkPermission("sys-role-delete");
service.delete(id);
return UnifiedResponse.success();
return RestfulResult.success();
}
@GetMapping("exists")
public UnifiedResponse exists(@RequestParam("id") Long id) {
public RestfulResult exists(@RequestParam("id") Long id) {
adminAuthLogic.checkPermissionOr("sys-role-list", "sys-role-details");
var isExists = service.exists(id);
return UnifiedResponse.success(isExists ? "存在" : "不存在", isExists);
return RestfulResult.success(isExists ? "存在" : "不存在", isExists);
}
@GetMapping("{id}")
public UnifiedResponse findById(@PathVariable("id") Long id) {
public RestfulResult findById(@PathVariable("id") Long id) {
adminAuthLogic.checkPermission("sys-role-details");
var result = service.findById(id);
return UnifiedResponse.success("查询成功", result);
return RestfulResult.success("查询成功", result);
}
@GetMapping("query")
public UnifiedResponse query(RoleQueryParams params) {
public RestfulResult query(RoleQueryParams params) {
adminAuthLogic.checkPermission("sys-role-list");
var result = service.query(params);
return UnifiedResponse.success("查询成功", result);
return RestfulResult.success("查询成功", result);
}
}

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.web.bind.annotation.ResponseStatus;
@ -10,13 +10,13 @@ public class AccountLoginException extends BizException {
@java.io.Serial
private static final long serialVersionUID = -3040996790739138556L;
private static final String DEFAULT_ERR_CODE = "4030000";
private static final int DEFAULT_ERR_CODE = 4030000;
private AccountLoginException() {
super(DEFAULT_ERR_CODE, "用户登录异常");
}
private AccountLoginException(String code, String message) {
private AccountLoginException(int code, String message) {
super(code, message);
}
@ -25,7 +25,7 @@ public class AccountLoginException extends BizException {
}
public static AccountLoginException accountNotExistException(String msg) {
return new AccountLoginException("4030101", msg);
return new AccountLoginException(4030101, msg);
}
public static AccountLoginException otpErrorException() {
@ -33,7 +33,7 @@ public class AccountLoginException extends BizException {
}
public static AccountLoginException otpErrorException(String msg) {
return new AccountLoginException("4030501", msg);
return new AccountLoginException(4030501, msg);
}
public static AccountLoginException otpNotExistsException() {
@ -41,7 +41,7 @@ public class AccountLoginException extends BizException {
}
public static AccountLoginException otpNotExistsException(String msg) {
return new AccountLoginException("4030502", msg);
return new AccountLoginException(4030502, msg);
}
public static AccountLoginException passwordErrorException() {
@ -49,6 +49,6 @@ public class AccountLoginException extends BizException {
}
public static AccountLoginException passwordErrorException(String msg) {
return new AccountLoginException("4030200", msg);
return new AccountLoginException(4030200, msg);
}
}

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.web.bind.annotation.ResponseStatus;
@ -12,46 +12,46 @@ public class AccountRegisterException extends BizException {
private static final long serialVersionUID = 7580245181633370195L;
public AccountRegisterException() {
this("4020000", "用户注册错误");
this(4020000, "用户注册错误");
}
public AccountRegisterException(String message) {
this("4020000", message);
this(4020000, message);
}
public AccountRegisterException(Throwable cause) {
super("4020000", cause);
super(4020000, cause);
}
public AccountRegisterException(String code, String message) {
public AccountRegisterException(int code, String message) {
super(code, message);
}
public AccountRegisterException(String code, Throwable cause) {
public AccountRegisterException(int code, Throwable cause) {
super(code, cause);
}
public static AccountRegisterException emailOrMobilePhoneRequiredException() {
return new AccountRegisterException("4020300", "邮箱和手机号应至少绑定一个");
return new AccountRegisterException(4020300, "邮箱和手机号应至少绑定一个");
}
public static AccountRegisterException usernameAlreadyExists(String username) {
return new AccountRegisterException("4020400", String.format("用户名 %s 已存在", username));
return new AccountRegisterException(4020400, String.format("用户名 %s 已存在", username));
}
public static AccountRegisterException emailAlreadyExists(String value) {
return new AccountRegisterException("4020500", String.format("邮箱 %s 已存在", value));
return new AccountRegisterException(4020500, String.format("邮箱 %s 已存在", value));
}
public static AccountRegisterException mobilePhoneAlreadyExists(String value) {
return new AccountRegisterException("4020600", String.format("手机号 %s 已存在", value));
return new AccountRegisterException(4020600, String.format("手机号 %s 已存在", value));
}
public static AccountRegisterException codeErrorException() {
return new AccountRegisterException("4020701", "校验码错误");
return new AccountRegisterException(4020701, "校验码错误");
}
public static AccountRegisterException codeNotExistsException() {
return new AccountRegisterException("4020702", "校验码不存在或已过期");
return new AccountRegisterException(4020702, "校验码不存在或已过期");
}
}

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;
@ -7,13 +7,11 @@ public class UnsupportedMenuTypeException extends InvalidInputException {
@java.io.Serial
private static final long serialVersionUID = -769169844015637730L;
public static final String ERROR_CODE = "4040209";
public UnsupportedMenuTypeException() {
this("不支持的菜单类型");
}
public UnsupportedMenuTypeException(String message) {
super(ERROR_CODE, message);
super(message);
}
}

View File

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

View File

@ -1,4 +1,4 @@
package xyz.zhouxy.plusone.system.application.common.exception.handler;
package xyz.zhouxy.plusone.system.application.exception.handler;
import javax.annotation.Nonnull;
@ -17,7 +17,7 @@ import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.exception.SameTokenInvalidException;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.commons.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.commons.util.UnifiedResponse;
import xyz.zhouxy.plusone.commons.exception.handler.RestfulResult;
/**
* Sa-Token
@ -52,7 +52,7 @@ public class SaTokenExceptionHandler extends BaseExceptionHandler {
}
@ExceptionHandler(SaTokenException.class)
public ResponseEntity<UnifiedResponse> handleSaTokenException(SaTokenException e) {
public ResponseEntity<RestfulResult> handleSaTokenException(SaTokenException e) {
log.error(e.getMessage(), e);
return buildExceptionResponse(e);
}

View File

@ -12,7 +12,7 @@ import xyz.zhouxy.plusone.commons.util.PagingAndSortingQueryParams;
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
@ToString(callSuper = true)
@ToString
public class AccountQueryParams extends PagingAndSortingQueryParams {
public AccountQueryParams() {
@ -29,6 +29,7 @@ public class AccountQueryParams extends PagingAndSortingQueryParams {
"update_time");
}
// TODO【添加】 注解参数校验
private @Getter @Setter Long id;
private @Getter @Setter String username;
private @Getter @Setter String email;

View File

@ -2,10 +2,9 @@ package xyz.zhouxy.plusone.system.application.query.result;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonInclude;
@ -82,18 +81,18 @@ public class MenuViewObject implements IWithOrderNumber {
List<Action> actions;
// MENU_LIST
SortedSet<MenuViewObject> children;
List<MenuViewObject> children;
public void addChild(MenuViewObject child) {
if (this.children == null) {
this.children = new TreeSet<>();
this.children = new ArrayList<>();
}
this.children.add(child);
}
public void addChildren(Collection<MenuViewObject> children) {
if (this.children == null) {
this.children = new TreeSet<>();
this.children = new ArrayList<>();
}
this.children.addAll(children);
}
@ -122,33 +121,11 @@ public class MenuViewObject implements IWithOrderNumber {
}
public List<MenuViewObject> getChildren() {
return this.children == null || this.children.isEmpty()
? Collections.emptyList()
: new ArrayList<>(this.children);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MenuViewObject other = (MenuViewObject) obj;
if (id == null) {
if (other.id != null)
return false;
} else if (!id.equals(other.id))
return false;
return true;
return Objects.nonNull(this.children)
? this.children
.stream()
.sorted(Comparator.comparing(IWithOrderNumber::getOrderNumber))
.toList()
: null;
}
}

View File

@ -8,9 +8,9 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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.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.result.AccountDetails;
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.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.params.AccountQueryParams;
import xyz.zhouxy.plusone.system.application.query.result.AccountDetails;
@ -94,6 +94,7 @@ public class AccountManagementService {
Account account = accountRepository.find(id)
.orElseThrow(() -> new DataNotExistException("该账号不存在"));
account.setAccountInfo(command.getNickname(), command.getAvatar(), Sex.of(command.getSex()));
account.setUpdatedBy(adminAuthLogic.getLoginIdAsLong());
accountRepository.save(account);
}

View File

@ -6,10 +6,10 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
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.util.PrincipalType;
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.result.LoginInfoViewObject;
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 xyz.zhouxy.plusone.mail.MailService;
import xyz.zhouxy.plusone.sms.SmsService;
import xyz.zhouxy.plusone.system.application.common.exception.AccountLoginException;
import xyz.zhouxy.plusone.system.application.common.exception.AccountRegisterException;
import xyz.zhouxy.plusone.system.application.exception.AccountLoginException;
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.Email;
import xyz.zhouxy.plusone.system.domain.model.account.MobilePhone;

View File

@ -1,6 +1,7 @@
package xyz.zhouxy.plusone.system.application.service;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -12,10 +13,10 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import xyz.zhouxy.plusone.commons.util.MoreCollections;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.domain.IWithOrderNumber;
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.result.MenuViewObject;
import xyz.zhouxy.plusone.system.application.service.command.CreateMenuCommand;
import xyz.zhouxy.plusone.system.application.service.command.UpdateMenuCommand;
@ -107,7 +108,7 @@ public class MenuManagementService {
command.getIcon(),
command.getHidden(),
command.getOrderNumber(),
EntityStatus.of(command.getStatus()),
EntityStatus.of(command.getStatus()),
command.getComponent(),
command.getResource(),
command.getCache(),
@ -138,33 +139,38 @@ public class MenuManagementService {
@Transactional(propagation = Propagation.SUPPORTS)
public List<MenuViewObject> buildMenuTree(List<MenuViewObject> menus) {
// 创建并填充 Map
final Map<Long, MenuViewObject> menuMap = MoreCollections.toHashMap(menus, MenuViewObject::getId);
List<MenuViewObject> rootMenus = menus
.stream()
.filter(menu -> Objects.equals(menu.getParentId(), 0L))
.toList();
Map<Long, MenuViewObject> allMenus = new HashMap<>();
for (var item : menus) {
allMenus.put(item.getId(), item);
}
for (MenuViewObject menu : menus) {
long parentId = menu.getParentId();
if (parentId != 0L) {
while (!menuMap.containsKey(parentId)) {
MenuViewObject parent = findById(parentId);
if (parent == null) {
break;
}
menuMap.put(parent.getId(), parent);
parentId = parent.getParentId();
while (parentId != 0 && !allMenus.containsKey(parentId)) {
MenuViewObject parent = findById(parentId);
if (parent == null) {
break;
}
allMenus.put(parent.getId(), parent);
parentId = parent.getParentId();
}
}
Collection<MenuViewObject> allMenus = menuMap.values();
for (var menu : allMenus) {
var parent = menuMap.get(menu.getParentId());
for (var menu : allMenus.values()) {
var parent = allMenus.getOrDefault(menu.getParentId(), null);
if (parent != null) {
parent.addChild(menu);
}
}
return allMenus.stream()
.filter(menu -> (menu != null) && Objects.equals(menu.getParentId(), 0L))
.sorted()
return rootMenus
.stream()
.sorted(Comparator.comparing(IWithOrderNumber::getOrderNumber))
.toList();
}
}

View File

@ -5,10 +5,10 @@ import java.util.Set;
import org.springframework.stereotype.Service;
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.util.PrincipalType;
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.domain.model.account.Account;
import xyz.zhouxy.plusone.system.domain.model.account.AccountInfo;

View File

@ -16,7 +16,7 @@ public class LoginByOtpCommandValidator extends BaseValidator<LoginByOtpCommand>
ruleForString(LoginByOtpCommand::getPrincipal)
.notNull("输入邮箱地址或手机号")
.notEmpty("输入邮箱地址或手机号")
.matchesOne(List.of(PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE), "输入用户名、邮箱地址或手机号");
.matchesOr(List.of(PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE), "输入用户名、邮箱地址或手机号");
ruleForString(LoginByOtpCommand::getOtp)
.notNull("验证码不能为空")
.notEmpty("验证码不能为空")

View File

@ -15,7 +15,7 @@ public class LoginByPasswordCommandValidator extends BaseValidator<LoginByPasswo
ruleForString(LoginByPasswordCommand::getPrincipal)
.notNull("输入用户名、邮箱地址或手机号")
.notEmpty("输入用户名、邮箱地址或手机号")
.matchesOne(List.of(PatternConsts.USERNAME, PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE),
.matchesOr(List.of(PatternConsts.USERNAME, PatternConsts.EMAIL, PatternConsts.MOBILE_PHONE),
"输入用户名、邮箱地址或手机号");
ruleForString(LoginByPasswordCommand::getPassword)
.notNull("密码不能为空")

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

@ -87,13 +87,10 @@
AND sar.role_id = #{roleId}
AND sr.deleted = 0
</if>
<if test="orderBy != null and !orderBy.isEmpty()">
ORDER BY
<foreach item="col" index="index" collection="orderBy" open="" separator="," close="">
sa.${col}
</foreach>
<if test="orderBy != null">
ORDER BY sa.${orderBy}, sa.id
</if>
<if test="orderBy == null or orderBy.isEmpty()">
<if test="orderBy == null">
ORDER BY sa.id
</if>
LIMIT #{size} OFFSET #{offset}
@ -102,7 +99,7 @@
</select>
<!--
long count(AccountQueryParams queryParams);
long count(SysAccountQuery queryParams);
-->
<select id="count" resultType="long">
SELECT COUNT(*)

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone-system</artifactId>

View File

@ -1,12 +1,15 @@
package xyz.zhouxy.plusone.system.util;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.springframework.util.Assert;
import com.google.common.hash.Hashing;
import javax.annotation.Nonnull;
import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
import xyz.zhouxy.plusone.exception.BizException;
import xyz.zhouxy.plusone.util.RandomUtil;
/**
@ -14,6 +17,7 @@ import xyz.zhouxy.plusone.util.RandomUtil;
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
@Slf4j
public final class PasswordUtil {
private static final char[] SALT_BASE_CHAR_ARRAY = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~`!@#$%^&*()_-+={}[]|\\:;\"',.<>?/"
.toCharArray();
@ -25,18 +29,18 @@ public final class PasswordUtil {
* @param salt
* @return
*/
public static String hashPassword(String password, String salt) {
Assert.notNull(password, "Password must not be null");
Assert.notNull(salt, "Salt must not be null");
return Hashing.sha512().newHasher()
.putInt(Arrays.hashCode(salt.toCharArray()))
.putString(password, StandardCharsets.UTF_8)
.putInt(password.length())
.putBoolean(password.length() % 2 == 0)
.putString(salt, StandardCharsets.UTF_8)
.putInt(Arrays.hashCode(password.toCharArray()))
.hash()
.toString();
@Nonnull
public static String hashPassword(@Nonnull String password, @Nonnull String salt) {
int length = salt.length();
int i = length > 0 ? length / 2 : 0;
var passwordWithSalt = salt.substring(0, i)
+ password
+ salt.substring(1);
String sha512Hex = sha512Hex(passwordWithSalt);
if (sha512Hex == null) {
throw new BizException(ErrorCodeConsts.DEFAULT_ERROR_CODE, "未知错误:哈希加密失败!");
}
return sha512Hex;
}
/**
@ -52,4 +56,16 @@ public final class PasswordUtil {
// 不允许实例化
throw new IllegalStateException("Utility class");
}
private static String sha512Hex(String data) {
try {
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
messageDigest.update(data.getBytes(StandardCharsets.UTF_8));
byte[] result = messageDigest.digest();
return new BigInteger(1, result).toString(16);
} catch (NoSuchAlgorithmException e) {
log.error("{}", e);
}
return null;
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>xyz.zhouxy</groupId>

View File

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

View File

@ -23,7 +23,7 @@ public final class AccountStatus extends Enumeration<AccountStatus> implements I
public static final AccountStatus AVAILABLE = new AccountStatus(0, "账号正常");
public static final AccountStatus LOCKED = new AccountStatus(1, "账号被锁定");
private static final ValueSet<AccountStatus> VALUE_SET = ValueSet.of(
private static final ValueSet<AccountStatus> VALUE_SET = new ValueSet<>(
AVAILABLE,
LOCKED);

View File

@ -3,11 +3,7 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import cn.hutool.core.util.DesensitizedUtil;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.annotation.ValueObject;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
/**
@ -15,28 +11,38 @@ import xyz.zhouxy.plusone.commons.constant.PatternConsts;
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
@ValueObject
public final class Email extends Principal {
public class Email extends Principal {
public static final Pattern REGEX = PatternConsts.EMAIL;
private Email(String email) {
super(email, REGEX);
super(REGEX);
if (email == null) {
throw new IllegalArgumentException("邮箱地址不能为空");
}
this.value = email;
if (!isValid()) {
throw new IllegalArgumentException("邮箱地址格式错误");
}
}
@StaticFactoryMethod(Email.class)
public static Email of(String email) {
return new Email(email);
}
@StaticFactoryMethod(Email.class)
@Nullable
public static Email ofNullable(String email) {
return Objects.nonNull(email) ? new Email(email) : null;
}
@Override
/**
*
*/
public String safeValue() {
return DesensitizedUtil.email(value());
return DesensitizedUtil.email(this.value);
}
@Override
public String toString() {
return this.safeValue();
}
}

View File

@ -3,11 +3,7 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import cn.hutool.core.util.DesensitizedUtil;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.annotation.ValueObject;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
/**
@ -15,28 +11,35 @@ import xyz.zhouxy.plusone.commons.constant.PatternConsts;
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
@ValueObject
public class MobilePhone extends Principal {
public static final Pattern REGEX = PatternConsts.MOBILE_PHONE;
private MobilePhone(String mobilePhone) {
super(mobilePhone, REGEX);
super(REGEX);
if (mobilePhone == null) {
throw new IllegalArgumentException("手机号不能为空");
}
this.value = mobilePhone;
if (!isValid()) {
throw new IllegalArgumentException("手机号格式错误");
}
}
@StaticFactoryMethod(MobilePhone.class)
public static MobilePhone of(String mobilePhone) {
return new MobilePhone(mobilePhone);
}
@StaticFactoryMethod(MobilePhone.class)
@Nullable
public static MobilePhone ofNullable(String mobilePhone) {
return Objects.nonNull(mobilePhone) ? new MobilePhone(mobilePhone) : null;
}
@Override
public String safeValue() {
return DesensitizedUtil.mobilePhone(this.value());
return DesensitizedUtil.mobilePhone(this.value);
}
@Override
public String toString() {
return this.safeValue();
}
}

View File

@ -3,31 +3,33 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.Objects;
import java.util.regex.Pattern;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.annotation.ValueObject;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
import xyz.zhouxy.plusone.commons.domain.ValidatableStringRecord;
import xyz.zhouxy.plusone.domain.ValidatableStringRecord;
/**
*
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
@ValueObject
public class Nickname extends ValidatableStringRecord {
public static final Pattern REGEX = PatternConsts.NICKNAME;
private Nickname(String value) {
super(value, REGEX);
super(REGEX);
if (value == null) {
throw new IllegalArgumentException("昵称不能为空");
}
this.value = value;
if (!isValid()) {
throw new IllegalArgumentException("昵称格式错误");
}
}
@StaticFactoryMethod(Nickname.class)
public static Nickname of(String nickname) {
return new Nickname(nickname);
}
@StaticFactoryMethod(Nickname.class)
public static Nickname ofNullable(String nickname) {
return Objects.nonNull(nickname) ? new Nickname(nickname) : null;
}

View File

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

View File

@ -2,23 +2,15 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.regex.Pattern;
import xyz.zhouxy.plusone.commons.domain.ValidatableStringRecord;
import xyz.zhouxy.plusone.domain.IValueObject;
import xyz.zhouxy.plusone.domain.ValidatableStringRecord;
/**
*
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
public abstract class Principal extends ValidatableStringRecord implements IValueObject {
protected Principal(String principal, Pattern pattern) {
super(principal, pattern);
}
protected abstract String safeValue();
@Override
public final String toString() {
return this.safeValue();
public abstract class Principal extends ValidatableStringRecord {
protected Principal(Pattern format) {
super(format);
}
}

View File

@ -4,7 +4,6 @@ import java.util.Collection;
import javax.annotation.Nonnull;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.util.Enumeration;
import xyz.zhouxy.plusone.domain.IValueObject;
@ -25,9 +24,8 @@ public final class Sex extends Enumeration<Sex> implements IValueObject {
super(id, name);
}
private static final ValueSet<Sex> VALUE_SET = ValueSet.of(UNSET, MALE, FEMALE);
private static final ValueSet<Sex> VALUE_SET = new ValueSet<>(UNSET, MALE, FEMALE);
@StaticFactoryMethod(Sex.class)
public static Sex of(int value) {
return VALUE_SET.get(value);
}

View File

@ -2,8 +2,6 @@ package xyz.zhouxy.plusone.system.domain.model.account;
import java.util.regex.Pattern;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.commons.annotation.ValueObject;
import xyz.zhouxy.plusone.commons.constant.PatternConsts;
/**
@ -11,23 +9,22 @@ import xyz.zhouxy.plusone.commons.constant.PatternConsts;
*
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
*/
@ValueObject
public class Username extends Principal {
public static final Pattern REGEX = PatternConsts.USERNAME;
private Username(String username) {
super(username, REGEX);
super(REGEX);
if (username == null) {
throw new IllegalArgumentException("用户名不能为空");
}
this.value = username;
if (!isValid()) {
throw new IllegalArgumentException("用户名格式错误");
}
}
@StaticFactoryMethod(Username.class)
public static Username of(String username) {
return new Username(username);
}
@Override
protected String safeValue() {
// 不需要脱敏。
return value();
}
}

View File

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

View File

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

View File

@ -9,7 +9,6 @@ import com.fasterxml.jackson.annotation.JsonValue;
import lombok.Getter;
import lombok.ToString;
import xyz.zhouxy.plusone.commons.base.IWithIntCode;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.domain.AggregateRoot;
import xyz.zhouxy.plusone.domain.IWithOrderNumber;
@ -130,28 +129,12 @@ public class Menu extends AggregateRoot<Long> implements IWithOrderNumber, IWith
this.version = version;
}
public enum MenuType implements IWithIntCode {
MENU_LIST(0), MENU_ITEM(1);
private final int code;
private MenuType(int code) {
this.code = code;
}
public enum MenuType {
MENU_LIST, MENU_ITEM;
@JsonValue
@Override
public int getCode() {
return code;
}
public static MenuType valueOf(int code) {
for (MenuType value : values()) {
if (value.code == code) {
return value;
}
}
throw new EnumConstantNotPresentException(MenuType.class, Integer.toString(code));
public int value() {
return ordinal();
}
}
}

View File

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

View File

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

View File

@ -6,7 +6,6 @@ import java.util.Objects;
import java.util.Optional;
import lombok.Getter;
import xyz.zhouxy.plusone.commons.annotation.StaticFactoryMethod;
import xyz.zhouxy.plusone.domain.AggregateRoot;
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) {
return new Permission(
null, resource,

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone-system</artifactId>

View File

@ -14,8 +14,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Repository;
import cn.hutool.core.util.IdUtil;
import xyz.zhouxy.plusone.commons.domain.ValidatableStringRecord;
import xyz.zhouxy.plusone.commons.util.OptionalUtil;
import static xyz.zhouxy.plusone.domain.ValidatableStringRecord.getValueOrNull;
import xyz.zhouxy.plusone.jdbc.JdbcRepositorySupport;
/**
@ -197,35 +196,23 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
@Override
protected final SqlParameterSource generateParamSource(Long id, @Nonnull Account entity) {
final LocalDateTime now = LocalDateTime.now();
final AccountInfo accountInfo = entity.getAccountInfo();
final Optional<String> email = entity.getEmail().map(ValidatableStringRecord::value);
final Optional<String> mobilePhone = entity.getMobilePhone().map(ValidatableStringRecord::value);
final String username = entity.getUsername().value();
final String password = entity.getPassword().value();
final String salt = entity.getPassword().getSalt();
final Optional<String> avatar = accountInfo.getAvatar().map(Object::toString);
final int sex = accountInfo.getSex().getId();
final Optional<String> nickname = accountInfo.getNickname().map(ValidatableStringRecord::value);
final int status = entity.getStatus().getId();
final Optional<Long> createdBy = entity.getCreatedBy();
final Optional<Long> updatedBy = entity.getUpdatedBy();
final long version = entity.getVersion();
LocalDateTime now = LocalDateTime.now();
AccountInfo accountInfo = entity.getAccountInfo();
return new MapSqlParameterSource()
.addValue("id", id)
.addValue("email", OptionalUtil.orElseNull(email))
.addValue("mobilePhone", OptionalUtil.orElseNull(mobilePhone))
.addValue("username", username)
.addValue("password", password)
.addValue("salt", salt)
.addValue("avatar", OptionalUtil.orElseNull(avatar))
.addValue("sex", sex)
.addValue("nickname", OptionalUtil.orElseNull(nickname))
.addValue("status", status)
.addValue("createdBy", OptionalUtil.orElseNull(createdBy))
.addValue("email", getValueOrNull(entity.getEmail()))
.addValue("mobilePhone", getValueOrNull(entity.getMobilePhone()))
.addValue("username", entity.getUsername().value())
.addValue("password", entity.getPassword().value())
.addValue("salt", entity.getPassword().getSalt())
.addValue("avatar", accountInfo.getAvatar().toString())
.addValue("sex", accountInfo.getSex().getId())
.addValue("nickname", getValueOrNull(accountInfo.getNickname()))
.addValue("status", entity.getStatus().getId())
.addValue("createdBy", entity.getCreatedBy())
.addValue("createTime", now)
.addValue("updatedBy", OptionalUtil.orElseNull(updatedBy))
.addValue("updatedBy", entity.getUpdatedBy())
.addValue("updateTime", now)
.addValue("version", version);
.addValue("version", entity.getVersion());
}
}

View File

@ -7,7 +7,6 @@ import java.sql.SQLException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import javax.annotation.Nonnull;
@ -95,12 +94,13 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
@Override
protected final Dict mapRow(ResultSet rs) throws SQLException {
final long id = rs.getLong("id");
final String dictType = rs.getString("dict_type");
final String dictLabel = rs.getString("dict_label");
final Set<DictValue> values = this.dictValueDAO.selectDictValuesByDictId(id);
final long version = rs.getLong("version");
return new Dict(id, dictType, dictLabel, values, version);
long id = rs.getLong("id");
return new Dict(
id,
rs.getString("dict_type"),
rs.getString("dict_label"),
this.dictValueDAO.selectDictValuesByDictId(id),
rs.getLong("version"));
}
@Override

View File

@ -17,6 +17,7 @@ import org.springframework.stereotype.Repository;
import org.springframework.util.CollectionUtils;
import cn.hutool.core.util.IdUtil;
import xyz.zhouxy.plusone.commons.util.EnumUtil;
import xyz.zhouxy.plusone.constant.EntityStatus;
import xyz.zhouxy.plusone.exception.DataNotExistException;
import xyz.zhouxy.plusone.jdbc.JdbcRepositorySupport;
@ -155,7 +156,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
protected final Menu mapRow(ResultSet rs) throws SQLException {
long menuId = rs.getLong("id");
return new Menu(
MenuType.valueOf(rs.getInt("type")),
EnumUtil.valueOf(MenuType.class, rs.getInt("type")),
menuId,
rs.getLong("parent_id"),
rs.getString("name"),
@ -180,7 +181,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
return new MapSqlParameterSource()
.addValue("id", id)
.addValue("parentId", entity.getParentId())
.addValue("type", entity.getType().getCode())
.addValue("type", entity.getType().value())
.addValue("name", entity.getName())
.addValue("path", entity.getPath())
.addValue("title", entity.getTitle())

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<artifactId>plusone</artifactId>

10
pom.xml
View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@ -25,9 +25,9 @@
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<spring-boot.version>2.7.18</spring-boot.version>
<spring-boot.version>2.7.10</spring-boot.version>
<sa-token.version>1.34.0</sa-token.version>
<hutool.version>5.8.20</hutool.version>
<hutool.version>5.8.16</hutool.version>
<mybatis-starter.version>3.0.1</mybatis-starter.version>
<mybatis-plus.version>3.5.3.1</mybatis-plus.version>
<commons-io.version>2.11.0</commons-io.version>
@ -40,7 +40,7 @@
<commons-pool2.version>2.11.1</commons-pool2.version>
<tencentcloud-sdk.version>3.1.681</tencentcloud-sdk.version>
<fastdfs.version>1.30-SNAPSHOT</fastdfs.version>
<okio.version>3.5.0</okio.version>
<okio.version>3.0.0</okio.version>
<okhttp.version>4.10.0</okhttp.version>
<plusone-basic.version>1.0.0-SNAPSHOT</plusone-basic.version>