Merge branch 'dev' into main
commit
1b551eeb4c
|
@ -4,6 +4,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
|
||||
|
||||
/**
|
||||
* AllExceptionHandlerConfig
|
||||
*/
|
||||
|
@ -12,7 +14,7 @@ import org.springframework.context.annotation.Configuration;
|
|||
public class AllExceptionHandlerConfig {
|
||||
|
||||
@Bean
|
||||
AllExceptionHandler getAllExceptionHandler() {
|
||||
return new AllExceptionHandler(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
|
||||
AllExceptionHandler getAllExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
|
||||
return new AllExceptionHandler(exceptionInfoHolder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,9 +40,8 @@ import xyz.zhouxy.plusone.util.RestfulResult;
|
|||
@Order(Ordered.LOWEST_PRECEDENCE - 1)
|
||||
@Slf4j
|
||||
public class DefaultExceptionHandler extends BaseExceptionHandler {
|
||||
|
||||
public DefaultExceptionHandler() {
|
||||
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
|
||||
public DefaultExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
|
||||
super(exceptionInfoHolder);
|
||||
set(IllegalArgumentException.class, 4010000, "格式错误", HttpStatus.FORBIDDEN);
|
||||
set(DataAccessException.class, 6030000, "数据库错误", HttpStatus.INTERNAL_SERVER_ERROR, true);
|
||||
set(MethodArgumentNotValidException.class,
|
||||
|
|
|
@ -31,6 +31,11 @@
|
|||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>xyz.zhouxy.plusone</groupId>
|
||||
<artifactId>plusone-commons</artifactId>
|
||||
|
|
|
@ -6,12 +6,7 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
|||
/**
|
||||
* 需要时,当查询数据不存在时抛出的异常
|
||||
*
|
||||
* <p>
|
||||
* 暂时先这样,后续完善异常体系时可能会更改。
|
||||
* </p>
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
* @see xyz.zhouxy.plusone.util.AssertResult
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||
public class DataNotExistException extends PlusoneException {
|
||||
|
|
|
@ -4,7 +4,7 @@ import org.springframework.http.HttpStatus;
|
|||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
/**
|
||||
* 需要时,当数据操作的行数不符合预期时抛出的异常
|
||||
* 需要时,当数据操作的结果不符合预期时抛出的异常
|
||||
*
|
||||
* <p>
|
||||
* 暂时先这样,后续完善异常体系时可能会更改。
|
||||
|
@ -14,18 +14,18 @@ import org.springframework.web.bind.annotation.ResponseStatus;
|
|||
* @see xyz.zhouxy.plusone.util.AssertResult
|
||||
*/
|
||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
public class DataOperationNumberException extends PlusoneException {
|
||||
public class DataOperationResultException extends PlusoneException {
|
||||
|
||||
@java.io.Serial
|
||||
private static final long serialVersionUID = -9220765735990318186L;
|
||||
|
||||
public static final int ERROR_CODE = 4110200;
|
||||
|
||||
public DataOperationNumberException() {
|
||||
super(ERROR_CODE, "数据操作的行数不符合预期");
|
||||
public DataOperationResultException() {
|
||||
super(ERROR_CODE, "数据操作结果不符合预期");
|
||||
}
|
||||
|
||||
public DataOperationNumberException(String message) {
|
||||
public DataOperationResultException(String message) {
|
||||
super(ERROR_CODE, message);
|
||||
}
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package xyz.zhouxy.plusone.util;
|
||||
|
||||
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
import xyz.zhouxy.plusone.exception.DataOperationNumberException;
|
||||
import xyz.zhouxy.plusone.exception.DataOperationResultException;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* 对数据库执行结果进行判断
|
||||
|
@ -17,51 +17,34 @@ public final class AssertResult {
|
|||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static void update(boolean expression) {
|
||||
if (!expression) {
|
||||
throw new DataOperationNumberException();
|
||||
public static <E extends Throwable> void isTrue(boolean condition, Supplier<E> e) throws E {
|
||||
if (!condition) {
|
||||
throw e.get();
|
||||
}
|
||||
}
|
||||
|
||||
public static void update(boolean expression, String message) {
|
||||
if (!expression) {
|
||||
throw new DataOperationNumberException(message);
|
||||
}
|
||||
public static <T> void equals(T result, T expectedValue) {
|
||||
isTrue(Objects.equals(result, expectedValue), DataOperationResultException::new);
|
||||
}
|
||||
|
||||
public static void update(Object i, int expectedValue) {
|
||||
if (!Objects.equals(i, expectedValue)) {
|
||||
throw new DataOperationNumberException();
|
||||
}
|
||||
public static <T> void equals(T result, T expectedValue, String msgTemplate, Object... args) {
|
||||
isTrue(!Objects.equals(result, expectedValue),
|
||||
() -> new DataOperationResultException(String.format(msgTemplate, args)));
|
||||
}
|
||||
|
||||
public static void update(Object i, int expectedValue, String format) {
|
||||
if (!Objects.equals(i, expectedValue)) {
|
||||
throw new DataOperationNumberException(String.format(format, i));
|
||||
}
|
||||
public static void updateOneRow(int i) {
|
||||
equals(i, 1);
|
||||
}
|
||||
|
||||
public static void exist(boolean expression) {
|
||||
if (!expression) {
|
||||
throw new DataNotExistException();
|
||||
}
|
||||
}
|
||||
|
||||
public static void exist(boolean expression, String message) {
|
||||
if (!expression) {
|
||||
throw new DataNotExistException(message);
|
||||
}
|
||||
public static void updateOneRow(int i, String format, Object... args) {
|
||||
equals(i, 1, format, args);
|
||||
}
|
||||
|
||||
public static void nonNull(Object obj) {
|
||||
if (Objects.isNull(obj)) {
|
||||
throw new DataNotExistException();
|
||||
}
|
||||
isTrue(Objects.nonNull(obj), DataNotExistException::new);
|
||||
}
|
||||
|
||||
public static void nonNull(Object obj, String message) {
|
||||
if (Objects.isNull(obj)) {
|
||||
throw new DataNotExistException(message);
|
||||
}
|
||||
isTrue(Objects.nonNull(obj), () -> new DataNotExistException(message));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package xyz.zhouxy.plusone.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Repository 基础接口
|
||||
|
@ -10,7 +11,7 @@ import java.io.Serializable;
|
|||
*/
|
||||
public interface IRepository<T extends AggregateRoot<ID>, ID extends Serializable> {
|
||||
|
||||
T find(ID id);
|
||||
Optional<T> find(ID id);
|
||||
|
||||
T save(T entity);
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package xyz.zhouxy.plusone.domain;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
|
||||
|
@ -31,4 +33,8 @@ public abstract class ValidatableStringRecord implements IValueObject {
|
|||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static String getValueOrNull(Optional<? extends ValidatableStringRecord> s) {
|
||||
return s.map(ValidatableStringRecord::value).orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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">
|
||||
<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>
|
||||
|
@ -84,6 +86,11 @@
|
|||
<groupId>com.tencentcloudapi</groupId>
|
||||
<artifactId>tencentcloud-sdk-java-sms</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.csource</groupId>
|
||||
<artifactId>fastdfs-client-java</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package xyz.zhouxy.plusone.exception.config;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
|
||||
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
|
||||
|
||||
@Configuration
|
||||
public class PlusoneExceptionHandlerConfig {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
ExceptionInfoHolder exceptionInfoHolder() {
|
||||
return new ExceptionInfoHolder(ErrorCodeConsts.DEFAULT_ERROR_CODE);
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
package xyz.zhouxy.plusone.exception.handler;
|
||||
|
||||
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
|
||||
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
|
||||
|
||||
public class ExceptionInfoHolderFactory {
|
||||
|
||||
private ExceptionInfoHolderFactory() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static ExceptionInfoHolder newDefaultExceptionInfoHolder() {
|
||||
return new ExceptionInfoHolder(ErrorCodeConsts.DEFAULT_ERROR_CODE);
|
||||
}
|
||||
}
|
|
@ -4,60 +4,61 @@ import java.io.Serializable;
|
|||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
|
||||
import xyz.zhouxy.plusone.domain.Entity;
|
||||
|
||||
public abstract class JdbcEntityDaoSupport<T extends Entity<ID>, ID extends Serializable> {
|
||||
protected final NamedParameterJdbcTemplate jdbc;
|
||||
public abstract class JdbcEntityDaoSupport<T extends Entity<ID>, ID extends Serializable>
|
||||
extends PlusoneJdbcDaoSupport {
|
||||
|
||||
protected RowMapper<T> rowMapper;
|
||||
protected ResultSetExtractor<T> resultSetExtractor;
|
||||
protected ResultSetExtractor<Optional<T>> resultSetExtractor;
|
||||
|
||||
protected JdbcEntityDaoSupport(@Nonnull NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
||||
this.jdbc = namedParameterJdbcTemplate;
|
||||
super(namedParameterJdbcTemplate);
|
||||
this.rowMapper = (ResultSet rs, int rowNum) -> mapRow(rs);
|
||||
this.resultSetExtractor = (ResultSet rs) -> rs.next() ? mapRow(rs) : null;
|
||||
this.resultSetExtractor = (ResultSet rs) -> rs.next() ? Optional.of(mapRow(rs)) : Optional.empty();
|
||||
}
|
||||
|
||||
protected final T queryForObject(String sql) {
|
||||
return this.jdbc.query(sql, this.resultSetExtractor);
|
||||
protected final Optional<T> queryForObject(String sql) {
|
||||
return queryForObject(sql, this.resultSetExtractor);
|
||||
}
|
||||
|
||||
protected final T queryForObject(String sql, SqlParameterSource paramSource) {
|
||||
return this.jdbc.query(sql, paramSource, this.resultSetExtractor);
|
||||
protected final Optional<T> queryForObject(String sql, SqlParameterSource paramSource) {
|
||||
return queryForObject(sql, paramSource, this.resultSetExtractor);
|
||||
}
|
||||
|
||||
protected final Optional<T> queryForObject(String sql, String paramName, Object value) {
|
||||
return queryForObject(sql, new MapSqlParameterSource(paramName, value), this.resultSetExtractor);
|
||||
}
|
||||
|
||||
protected final List<T> queryForList(String sql) {
|
||||
return this.jdbc.query(sql, this.rowMapper);
|
||||
return queryForList(sql, this.rowMapper);
|
||||
}
|
||||
|
||||
protected final List<T> queryForList(String sql, SqlParameterSource parameterSource) {
|
||||
return this.jdbc.query(sql, parameterSource, this.rowMapper);
|
||||
return queryForList(sql, parameterSource, this.rowMapper);
|
||||
}
|
||||
|
||||
protected final List<T> queryForList(String sql, String paramName, Object value) {
|
||||
return queryForList(sql, new MapSqlParameterSource(paramName, value), this.rowMapper);
|
||||
}
|
||||
|
||||
protected final Stream<T> queryForStream(String sql, SqlParameterSource parameterSource) {
|
||||
return this.jdbc.queryForStream(sql, parameterSource, this.rowMapper);
|
||||
return queryForStream(sql, parameterSource, this.rowMapper);
|
||||
}
|
||||
|
||||
protected final <E> Stream<E> queryForStream(String sql, SqlParameterSource parameterSource, Class<E> elementType) {
|
||||
return this.jdbc.queryForList(sql, parameterSource, elementType).stream();
|
||||
}
|
||||
|
||||
protected final boolean queryExists(String sql, SqlParameterSource parameterSource) {
|
||||
Boolean isExists = this.jdbc.query(sql, parameterSource, ResultSet::next);
|
||||
return Boolean.TRUE.equals(isExists);
|
||||
}
|
||||
|
||||
protected final int update(String sql, SqlParameterSource parameterSource) {
|
||||
return this.jdbc.update(sql, parameterSource);
|
||||
protected final Stream<T> queryForStream(String sql, String paramName, Object value) {
|
||||
return queryForStream(sql, new MapSqlParameterSource(paramName, value), this.rowMapper);
|
||||
}
|
||||
|
||||
protected abstract T mapRow(ResultSet rs) throws SQLException;
|
||||
|
@ -66,7 +67,7 @@ public abstract class JdbcEntityDaoSupport<T extends Entity<ID>, ID extends Seri
|
|||
this.rowMapper = rowMapper;
|
||||
}
|
||||
|
||||
protected void setResultSetExtractor(@Nonnull ResultSetExtractor<T> resultSetExtractor) {
|
||||
protected void setResultSetExtractor(@Nonnull ResultSetExtractor<Optional<T>> resultSetExtractor) {
|
||||
this.resultSetExtractor = resultSetExtractor;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package xyz.zhouxy.plusone.jdbc;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
|
||||
|
@ -16,15 +17,17 @@ import xyz.zhouxy.plusone.spring.SpringContextHolder;
|
|||
*/
|
||||
public final class JdbcFactory {
|
||||
|
||||
private static final ApplicationContext CONTEXT = SpringContextHolder.getContext();
|
||||
|
||||
private JdbcFactory() {
|
||||
throw new IllegalStateException("Utility class");
|
||||
}
|
||||
|
||||
public static JdbcTemplate getJdbcTemplate() {
|
||||
return SpringContextHolder.getContext().getBean(JdbcTemplate.class);
|
||||
return CONTEXT.getBean(JdbcTemplate.class);
|
||||
}
|
||||
|
||||
public static NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
|
||||
return SpringContextHolder.getContext().getBean(NamedParameterJdbcTemplate.class);
|
||||
return CONTEXT.getBean(NamedParameterJdbcTemplate.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package xyz.zhouxy.plusone.jdbc;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
@ -20,7 +21,7 @@ public abstract class JdbcRepositorySupport<T extends AggregateRoot<ID>, ID exte
|
|||
|
||||
protected abstract void doDelete(@Nonnull T entity);
|
||||
|
||||
protected abstract T doFindById(@Nonnull ID id);
|
||||
protected abstract Optional<T> doFindById(@Nonnull ID id);
|
||||
|
||||
protected abstract T doInsert(@Nonnull T entity);
|
||||
|
||||
|
@ -35,7 +36,7 @@ public abstract class JdbcRepositorySupport<T extends AggregateRoot<ID>, ID exte
|
|||
}
|
||||
|
||||
@Override
|
||||
public final T find(ID id) {
|
||||
public final Optional<T> find(ID id) {
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("Id cannot be null.");
|
||||
}
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
package xyz.zhouxy.plusone.jdbc;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.springframework.jdbc.core.ResultSetExtractor;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
|
||||
import xyz.zhouxy.plusone.exception.DataOperationResultException;
|
||||
import xyz.zhouxy.plusone.util.NumberUtil;
|
||||
|
||||
public abstract class PlusoneJdbcDaoSupport {
|
||||
protected final NamedParameterJdbcTemplate jdbc;
|
||||
|
||||
protected PlusoneJdbcDaoSupport(@Nonnull NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
|
||||
this.jdbc = namedParameterJdbcTemplate;
|
||||
}
|
||||
|
||||
protected final <T> T queryForObject(String sql, ResultSetExtractor<T> resultSetExtractor) {
|
||||
return this.jdbc.query(sql, resultSetExtractor);
|
||||
}
|
||||
|
||||
protected final <T> T queryForObject(String sql, SqlParameterSource paramSource,
|
||||
ResultSetExtractor<T> resultSetExtractor) {
|
||||
return this.jdbc.query(sql, paramSource, resultSetExtractor);
|
||||
}
|
||||
|
||||
protected final <T> T queryForObject(String sql, String paramName, Object value,
|
||||
ResultSetExtractor<T> resultSetExtractor) {
|
||||
return this.jdbc.query(sql, new MapSqlParameterSource(paramName, value), resultSetExtractor);
|
||||
}
|
||||
|
||||
protected final <T> List<T> queryForList(String sql, RowMapper<T> rowMapper) {
|
||||
return this.jdbc.query(sql, rowMapper);
|
||||
}
|
||||
|
||||
protected final <T> List<T> queryForList(String sql, SqlParameterSource parameterSource, RowMapper<T> rowMapper) {
|
||||
return this.jdbc.query(sql, parameterSource, rowMapper);
|
||||
}
|
||||
|
||||
protected final <T> List<T> queryForList(String sql, String paramName, Object value, RowMapper<T> rowMapper) {
|
||||
return this.jdbc.query(sql, new MapSqlParameterSource(paramName, value), rowMapper);
|
||||
}
|
||||
|
||||
protected final <T> Stream<T> queryForStream(String sql, SqlParameterSource parameterSource,
|
||||
RowMapper<T> rowMapper) {
|
||||
return this.jdbc.queryForStream(sql, parameterSource, rowMapper);
|
||||
}
|
||||
|
||||
protected final <T> Stream<T> queryForStream(String sql, String paramName, Object value, RowMapper<T> rowMapper) {
|
||||
return this.jdbc.queryForStream(sql, new MapSqlParameterSource(paramName, value), rowMapper);
|
||||
}
|
||||
|
||||
protected final <T> Stream<T> queryForStream(String sql, SqlParameterSource parameterSource, Class<T> elementType) {
|
||||
return this.jdbc.queryForList(sql, parameterSource, elementType).stream();
|
||||
}
|
||||
|
||||
protected final <T> Stream<T> queryForStream(String sql, String paramName, Object value, Class<T> elementType) {
|
||||
return queryForStream(sql, new MapSqlParameterSource(paramName, value), elementType);
|
||||
}
|
||||
|
||||
protected final boolean queryExists(String sql, SqlParameterSource parameterSource) {
|
||||
Boolean isExists = this.jdbc.queryForObject(sql, parameterSource, Boolean.TYPE);
|
||||
return Boolean.TRUE.equals(isExists);
|
||||
}
|
||||
|
||||
protected final boolean queryExists(String sql, String paramName, Object value) {
|
||||
return queryExists(sql, new MapSqlParameterSource(paramName, value));
|
||||
}
|
||||
|
||||
protected final int update(String sql, SqlParameterSource parameterSource) {
|
||||
return this.jdbc.update(sql, parameterSource);
|
||||
}
|
||||
|
||||
protected final int update(String sql, String paramName, Object value) {
|
||||
return update(sql, new MapSqlParameterSource(paramName, value));
|
||||
}
|
||||
|
||||
protected final int batchUpdate(String sql, SqlParameterSource[] batchArgs) {
|
||||
int[] i = this.jdbc.batchUpdate(sql, batchArgs);
|
||||
return NumberUtil.sum(i);
|
||||
}
|
||||
|
||||
protected final <T> int batchUpdate(String sql, Stream<T> c,
|
||||
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
|
||||
int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder));
|
||||
return NumberUtil.sum(i);
|
||||
}
|
||||
|
||||
protected final <T> int batchUpdate(String sql, Collection<T> c,
|
||||
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
|
||||
int[] i = this.jdbc.batchUpdate(sql, buildSqlParameterSourceArray(c, paramSourceBuilder));
|
||||
return NumberUtil.sum(i);
|
||||
}
|
||||
|
||||
protected static final <T> void assertResultEquals(T result, T expectedValue) {
|
||||
if (!Objects.equals(result, expectedValue)) {
|
||||
throw new DataOperationResultException();
|
||||
}
|
||||
}
|
||||
|
||||
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 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 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 final void assertUpdateOneRow(int result) {
|
||||
assertResultEquals(result, 1);
|
||||
}
|
||||
|
||||
protected static final void assertUpdateOneRow(int result, Function<Integer, String> errMsg) {
|
||||
assertResultEquals(result, 1, errMsg);
|
||||
}
|
||||
|
||||
protected static final void assertUpdateOneRow(int result, String msgTemplate, Object... args) {
|
||||
assertResultEquals(result, 1, msgTemplate, args);
|
||||
}
|
||||
|
||||
protected static final <E extends Throwable> void assertUpdateOneRowOrThrow(int result, Function<Integer, E> e)
|
||||
throws E {
|
||||
assertResultEqualsOrThrow(result, 1, e);
|
||||
}
|
||||
|
||||
protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray(
|
||||
T[] c,
|
||||
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
|
||||
if (c == null || c.length == 0) {
|
||||
return new SqlParameterSource[] {};
|
||||
}
|
||||
return buildSqlParameterSourceArray(Arrays.stream(c), paramSourceBuilder);
|
||||
}
|
||||
|
||||
protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray(
|
||||
Collection<T> c,
|
||||
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
|
||||
if (c == null || c.isEmpty()) {
|
||||
return new SqlParameterSource[] {};
|
||||
}
|
||||
return buildSqlParameterSourceArray(c.stream(), paramSourceBuilder);
|
||||
}
|
||||
|
||||
protected static final <T> SqlParameterSource[] buildSqlParameterSourceArray(
|
||||
Stream<T> stream,
|
||||
@Nonnull Function<T, SqlParameterSource> paramSourceBuilder) {
|
||||
Objects.requireNonNull(stream);
|
||||
Objects.requireNonNull(paramSourceBuilder);
|
||||
return stream.map(paramSourceBuilder).toArray(SqlParameterSource[]::new);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package xyz.zhouxy.plusone.mail;
|
||||
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
@ -15,11 +14,10 @@ import org.springframework.mail.javamail.JavaMailSender;
|
|||
@Configuration
|
||||
@EnableConfigurationProperties(PlusoneMailProperties.class)
|
||||
@ConditionalOnClass(MailService.class)
|
||||
@EnableAutoConfiguration
|
||||
public class PlusoneMailAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public MailService mailService(JavaMailSender mailSender, PlusoneMailProperties mailProperties) {
|
||||
MailService mailService(JavaMailSender mailSender, PlusoneMailProperties mailProperties) {
|
||||
MailMessageFactory mailMessageFactory = new MailMessageFactory(mailProperties);
|
||||
return new SimpleMailService(mailSender, mailMessageFactory);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package xyz.zhouxy.plusone.oss;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import org.csource.common.MyException;
|
||||
import org.csource.fastdfs.ClientGlobal;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import xyz.zhouxy.plusone.oss.FastDFSProperties.ConnectionPool;
|
||||
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(FastDFSProperties.class)
|
||||
@ConditionalOnClass(FastDFSUtil.class)
|
||||
public class FastDFSAutoConfig {
|
||||
|
||||
@Bean
|
||||
@SuppressWarnings("all")
|
||||
FastDFSUtil fastDFSUtil(FastDFSProperties props) throws IOException, FastDFSException {
|
||||
|
||||
List<String> trackerServerStrList = props.getTrackerServers();
|
||||
if (CollectionUtils.isEmpty(trackerServerStrList)) {
|
||||
throw new FastDFSException(
|
||||
String.format("configure item %s is required - ", ClientGlobal.PROP_KEY_TRACKER_SERVERS));
|
||||
}
|
||||
try {
|
||||
InetSocketAddress[] trackerServers = trackerServerStrList.stream()
|
||||
.map(trackerServer -> {
|
||||
String[] hostPort = trackerServer.trim().split(":");
|
||||
String host = hostPort[0].trim();
|
||||
int port = Integer.parseInt(hostPort[1].trim());
|
||||
return new InetSocketAddress(host, port);
|
||||
})
|
||||
.toArray(InetSocketAddress[]::new);
|
||||
ClientGlobal.initByTrackers(trackerServers);
|
||||
|
||||
var connectTimeoutInSecondsConf = props.getConnectTimeoutInSeconds();
|
||||
if (connectTimeoutInSecondsConf != null) {
|
||||
ClientGlobal.setG_connect_timeout(connectTimeoutInSecondsConf * 1000);
|
||||
}
|
||||
var networkTimeoutInSecondsConf = props.getNetworkTimeoutInSeconds();
|
||||
if (networkTimeoutInSecondsConf != null) {
|
||||
ClientGlobal.setG_network_timeout(networkTimeoutInSecondsConf * 1000);
|
||||
}
|
||||
var charsetConf = props.getCharset();
|
||||
if (StringUtils.hasText(charsetConf)) {
|
||||
ClientGlobal.setG_charset(charsetConf);
|
||||
}
|
||||
var httpAntiStealTokenConf = props.getHttpAntiStealToken();
|
||||
if (httpAntiStealTokenConf != null) {
|
||||
ClientGlobal.setG_anti_steal_token(httpAntiStealTokenConf);
|
||||
}
|
||||
var httpSecretKeyConf = props.getHttpSecretKey();
|
||||
if (StringUtils.hasText(httpSecretKeyConf)) {
|
||||
ClientGlobal.setG_secret_key(httpSecretKeyConf);
|
||||
}
|
||||
var httpTrackerHttpPortConf = props.getHttpTrackerHttpPort();
|
||||
if (httpTrackerHttpPortConf != null) {
|
||||
ClientGlobal.setG_tracker_http_port(httpTrackerHttpPortConf);
|
||||
}
|
||||
|
||||
ConnectionPool connectionPool = props.getConnectionPool();
|
||||
var poolEnabled = Objects.nonNull(connectionPool)
|
||||
&& Boolean.TRUE.equals(connectionPool.getEnabled());
|
||||
|
||||
if (poolEnabled) {
|
||||
var poolMaxCountPerEntry = connectionPool.getMaxCountPerEntry();
|
||||
if (poolMaxCountPerEntry != null) {
|
||||
ClientGlobal.g_connection_pool_max_count_per_entry = poolMaxCountPerEntry;
|
||||
}
|
||||
var poolMaxIdleTime = connectionPool.getMaxIdleTime();
|
||||
if (poolMaxIdleTime != null) {
|
||||
ClientGlobal.g_connection_pool_max_idle_time = poolMaxIdleTime * 1000;
|
||||
}
|
||||
var poolMaxWaitTimeInMS = connectionPool.getMaxWaitTimeInMs();
|
||||
if (poolMaxWaitTimeInMS != null) {
|
||||
ClientGlobal.g_connection_pool_max_wait_time_in_ms = poolMaxWaitTimeInMS;
|
||||
}
|
||||
}
|
||||
return new FastDFSUtil();
|
||||
} catch (MyException e) {
|
||||
throw new FastDFSException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package xyz.zhouxy.plusone.oss;
|
||||
|
||||
/**
|
||||
* 封装 FastDFS 的 {@link org.csource.common.MyException}
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
*/
|
||||
public class FastDFSException extends Exception {
|
||||
|
||||
public FastDFSException() {
|
||||
}
|
||||
|
||||
public FastDFSException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public FastDFSException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public FastDFSException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public FastDFSException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package xyz.zhouxy.plusone.oss;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
@ConfigurationProperties("fastdfs")
|
||||
public class FastDFSProperties {
|
||||
private Integer connectTimeoutInSeconds;
|
||||
private Integer networkTimeoutInSeconds;
|
||||
private String charset;
|
||||
private Boolean httpAntiStealToken;
|
||||
private String httpSecretKey;
|
||||
private Integer httpTrackerHttpPort;
|
||||
private List<String> trackerServers;
|
||||
|
||||
private ConnectionPool connectionPool;
|
||||
|
||||
public Integer getConnectTimeoutInSeconds() {
|
||||
return connectTimeoutInSeconds;
|
||||
}
|
||||
|
||||
public void setConnectTimeoutInSeconds(Integer connectTimeoutInSeconds) {
|
||||
this.connectTimeoutInSeconds = connectTimeoutInSeconds;
|
||||
}
|
||||
|
||||
public Integer getNetworkTimeoutInSeconds() {
|
||||
return networkTimeoutInSeconds;
|
||||
}
|
||||
|
||||
public void setNetworkTimeoutInSeconds(Integer networkTimeoutInSeconds) {
|
||||
this.networkTimeoutInSeconds = networkTimeoutInSeconds;
|
||||
}
|
||||
|
||||
public String getCharset() {
|
||||
return charset;
|
||||
}
|
||||
|
||||
public void setCharset(String charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
public Boolean getHttpAntiStealToken() {
|
||||
return httpAntiStealToken;
|
||||
}
|
||||
|
||||
public void setHttpAntiStealToken(Boolean httpAntiStealToken) {
|
||||
this.httpAntiStealToken = httpAntiStealToken;
|
||||
}
|
||||
|
||||
public String getHttpSecretKey() {
|
||||
return httpSecretKey;
|
||||
}
|
||||
|
||||
public void setHttpSecretKey(String httpSecretKey) {
|
||||
this.httpSecretKey = httpSecretKey;
|
||||
}
|
||||
|
||||
public Integer getHttpTrackerHttpPort() {
|
||||
return httpTrackerHttpPort;
|
||||
}
|
||||
|
||||
public void setHttpTrackerHttpPort(Integer httpTrackerHttpPort) {
|
||||
this.httpTrackerHttpPort = httpTrackerHttpPort;
|
||||
}
|
||||
|
||||
public List<String> getTrackerServers() {
|
||||
return trackerServers;
|
||||
}
|
||||
|
||||
public void setTrackerServers(List<String> trackerServers) {
|
||||
this.trackerServers = trackerServers;
|
||||
}
|
||||
|
||||
public ConnectionPool getConnectionPool() {
|
||||
return connectionPool;
|
||||
}
|
||||
|
||||
public void setConnectionPool(ConnectionPool connectionPool) {
|
||||
this.connectionPool = connectionPool;
|
||||
}
|
||||
|
||||
public static class ConnectionPool {
|
||||
private Boolean enabled;
|
||||
private Integer maxCountPerEntry;
|
||||
private Integer maxIdleTime;
|
||||
private Integer maxWaitTimeInMs;
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Integer getMaxCountPerEntry() {
|
||||
return maxCountPerEntry;
|
||||
}
|
||||
|
||||
public void setMaxCountPerEntry(Integer maxCountPerEntry) {
|
||||
this.maxCountPerEntry = maxCountPerEntry;
|
||||
}
|
||||
|
||||
public Integer getMaxIdleTime() {
|
||||
return maxIdleTime;
|
||||
}
|
||||
|
||||
public void setMaxIdleTime(Integer maxIdleTime) {
|
||||
this.maxIdleTime = maxIdleTime;
|
||||
}
|
||||
|
||||
public Integer getMaxWaitTimeInMs() {
|
||||
return maxWaitTimeInMs;
|
||||
}
|
||||
|
||||
public void setMaxWaitTimeInMs(Integer maxWaitTimeInMs) {
|
||||
this.maxWaitTimeInMs = maxWaitTimeInMs;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package xyz.zhouxy.plusone.oss;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.csource.common.MyException;
|
||||
import org.csource.common.NameValuePair;
|
||||
import org.csource.fastdfs.FileInfo;
|
||||
import org.csource.fastdfs.StorageClient;
|
||||
import org.csource.fastdfs.StorageServer;
|
||||
import org.csource.fastdfs.TrackerClient;
|
||||
import org.csource.fastdfs.TrackerServer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import lombok.Getter;
|
||||
|
||||
public class FastDFSUtil {
|
||||
|
||||
private final TrackerServer trackerServer;
|
||||
private final StorageServer storageServer;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(FastDFSUtil.class);
|
||||
|
||||
FastDFSUtil() throws IOException, MyException {
|
||||
TrackerClient trackerClient = new TrackerClient();
|
||||
this.trackerServer = trackerClient.getTrackerServer();
|
||||
this.storageServer = trackerClient.getStoreStorage(trackerServer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 上传文件到 Fast DFS,失败将抛异常
|
||||
*
|
||||
* @param file 文件信息
|
||||
* @return 2 elements string array if success:<br>
|
||||
* <ul>
|
||||
* <li>results[0]: the group name to store the file</li>
|
||||
* </ul>
|
||||
* <ul>
|
||||
* <li>results[1]: the new created filename</li>
|
||||
* </ul>
|
||||
* return null if fail
|
||||
* @throws FastDFSException
|
||||
*/
|
||||
public String[] upload(FastDFSFile file) throws FastDFSException {
|
||||
logger.info("File Name: {}, File Length: {}", file.getName(), file.getContent().length);
|
||||
|
||||
NameValuePair[] metaList = new NameValuePair[1];
|
||||
metaList[0] = new NameValuePair("author", file.getAuthor());
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
StorageClient storageClient = null;
|
||||
String[] uploadResults = null;
|
||||
try {
|
||||
storageClient = new StorageClient(this.trackerServer, this.storageServer);
|
||||
uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), metaList);
|
||||
|
||||
if (uploadResults == null) {
|
||||
throw new FastDFSException("upload file fail, error code: " + storageClient.getErrorCode());
|
||||
}
|
||||
logger.info("Upload file successfully!!! group_name: {}, remoteFileName: {}, time used: {} ms",
|
||||
uploadResults[0], uploadResults[1], System.currentTimeMillis() - startTime);
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new FastDFSException("IO Exception when uploadind the file:" + file.getName(), e);
|
||||
} catch (MyException e) {
|
||||
throw new FastDFSException(e);
|
||||
}
|
||||
|
||||
return uploadResults;
|
||||
}
|
||||
|
||||
public FileInfo getFile(String groupName, String remoteFileName) throws FastDFSException {
|
||||
try {
|
||||
StorageClient storageClient = new StorageClient(this.trackerServer, this.storageServer);
|
||||
return storageClient.get_file_info(groupName, remoteFileName);
|
||||
} catch (IOException e) {
|
||||
throw new FastDFSException("IO Exception: Get File from Fast DFS failed", e);
|
||||
} catch (Exception e) {
|
||||
throw new FastDFSException("Non IO Exception: Get File from Fast DFS failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
public InputStream downFile(String groupName, String remoteFileName) throws FastDFSException {
|
||||
try {
|
||||
StorageClient storageClient = new StorageClient(this.trackerServer, this.storageServer);
|
||||
byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
|
||||
InputStream ins = new ByteArrayInputStream(fileByte);
|
||||
return ins;
|
||||
} catch (IOException e) {
|
||||
throw new FastDFSException("IO Exception: Get File from Fast DFS failed", e);
|
||||
} catch (Exception e) {
|
||||
throw new FastDFSException("Non IO Exception: Get File from Fast DFS failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteFile(String groupName, String remoteFileName) throws FastDFSException {
|
||||
StorageClient storageClient = new StorageClient(this.trackerServer, this.storageServer);
|
||||
try {
|
||||
int i = storageClient.delete_file(groupName, remoteFileName);
|
||||
if (i == 0) {
|
||||
logger.info("Delete file SUCCESSFULLY!!!");
|
||||
} else {
|
||||
throw new FastDFSException("Delete file failed, error code is: " + i);
|
||||
}
|
||||
} catch (IOException | MyException e) {
|
||||
throw new FastDFSException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static final class FastDFSFile {
|
||||
private String name;
|
||||
private byte[] content;
|
||||
private String ext;
|
||||
private String md5;
|
||||
private String author;
|
||||
|
||||
public FastDFSFile(String name, byte[] content, String ext) {
|
||||
this.name = name;
|
||||
this.content = content;
|
||||
this.ext = ext;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,17 +11,12 @@ import org.springframework.context.annotation.Configuration;
|
|||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
*/
|
||||
@Configuration
|
||||
@EnableConfigurationProperties(value = {
|
||||
SmsProperties.class,
|
||||
SmsCredentialProperties.class,
|
||||
SmsClientProperties.class,
|
||||
SmsHttpProperties.class,
|
||||
SmsProxyProperties.class})
|
||||
@EnableConfigurationProperties(SmsProperties.class)
|
||||
@ConditionalOnClass(SmsService.class)
|
||||
public class PlusoneSmsAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
public SmsService smsService(SmsProperties smsProperties) {
|
||||
SmsService smsService(SmsProperties smsProperties) {
|
||||
return new TencentSmsServiceImpl(smsProperties);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,11 @@ import java.util.Map;
|
|||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* SMS 相关参数
|
||||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
*/
|
||||
@Data
|
||||
@ConfigurationProperties("plusone.sms")
|
||||
public class SmsProperties {
|
||||
private String region;
|
||||
|
@ -19,33 +16,138 @@ public class SmsProperties {
|
|||
private SmsClientProperties client;
|
||||
private String appId;
|
||||
private Map<String, String> templates;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ConfigurationProperties("plusone.sms.credential")
|
||||
class SmsCredentialProperties {
|
||||
private String secretId;
|
||||
private String secretKey;
|
||||
}
|
||||
public String getRegion() {
|
||||
return region;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ConfigurationProperties("plusone.sms.client")
|
||||
class SmsClientProperties {
|
||||
private String signMethod;
|
||||
private SmsHttpProperties http;
|
||||
}
|
||||
public void setRegion(String region) {
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
@Data
|
||||
@ConfigurationProperties("plusone.sms.client.http")
|
||||
class SmsHttpProperties {
|
||||
private SmsProxyProperties proxy;
|
||||
private String reqMethod;
|
||||
private Integer connTimeout;
|
||||
}
|
||||
public SmsCredentialProperties getCredential() {
|
||||
return credential;
|
||||
}
|
||||
|
||||
public void setCredential(SmsCredentialProperties credential) {
|
||||
this.credential = credential;
|
||||
}
|
||||
|
||||
public SmsClientProperties getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void setClient(SmsClientProperties client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public Map<String, String> getTemplates() {
|
||||
return templates;
|
||||
}
|
||||
|
||||
public void setTemplates(Map<String, String> templates) {
|
||||
this.templates = templates;
|
||||
}
|
||||
|
||||
public static class SmsCredentialProperties {
|
||||
private String secretId;
|
||||
private String secretKey;
|
||||
|
||||
public String getSecretId() {
|
||||
return secretId;
|
||||
}
|
||||
|
||||
public void setSecretId(String secretId) {
|
||||
this.secretId = secretId;
|
||||
}
|
||||
|
||||
public String getSecretKey() {
|
||||
return secretKey;
|
||||
}
|
||||
|
||||
public void setSecretKey(String secretKey) {
|
||||
this.secretKey = secretKey;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SmsClientProperties {
|
||||
private String signMethod;
|
||||
private SmsHttpProperties http;
|
||||
|
||||
public String getSignMethod() {
|
||||
return signMethod;
|
||||
}
|
||||
|
||||
public void setSignMethod(String signMethod) {
|
||||
this.signMethod = signMethod;
|
||||
}
|
||||
|
||||
public SmsHttpProperties getHttp() {
|
||||
return http;
|
||||
}
|
||||
|
||||
public void setHttp(SmsHttpProperties http) {
|
||||
this.http = http;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SmsHttpProperties {
|
||||
private SmsProxyProperties proxy;
|
||||
private String reqMethod;
|
||||
private Integer connTimeout;
|
||||
|
||||
public SmsProxyProperties getProxy() {
|
||||
return proxy;
|
||||
}
|
||||
|
||||
public void setProxy(SmsProxyProperties proxy) {
|
||||
this.proxy = proxy;
|
||||
}
|
||||
|
||||
public String getReqMethod() {
|
||||
return reqMethod;
|
||||
}
|
||||
|
||||
public void setReqMethod(String reqMethod) {
|
||||
this.reqMethod = reqMethod;
|
||||
}
|
||||
|
||||
public Integer getConnTimeout() {
|
||||
return connTimeout;
|
||||
}
|
||||
|
||||
public void setConnTimeout(Integer connTimeout) {
|
||||
this.connTimeout = connTimeout;
|
||||
}
|
||||
}
|
||||
|
||||
public static class SmsProxyProperties {
|
||||
private String host;
|
||||
private Integer port;
|
||||
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public Integer getPort() {
|
||||
return port;
|
||||
}
|
||||
|
||||
public void setPort(Integer port) {
|
||||
this.port = port;
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@ConfigurationProperties("plusone.sms.client.http.proxy")
|
||||
class SmsProxyProperties {
|
||||
private String host;
|
||||
private Integer port;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,9 @@ import org.springframework.stereotype.Service;
|
|||
import lombok.extern.slf4j.Slf4j;
|
||||
import xyz.zhouxy.plusone.constant.ErrorCodeConsts;
|
||||
import xyz.zhouxy.plusone.exception.PlusoneException;
|
||||
import xyz.zhouxy.plusone.sms.SmsProperties.SmsCredentialProperties;
|
||||
import xyz.zhouxy.plusone.sms.SmsProperties.SmsHttpProperties;
|
||||
import xyz.zhouxy.plusone.sms.SmsProperties.SmsProxyProperties;
|
||||
|
||||
/**
|
||||
* 使用腾讯 SMS 服务
|
||||
|
|
|
@ -3,13 +3,12 @@ package xyz.zhouxy.plusone.validator;
|
|||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
|
||||
import xyz.zhouxy.plusone.exception.handler.ExceptionInfoHolderFactory;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class InvalidInputExceptionHandler extends BaseExceptionHandler {
|
||||
|
||||
protected InvalidInputExceptionHandler() {
|
||||
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
|
||||
public InvalidInputExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
|
||||
super(exceptionInfoHolder);
|
||||
set(InvalidInputException.class, InvalidInputException.ERROR_CODE, "无效的用户输入");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
xyz.zhouxy.plusone.sms.PlusoneSmsAutoConfiguration,\
|
||||
xyz.zhouxy.plusone.mail.PlusoneMailAutoConfiguration,\
|
||||
xyz.zhouxy.plusone.oss.FastDFSAutoConfig
|
|
@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
|
|||
import xyz.zhouxy.plusone.constant.RegexConsts;
|
||||
import xyz.zhouxy.plusone.validator.BaseValidator;
|
||||
|
||||
class BaseValidator2Test {
|
||||
class BaseValidatorTest {
|
||||
|
||||
@Test
|
||||
void testValid() {
|
|
@ -1,34 +1,32 @@
|
|||
{
|
||||
"properties": [
|
||||
{
|
||||
"name": "plusone.application.name",
|
||||
"type": "java.lang.String",
|
||||
"description": "A description for 'plusone.application.name'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.server.port",
|
||||
"type": "java.lang.Integer",
|
||||
"description": "A description for 'plusone.server.port'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.debug",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "A description for 'plusone.debug'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.mail.host",
|
||||
"type": "java.lang.String",
|
||||
"description": "A description for 'plusone.mail.host'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.mail.password",
|
||||
"type": "java.lang.String",
|
||||
"description": "A description for 'plusone.mail.password'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.exception.handle-all-exception",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "A description for 'plusone.exception.handle-all-exception'"
|
||||
}
|
||||
]
|
||||
}
|
||||
{"properties": [
|
||||
{
|
||||
"name": "plusone.application.name",
|
||||
"type": "java.lang.String",
|
||||
"description": "A description for 'plusone.application.name'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.server.port",
|
||||
"type": "java.lang.Integer",
|
||||
"description": "A description for 'plusone.server.port'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.debug",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "A description for 'plusone.debug'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.mail.host",
|
||||
"type": "java.lang.String",
|
||||
"description": "A description for 'plusone.mail.host'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.mail.password",
|
||||
"type": "java.lang.String",
|
||||
"description": "A description for 'plusone.mail.password'"
|
||||
},
|
||||
{
|
||||
"name": "plusone.exception.handle-all-exception",
|
||||
"type": "java.lang.Boolean",
|
||||
"description": "A description for 'plusone.exception.handle-all-exception'"
|
||||
}
|
||||
]}
|
||||
|
|
|
@ -50,7 +50,7 @@ plusone:
|
|||
conn-timeout: 60
|
||||
app-id: 1111111111
|
||||
templates:
|
||||
code: 0000000
|
||||
'[code]': 0000000
|
||||
|
||||
# 邮件发送相关参数
|
||||
mail:
|
||||
|
@ -63,7 +63,16 @@ plusone:
|
|||
exception:
|
||||
handle-all-exception: false
|
||||
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
root: debug
|
||||
fastdfs:
|
||||
connect_timeout_in_seconds: 5
|
||||
network_timeout_in_seconds: 30
|
||||
charset: UTF-8
|
||||
http_anti_steal_token: false
|
||||
http_secret_key: FastDFS1234567890
|
||||
http_tracker_http_port: 80
|
||||
tracker_servers: 10.0.11.201:22122,10.0.11.202:22122,10.0.11.203:22122
|
||||
connection_pool:
|
||||
enabled: true
|
||||
max_count_per_entry: 500
|
||||
max_idle_time: 3600
|
||||
max_wait_time_in_ms: 1000
|
||||
|
|
|
@ -6,6 +6,11 @@ plusone:
|
|||
# 邮件发送相关参数
|
||||
mail:
|
||||
subject:
|
||||
code: Plusone
|
||||
'[code]': Plusone
|
||||
template:
|
||||
code: 【Plusone】验证码:%s,10分钟内有效,请勿泄露。
|
||||
'[code]': 【Plusone】验证码:%s,10分钟内有效,请勿泄露。
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
root: info
|
||||
'[xyz.zhouxy.plusone]': debug
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package xyz.zhouxy.plusone;
|
||||
|
||||
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;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import xyz.zhouxy.plusone.oss.FastDFSException;
|
||||
import xyz.zhouxy.plusone.oss.FastDFSUtil;
|
||||
import xyz.zhouxy.plusone.oss.FastDFSUtil.FastDFSFile;
|
||||
|
||||
@SpringBootTest(classes = PlusoneApplication.class)
|
||||
@Slf4j
|
||||
class FastDFSTests {
|
||||
|
||||
@Resource
|
||||
FastDFSUtil fastDFSUtil;
|
||||
|
||||
@Test
|
||||
void testOSS() throws FileNotFoundException, IOException, FastDFSException {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
spring:
|
||||
profiles:
|
||||
active: secret
|
||||
|
||||
plusone:
|
||||
# 邮件发送相关参数
|
||||
mail:
|
||||
subject:
|
||||
'[code]': Plusone
|
||||
template:
|
||||
'[code]': 【Plusone】验证码:%s,10分钟内有效,请勿泄露。
|
||||
# 日志配置
|
||||
logging:
|
||||
level:
|
||||
root: info
|
||||
'[xyz.zhouxy.plusone]': debug
|
|
@ -20,7 +20,6 @@ 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;
|
||||
import xyz.zhouxy.plusone.system.application.service.command.UpdateAccountCommand;
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
import xyz.zhouxy.plusone.util.RestfulResult;
|
||||
|
||||
/**
|
||||
|
@ -77,7 +76,6 @@ public class AccountManagementController {
|
|||
adminAuthLogic.checkLogin();
|
||||
adminAuthLogic.checkPermission("sys-account-details");
|
||||
var accountDetails = service.queryAccountDetails(accountId);
|
||||
AssertResult.nonNull(accountDetails);
|
||||
return success("查询成功", accountDetails);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,18 +21,34 @@ public class AccountLoginException extends PlusoneException {
|
|||
}
|
||||
|
||||
public static AccountLoginException accountNotExistException() {
|
||||
return new AccountLoginException(4030101, "用户账户不存在");
|
||||
return accountNotExistException("用户账户不存在");
|
||||
}
|
||||
|
||||
public static AccountLoginException accountNotExistException(String msg) {
|
||||
return new AccountLoginException(4030101, msg);
|
||||
}
|
||||
|
||||
public static AccountLoginException otpErrorException() {
|
||||
return new AccountLoginException(4030501, "验证码错误");
|
||||
return otpErrorException("验证码错误");
|
||||
}
|
||||
|
||||
public static AccountLoginException otpErrorException(String msg) {
|
||||
return new AccountLoginException(4030501, msg);
|
||||
}
|
||||
|
||||
public static AccountLoginException otpNotExistsException() {
|
||||
return new AccountLoginException(4030502, "验证码不存在或已过期");
|
||||
return otpNotExistsException("验证码不存在或已过期");
|
||||
}
|
||||
|
||||
public static AccountLoginException otpNotExistsException(String msg) {
|
||||
return new AccountLoginException(4030502, msg);
|
||||
}
|
||||
|
||||
public static AccountLoginException passwordErrorException() {
|
||||
return new AccountLoginException(4030200, "用户密码错误");
|
||||
return passwordErrorException("用户密码错误");
|
||||
}
|
||||
|
||||
public static AccountLoginException passwordErrorException(String msg) {
|
||||
return new AccountLoginException(4030200, msg);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,15 +7,14 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
|
|||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||
|
||||
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
|
||||
import xyz.zhouxy.plusone.exception.handler.ExceptionInfoHolderFactory;
|
||||
import xyz.zhouxy.plusone.system.application.exception.AccountLoginException;
|
||||
import xyz.zhouxy.plusone.util.RestfulResult;
|
||||
|
||||
@RestControllerAdvice
|
||||
public class AccountLoginExceptionHandler extends BaseExceptionHandler {
|
||||
|
||||
protected AccountLoginExceptionHandler() {
|
||||
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
|
||||
public AccountLoginExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
|
||||
super(exceptionInfoHolder);
|
||||
}
|
||||
|
||||
@ExceptionHandler({ AccountLoginException.class })
|
||||
|
|
|
@ -15,7 +15,6 @@ import cn.dev33.satoken.exception.SaTokenException;
|
|||
import cn.dev33.satoken.exception.SameTokenInvalidException;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
|
||||
import xyz.zhouxy.plusone.exception.handler.ExceptionInfoHolderFactory;
|
||||
import xyz.zhouxy.plusone.util.RestfulResult;
|
||||
|
||||
/**
|
||||
|
@ -27,8 +26,9 @@ import xyz.zhouxy.plusone.util.RestfulResult;
|
|||
@Slf4j
|
||||
public class SaTokenExceptionHandler extends BaseExceptionHandler {
|
||||
|
||||
public SaTokenExceptionHandler() {
|
||||
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
|
||||
|
||||
public SaTokenExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
|
||||
super(exceptionInfoHolder);
|
||||
set(NotPermissionException.class, 4030103, "会话未能通过权限认证", HttpStatus.FORBIDDEN);
|
||||
set(NotRoleException.class, 4030103, "会话未能通过角色认证", HttpStatus.FORBIDDEN);
|
||||
set(DisableServiceException.class, 4030202, "账号指定服务已被封禁", HttpStatus.FORBIDDEN);
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
package xyz.zhouxy.plusone.system.application.service;
|
||||
|
||||
import xyz.zhouxy.plusone.system.constant.AuthLogic;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
|
@ -10,7 +9,6 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
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;
|
||||
|
@ -19,6 +17,7 @@ import xyz.zhouxy.plusone.system.application.query.result.MenuViewObject;
|
|||
import xyz.zhouxy.plusone.system.application.service.command.ChangePasswordByOtpCommand;
|
||||
import xyz.zhouxy.plusone.system.application.service.command.ChangePasswordCommand;
|
||||
import xyz.zhouxy.plusone.system.application.service.command.ChangePasswordWithoutLoginCommand;
|
||||
import xyz.zhouxy.plusone.system.constant.AuthLogic;
|
||||
import xyz.zhouxy.plusone.system.domain.model.account.Account;
|
||||
import xyz.zhouxy.plusone.system.domain.model.account.AccountRepository;
|
||||
import xyz.zhouxy.plusone.system.domain.model.account.Email;
|
||||
|
@ -34,7 +33,7 @@ import xyz.zhouxy.plusone.validator.InvalidInputException;
|
|||
@Service
|
||||
public class AccountContextService {
|
||||
|
||||
private final static StpLogic adminAuthLogic = AuthLogic.adminAuthLogic;
|
||||
private static final StpLogic adminAuthLogic = AuthLogic.adminAuthLogic;
|
||||
|
||||
@Resource
|
||||
private AccountQueries accountQueries;
|
||||
|
@ -65,7 +64,8 @@ public class AccountContextService {
|
|||
@Transactional
|
||||
public void changePassword(ChangePasswordCommand command) {
|
||||
adminAuthLogic.checkLogin();
|
||||
Account account = accountRepository.find(adminAuthLogic.getLoginIdAsLong());
|
||||
Account account = accountRepository.find(adminAuthLogic.getLoginIdAsLong())
|
||||
.orElseThrow(() -> AccountLoginException.accountNotExistException("当前所登录的账号不存在"));
|
||||
account.checkPassword(command.getPassword());
|
||||
account.changePassword(command.getNewPassword(), command.getPasswordConfirmation());
|
||||
accountRepository.save(account);
|
||||
|
@ -77,9 +77,10 @@ public class AccountContextService {
|
|||
String principal = command.getAccount();
|
||||
Principal emailOrMobilePhone = PrincipalUtil.getEmailOrMobilePhone(principal);
|
||||
|
||||
Account account = emailOrMobilePhone instanceof Email
|
||||
Account account = (emailOrMobilePhone instanceof Email
|
||||
? accountRepository.findByEmail((Email) emailOrMobilePhone)
|
||||
: accountRepository.findByMobilePhone((MobilePhone) emailOrMobilePhone);
|
||||
: accountRepository.findByMobilePhone((MobilePhone) emailOrMobilePhone))
|
||||
.orElseThrow(() -> AccountLoginException.accountNotExistException("当前所登录的账号不存在"));
|
||||
account.checkPassword(command.getOldPassword());
|
||||
account.changePassword(command.getNewPassword(), command.getPasswordConfirmation());
|
||||
accountRepository.save(account);
|
||||
|
@ -90,12 +91,12 @@ public class AccountContextService {
|
|||
public void changePasswordByOtp(ChangePasswordByOtpCommand command) {
|
||||
|
||||
var principal = command.getAccount();
|
||||
Account account = switch (command.getPrincipalType()) {
|
||||
Optional<Account> account = switch (command.getPrincipalType()) {
|
||||
case EMAIL -> accountRepository.findByEmail(Email.of(principal));
|
||||
case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal));
|
||||
default -> throw InvalidInputException.unsupportedPrincipalTypeException("输入邮箱地址或手机号");
|
||||
};
|
||||
Assert.notNull(account, () -> AccountLoginException.accountNotExistException());
|
||||
account.orElseThrow(AccountLoginException::accountNotExistException);
|
||||
|
||||
mailAndSmsVerifyService.checkOtp(principal, command.getOtp());
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.springframework.util.Assert;
|
|||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
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;
|
||||
|
@ -76,16 +77,16 @@ public class AccountManagementService {
|
|||
public void deleteAccounts(List<Long> ids) {
|
||||
Account accountToDelete;
|
||||
for (var id : ids) {
|
||||
accountToDelete = accountRepository.find(id);
|
||||
AssertResult.nonNull(accountToDelete);
|
||||
accountToDelete = accountRepository.find(id)
|
||||
.orElseThrow(() -> new DataNotExistException("该账号不存在"));
|
||||
accountRepository.delete(accountToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateAccountInfo(Long id, @Valid UpdateAccountCommand command) {
|
||||
Assert.isTrue(Objects.equals(id, command.getId()), "参数错误: id 不匹配");
|
||||
Account account = accountRepository.find(id);
|
||||
AssertResult.nonNull(account, "该账号不存在");
|
||||
Account account = accountRepository.find(id)
|
||||
.orElseThrow(() -> new DataNotExistException("该账号不存在"));
|
||||
account.setAccountInfo(command.getNickname(), command.getAvatar(), command.getSex());
|
||||
account.setUpdatedBy(adminAuthLogic.getLoginIdAsLong());
|
||||
accountRepository.save(account);
|
||||
|
@ -96,6 +97,13 @@ public class AccountManagementService {
|
|||
return accountQueries.queryAccountOverviewPage(queryParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询账号详细信息,如果查不到将抛出 {@link DataNotExistException}。
|
||||
*
|
||||
* @param accountId 账号 id
|
||||
* @return 账号信息
|
||||
* @throws DataNotExistException 查询不到数据时抛出异常
|
||||
*/
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public AccountDetails queryAccountDetails(@PathVariable("accountId") Long accountId) {
|
||||
var accountDetails = accountQueries.queryAccountDetails(accountId);
|
||||
|
|
|
@ -44,14 +44,13 @@ public class AdminLoginService {
|
|||
@ValidateDto
|
||||
public LoginInfoViewObject loginByPassword(LoginByPasswordCommand command) {
|
||||
var principal = command.getPrincipal();
|
||||
Account account = switch (command.getPrincipalType()) {
|
||||
Account account = (switch (command.getPrincipalType()) {
|
||||
case USERNAME -> accountRepository.findByUsername(Username.of(principal));
|
||||
case EMAIL -> accountRepository.findByEmail(Email.of(principal));
|
||||
case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal));
|
||||
};
|
||||
Assert.notNull(account, () -> AccountLoginException.accountNotExistException());
|
||||
}).orElseThrow(AccountLoginException::accountNotExistException);
|
||||
var isPasswordCorrect = account.checkPassword(command.getPassword());
|
||||
Assert.isTrue(isPasswordCorrect, () -> AccountLoginException.passwordErrorException());
|
||||
Assert.isTrue(isPasswordCorrect, AccountLoginException::passwordErrorException);
|
||||
|
||||
adminAuthLogic.login(account.getId().orElseThrow(), command.isRememberMe());
|
||||
var accountDetails = accountQueries.queryAccountDetails(account.getId().orElseThrow());
|
||||
|
@ -61,12 +60,11 @@ public class AdminLoginService {
|
|||
@ValidateDto
|
||||
public LoginInfoViewObject loginByOtp(LoginByOtpCommand command) {
|
||||
var principal = command.getPrincipal();
|
||||
Account account = switch (command.getPrincipalType()) {
|
||||
Account account = (switch (command.getPrincipalType()) {
|
||||
case EMAIL -> accountRepository.findByEmail(Email.of(principal));
|
||||
case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal));
|
||||
default -> throw InvalidInputException.unsupportedPrincipalTypeException("输入邮箱地址或手机号");
|
||||
};
|
||||
Assert.notNull(account, () -> AccountLoginException.accountNotExistException());
|
||||
}).orElseThrow(AccountLoginException::accountNotExistException);
|
||||
|
||||
mailAndSmsVerifyService.checkOtp(principal, command.getOtp());
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.transaction.annotation.Propagation;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
import xyz.zhouxy.plusone.system.application.query.DictQueries;
|
||||
import xyz.zhouxy.plusone.system.application.query.params.DictQueryParams;
|
||||
import xyz.zhouxy.plusone.system.application.query.result.DictOverview;
|
||||
|
@ -45,21 +46,21 @@ public class DictManagementService {
|
|||
public void deleteDicts(List<Long> ids) {
|
||||
Dict dictToDelete;
|
||||
for (Long id : ids) {
|
||||
dictToDelete = dictRepository.find(id);
|
||||
dictToDelete = dictRepository.find(id).orElseThrow(DataNotExistException::new);
|
||||
dictRepository.delete(dictToDelete);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateDict(Long id, @Valid UpdateDictCommand command) {
|
||||
Assert.isTrue(Objects.equals(id, command.getId()), "id 不匹配");
|
||||
Dict dictToUpdate = dictRepository.find(command.getId());
|
||||
Dict dictToUpdate = dictRepository.find(command.getId()).orElseThrow(DataNotExistException::new);
|
||||
dictToUpdate.updateDict(command.getDictType(), command.getDictLabel(), command.getKeyLabelMap());
|
||||
dictRepository.save(dictToUpdate);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public Dict findDictDetails(Long dictId) {
|
||||
return dictRepository.find(dictId);
|
||||
return dictRepository.find(dictId).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
import org.springframework.util.Assert;
|
||||
|
||||
import xyz.zhouxy.plusone.domain.IWithOrderNumber;
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
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;
|
||||
|
@ -22,7 +23,6 @@ import xyz.zhouxy.plusone.system.domain.model.menu.Menu;
|
|||
import xyz.zhouxy.plusone.system.domain.model.menu.MenuConstructor;
|
||||
import xyz.zhouxy.plusone.system.domain.model.menu.MenuRepository;
|
||||
import xyz.zhouxy.plusone.system.domain.service.MenuService;
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
|
||||
/**
|
||||
* 菜单管理
|
||||
|
@ -88,15 +88,16 @@ public class MenuManagementService {
|
|||
|
||||
// ==================== delete ====================
|
||||
public void deleteMenu(Long id) {
|
||||
Menu menuToDelete = menuRepository.find(id);
|
||||
AssertResult.nonNull(menuToDelete);
|
||||
Menu menuToDelete = menuRepository.find(id)
|
||||
.orElseThrow(DataNotExistException::new);
|
||||
menuRepository.delete(menuToDelete);
|
||||
}
|
||||
|
||||
// ==================== update ====================
|
||||
public void updateMenu(Long id, @Valid UpdateMenuCommand command) {
|
||||
Assert.isTrue(Objects.equals(id, command.getId()), "id 不匹配");
|
||||
Menu menuToUpdate = menuRepository.find(command.getId());
|
||||
Menu menuToUpdate = menuRepository.find(command.getId())
|
||||
.orElseThrow(DataNotExistException::new);
|
||||
menuToUpdate.updateMenuInfo(
|
||||
command.getMenuType(),
|
||||
command.getParentId(),
|
||||
|
@ -118,7 +119,7 @@ public class MenuManagementService {
|
|||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public MenuViewObject findById(Long id) {
|
||||
var menu = menuRepository.find(id);
|
||||
return MenuViewObject.of(menu);
|
||||
return MenuViewObject.of(menu.orElseThrow(DataNotExistException::new));
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.springframework.stereotype.Service;
|
|||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
import xyz.zhouxy.plusone.system.application.query.RoleQueries;
|
||||
import xyz.zhouxy.plusone.system.application.query.params.RoleQueryParams;
|
||||
import xyz.zhouxy.plusone.system.application.query.result.RoleOverview;
|
||||
|
@ -62,7 +63,7 @@ public class RoleManagementService {
|
|||
|
||||
public void updateRole(@Valid UpdateRoleCommand command) {
|
||||
Long roleId = command.getId();
|
||||
Role roleToUpdate = _roleRepository.find(roleId);
|
||||
Role roleToUpdate = _roleRepository.find(roleId).orElseThrow(DataNotExistException::new);
|
||||
roleToUpdate.update(
|
||||
command.getName(),
|
||||
command.getIdentifier(),
|
||||
|
@ -74,7 +75,7 @@ public class RoleManagementService {
|
|||
}
|
||||
|
||||
public void delete(Long id) {
|
||||
Role role = _roleRepository.find(id);
|
||||
Role role = _roleRepository.find(id).orElseThrow(DataNotExistException::new);
|
||||
_roleRepository.delete(role);
|
||||
}
|
||||
|
||||
|
@ -85,7 +86,7 @@ public class RoleManagementService {
|
|||
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
public Role findById(Long id) {
|
||||
return _roleRepository.find(id);
|
||||
return _roleRepository.find(id).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Transactional(propagation = Propagation.SUPPORTS)
|
||||
|
|
|
@ -27,7 +27,7 @@ public class AccountCreated extends DomainEvent {
|
|||
|
||||
public AccountCreated(Account account) {
|
||||
this.username = account.getUsername();
|
||||
this.email = account.getEmail();
|
||||
this.mobilePhone = account.getMobilePhone();
|
||||
this.email = account.getEmail().orElse(null);
|
||||
this.mobilePhone = account.getMobilePhone().orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public class AccountLocked extends DomainEvent {
|
|||
|
||||
public AccountLocked(Account account) {
|
||||
this.username = account.getUsername();
|
||||
this.email = account.getEmail();
|
||||
this.mobilePhone = account.getMobilePhone();
|
||||
this.email = account.getEmail().orElse(null);
|
||||
this.mobilePhone = account.getMobilePhone().orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,8 +27,8 @@ public class AccountPasswordChanged extends DomainEvent {
|
|||
|
||||
public AccountPasswordChanged(Account account) {
|
||||
this.username = account.getUsername();
|
||||
this.email = account.getEmail();
|
||||
this.mobilePhone = account.getMobilePhone();
|
||||
this.email = account.getEmail().orElse(null);
|
||||
this.mobilePhone = account.getMobilePhone().orElse(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,6 +25,6 @@ public class EmailChanged extends DomainEvent {
|
|||
|
||||
public EmailChanged(Account account) {
|
||||
this.username = account.getUsername();
|
||||
this.email = account.getEmail();
|
||||
this.email = account.getEmail().orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,6 +25,6 @@ public class MobilePhoneChanged extends DomainEvent {
|
|||
|
||||
public MobilePhoneChanged(Account account) {
|
||||
this.username = account.getUsername();
|
||||
this.mobilePhone = account.getMobilePhone();
|
||||
this.mobilePhone = account.getMobilePhone().orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ public class UsernameChanged extends DomainEvent {
|
|||
|
||||
public UsernameChanged(Account account) {
|
||||
this.username = account.getUsername();
|
||||
this.email = account.getEmail();
|
||||
this.mobilePhone = account.getMobilePhone();
|
||||
this.email = account.getEmail().orElse(null);
|
||||
this.mobilePhone = account.getMobilePhone().orElse(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,6 @@ import java.util.HashSet;
|
|||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import xyz.zhouxy.plusone.domain.AggregateRoot;
|
||||
import xyz.zhouxy.plusone.domain.IWithVersion;
|
||||
|
@ -30,17 +28,17 @@ public class Account extends AggregateRoot<Long> implements IWithVersion {
|
|||
|
||||
// ===================== 字段 ====================
|
||||
private Long id;
|
||||
private @Getter Username username;
|
||||
private @Getter Email email;
|
||||
private @Getter MobilePhone mobilePhone;
|
||||
private Username username;
|
||||
private Email email;
|
||||
private MobilePhone mobilePhone;
|
||||
private Password password;
|
||||
private @Getter AccountStatus status;
|
||||
private @Getter AccountInfo accountInfo;
|
||||
private AccountStatus status;
|
||||
private AccountInfo accountInfo;
|
||||
private Set<Long> roleRefs = new HashSet<>();
|
||||
|
||||
private @Getter Long createdBy;
|
||||
private @Getter @Setter Long updatedBy;
|
||||
private @Getter long version;
|
||||
private Long createdBy;
|
||||
private Long updatedBy;
|
||||
private long version;
|
||||
|
||||
public void setUsername(Username username) {
|
||||
this.username = username;
|
||||
|
@ -223,11 +221,48 @@ public class Account extends AggregateRoot<Long> implements IWithVersion {
|
|||
return Optional.ofNullable(id);
|
||||
}
|
||||
|
||||
public Set<Long> getRoleIds() {
|
||||
return Set.copyOf(this.roleRefs);
|
||||
public Username getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public Optional<Email> getEmail() {
|
||||
return Optional.ofNullable(email);
|
||||
}
|
||||
|
||||
public Optional<MobilePhone> getMobilePhone() {
|
||||
return Optional.ofNullable(mobilePhone);
|
||||
}
|
||||
|
||||
Password getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public AccountStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public AccountInfo getAccountInfo() {
|
||||
return accountInfo;
|
||||
}
|
||||
|
||||
public Set<Long> getRoleIds() {
|
||||
return Set.copyOf(roleRefs);
|
||||
}
|
||||
|
||||
public Optional<Long> getCreatedBy() {
|
||||
return Optional.ofNullable(createdBy);
|
||||
}
|
||||
|
||||
public Optional<Long> getUpdatedBy() {
|
||||
return Optional.ofNullable(updatedBy);
|
||||
}
|
||||
|
||||
public void setUpdatedBy(long updatedBy) {
|
||||
this.updatedBy = updatedBy;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getVersion() {
|
||||
return this.version;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package xyz.zhouxy.plusone.system.domain.model.account;
|
|||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.ToString;
|
||||
|
@ -13,13 +14,12 @@ import xyz.zhouxy.plusone.domain.IValueObject;
|
|||
*
|
||||
* @author <a href="https://gitee.com/zhouxy108">ZhouXY</a>
|
||||
*/
|
||||
@Getter
|
||||
@ToString
|
||||
public class AccountInfo implements IValueObject {
|
||||
|
||||
private final Nickname nickname;
|
||||
private final URL avatar;
|
||||
private final Sex sex;
|
||||
private final @Getter Sex sex;
|
||||
|
||||
private AccountInfo(Nickname nickname, URL avatar, Sex sex) {
|
||||
this.nickname = nickname;
|
||||
|
@ -40,4 +40,12 @@ public class AccountInfo implements IValueObject {
|
|||
}
|
||||
return new AccountInfo(Nickname.ofNullable(nickname), avatarURL, sex);
|
||||
}
|
||||
|
||||
public Optional<Nickname> getNickname() {
|
||||
return Optional.ofNullable(nickname);
|
||||
}
|
||||
|
||||
public Optional<URL> getAvatar() {
|
||||
return Optional.ofNullable(avatar);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package xyz.zhouxy.plusone.system.domain.model.account;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import xyz.zhouxy.plusone.domain.IRepository;
|
||||
|
||||
|
@ -14,11 +15,11 @@ public interface AccountRepository extends IRepository<Account, Long> {
|
|||
|
||||
Collection<Account> findByRoleId(Long roleId);
|
||||
|
||||
Account findByEmail(Email email);
|
||||
Optional<Account> findByEmail(Email email);
|
||||
|
||||
Account findByMobilePhone(MobilePhone mobilePhone);
|
||||
Optional<Account> findByMobilePhone(MobilePhone mobilePhone);
|
||||
|
||||
Account findByUsername(Username username);
|
||||
Optional<Account> findByUsername(Username username);
|
||||
|
||||
boolean existsUsername(Username username);
|
||||
|
||||
|
|
|
@ -6,7 +6,6 @@ import java.util.HashSet;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import lombok.ToString;
|
||||
import xyz.zhouxy.plusone.domain.AggregateRoot;
|
||||
|
@ -115,7 +114,7 @@ public class Dict extends AggregateRoot<Long> implements IWithLabel, IWithVersio
|
|||
}
|
||||
|
||||
public Set<DictValue> getValues() {
|
||||
return this.values.values().stream().collect(Collectors.toSet());
|
||||
return Set.copyOf(this.values.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -4,7 +4,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
@ -14,8 +14,8 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
|||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import static xyz.zhouxy.plusone.domain.ValidatableStringRecord.getValueOrNull;
|
||||
import xyz.zhouxy.plusone.jdbc.JdbcRepositorySupport;
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
|
||||
/**
|
||||
* AccountRepository 实现类
|
||||
|
@ -41,11 +41,11 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
new MapSqlParameterSource()
|
||||
.addValue("id", entity.getId().orElseThrow())
|
||||
.addValue("version", entity.getVersion()));
|
||||
AssertResult.update(i, 1);
|
||||
assertUpdateOneRow(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final Account doFindById(@Nonnull Long id) {
|
||||
protected final Optional<Account> doFindById(@Nonnull Long id) {
|
||||
return queryForObject("""
|
||||
SELECT
|
||||
id, email, mobile_phone, username, "password", salt, avatar, sex, nickname, status,
|
||||
|
@ -53,11 +53,11 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
FROM sys_account
|
||||
WHERE id = :id AND deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("id", id));
|
||||
"id", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account findByEmail(Email email) {
|
||||
public Optional<Account> findByEmail(Email email) {
|
||||
return queryForObject("""
|
||||
SELECT
|
||||
id, email, mobile_phone, username, "password", salt, avatar, sex, nickname, status,
|
||||
|
@ -65,11 +65,11 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
FROM sys_account
|
||||
WHERE email = :email AND deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("email", email.value()));
|
||||
"email", email.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account findByMobilePhone(MobilePhone mobilePhone) {
|
||||
public Optional<Account> findByMobilePhone(MobilePhone mobilePhone) {
|
||||
return queryForObject("""
|
||||
SELECT
|
||||
id, email, mobile_phone, username, "password", salt, avatar, sex, nickname, status,
|
||||
|
@ -77,11 +77,11 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
FROM sys_account
|
||||
WHERE mobile_phone = :mobilePhone AND deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("mobilePhone", mobilePhone.value()));
|
||||
"mobilePhone", mobilePhone.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account findByUsername(Username username) {
|
||||
public Optional<Account> findByUsername(Username username) {
|
||||
return queryForObject("""
|
||||
SELECT
|
||||
id, email, mobile_phone, username, "password", salt, avatar, sex, nickname, status,
|
||||
|
@ -89,31 +89,33 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
FROM sys_account
|
||||
WHERE username = :username AND deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("username", username.value()));
|
||||
"username", username.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Long id) {
|
||||
return queryExists("SELECT 1 FROM sys_account WHERE id = :id AND deleted = 0 LIMIT 1",
|
||||
new MapSqlParameterSource("id", id));
|
||||
return queryExists("SELECT EXISTS (SELECT 1 FROM sys_account WHERE id = :id AND deleted = 0 LIMIT 1)",
|
||||
"id", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsUsername(Username username) {
|
||||
return queryExists("SELECT 1 FROM sys_account WHERE username = :username AND deleted = 0 LIMIT 1",
|
||||
new MapSqlParameterSource("username", username.value()));
|
||||
return queryExists(
|
||||
"SELECT EXISTS (SELECT 1 FROM sys_account WHERE username = :username AND deleted = 0 LIMIT 1)",
|
||||
"username", username.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsEmail(Email email) {
|
||||
return queryExists("SELECT 1 FROM sys_account WHERE email = :email AND deleted = 0 LIMIT 1",
|
||||
new MapSqlParameterSource("email", email.value()));
|
||||
return queryExists("SELECT EXISTS (SELECT 1 FROM sys_account WHERE email = :email AND deleted = 0 LIMIT 1)",
|
||||
"email", email.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean existsMobilePhone(MobilePhone mobilePhone) {
|
||||
return queryExists("SELECT 1 FROM sys_account WHERE mobile_phone = :mobile_phone AND deleted = 0 LIMIT 1",
|
||||
new MapSqlParameterSource("mobile_phone", mobilePhone.value()));
|
||||
return queryExists(
|
||||
"SELECT EXISTS (SELECT 1 FROM sys_account WHERE mobile_phone = :mobile_phone AND deleted = 0 LIMIT 1)",
|
||||
"mobile_phone", mobilePhone.value());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,7 +129,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
LEFT JOIN sys_account_role ar ON a.id = ar.account_id
|
||||
WHERE ar.role_id = :roleId AND a.deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("roleId", roleId));
|
||||
"roleId", roleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -142,9 +144,9 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
:createdBy, :createTime)
|
||||
""",
|
||||
generateParamSource(id, entity));
|
||||
AssertResult.update(i, 1);
|
||||
assertUpdateOneRow(i);
|
||||
this.accountRoleDAO.insertAccountRoleRefs(id, entity.getRoleIds());
|
||||
return entity;
|
||||
return find(id).orElseThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -166,9 +168,9 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
WHERE id = :id AND deleted = 0 AND "version" = :version
|
||||
""",
|
||||
generateParamSource(entity));
|
||||
AssertResult.update(i, 1);
|
||||
assertUpdateOneRow(i);
|
||||
this.accountRoleDAO.saveAccountRoleRefs(entity);
|
||||
return entity;
|
||||
return find(entity.getId().orElseThrow()).orElseThrow();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -198,16 +200,14 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
|
|||
AccountInfo accountInfo = entity.getAccountInfo();
|
||||
return new MapSqlParameterSource()
|
||||
.addValue("id", id)
|
||||
.addValue("email", Objects.nonNull(entity.getEmail()) ? entity.getEmail().value() : null)
|
||||
.addValue("mobilePhone",
|
||||
Objects.nonNull(entity.getMobilePhone()) ? entity.getMobilePhone().value() : null)
|
||||
.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().getValue())
|
||||
.addValue("nickname",
|
||||
Objects.nonNull(accountInfo.getNickname()) ? accountInfo.getNickname().value() : null)
|
||||
.addValue("nickname", getValueOrNull(accountInfo.getNickname()))
|
||||
.addValue("status", entity.getStatus().getValue())
|
||||
.addValue("createdBy", entity.getCreatedBy())
|
||||
.addValue("createTime", now)
|
||||
|
|
|
@ -1,47 +1,43 @@
|
|||
package xyz.zhouxy.plusone.system.domain.model.account;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
import xyz.zhouxy.plusone.util.NumberUtil;
|
||||
import xyz.zhouxy.plusone.jdbc.PlusoneJdbcDaoSupport;
|
||||
|
||||
class AccountRoleRefDAO {
|
||||
private final NamedParameterJdbcTemplate jdbc;
|
||||
class AccountRoleRefDAO extends PlusoneJdbcDaoSupport {
|
||||
|
||||
AccountRoleRefDAO(NamedParameterJdbcTemplate jdbc) {
|
||||
this.jdbc = jdbc;
|
||||
AccountRoleRefDAO(@Nonnull NamedParameterJdbcTemplate jdbc) {
|
||||
super(jdbc);
|
||||
}
|
||||
|
||||
Set<Long> selectRoleIdsByAccountId(Long accountId) {
|
||||
List<Long> roleRefs = this.jdbc.queryForList("""
|
||||
return queryForStream("""
|
||||
SELECT r.id FROM sys_role r RIGHT JOIN sys_account_role ar ON r.id = ar.role_id
|
||||
WHERE r.deleted = 0 AND ar.account_id = :accountId;
|
||||
""",
|
||||
new MapSqlParameterSource("accountId", accountId),
|
||||
Long.TYPE);
|
||||
return new HashSet<>(roleRefs);
|
||||
"accountId", accountId,
|
||||
Long.TYPE)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
void clearAccountRoleRefs(Account entity) {
|
||||
var param = new MapSqlParameterSource("accountId", entity.getId().orElseThrow());
|
||||
this.jdbc.update("DELETE FROM sys_account_role WHERE account_id = :accountId", param);
|
||||
update("DELETE FROM sys_account_role WHERE account_id = :accountId", "accountId", entity.getId().orElseThrow());
|
||||
}
|
||||
|
||||
void insertAccountRoleRefs(Long accountId, Set<Long> roleRefs) {
|
||||
String sql = "INSERT INTO sys_account_role (account_id, role_id) VALUES (:accountId, :roleId)";
|
||||
MapSqlParameterSource[] batchArgs = roleRefs
|
||||
.stream()
|
||||
.map((Long roleId) -> new MapSqlParameterSource()
|
||||
int i = batchUpdate(
|
||||
"INSERT INTO sys_account_role (account_id, role_id) VALUES (:accountId, :roleId)",
|
||||
roleRefs,
|
||||
(Long roleId) -> new MapSqlParameterSource()
|
||||
.addValue("accountId", accountId)
|
||||
.addValue("roleId", roleId))
|
||||
.toArray(MapSqlParameterSource[]::new);
|
||||
int[] i = this.jdbc.batchUpdate(sql, batchArgs);
|
||||
AssertResult.update(roleRefs.size(), NumberUtil.sum(i));
|
||||
.addValue("roleId", roleId));
|
||||
assertResultEquals(i, roleRefs.size());
|
||||
}
|
||||
|
||||
void saveAccountRoleRefs(Account entity) {
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
@ -15,6 +16,7 @@ import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
|||
import org.springframework.stereotype.Repository;
|
||||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
import xyz.zhouxy.plusone.jdbc.JdbcRepositorySupport;
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
|
||||
|
@ -34,9 +36,9 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public Dict doFindById(@Nonnull Long id) {
|
||||
public Optional<Dict> doFindById(@Nonnull Long id) {
|
||||
return queryForObject("SELECT id, dict_type, dict_label, \"version\" WHERE id = :id AND deleted = 0",
|
||||
new MapSqlParameterSource("id", id));
|
||||
"id", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -47,9 +49,9 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
|
|||
VALUES (:dictType, :dictLabel, :createTime, :createdBy)
|
||||
""",
|
||||
generateParamSource(id, entity));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
this.dictValueDAO.insertDictValues(id, entity);
|
||||
return find(id);
|
||||
return find(id).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -64,9 +66,9 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
|
|||
WHERE id = :id AND deleted = 0 AND "version" = :version
|
||||
""",
|
||||
generateParamSource(entity));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
this.dictValueDAO.updateDictValues(entity);
|
||||
return find(entity.getId().orElseThrow());
|
||||
return find(entity.getId().orElseThrow()).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -76,12 +78,12 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
|
|||
WHERE id = :id AND deleted = 0 AND "version" = :version
|
||||
""",
|
||||
generateParamSource(entity));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Long id) {
|
||||
return queryExists("SELECT 1 FROM sys_dict_type WHERE id = :id AND deleted = 0 LIMIT 1",
|
||||
return queryExists("SELECT EXISTS (SELECT 1 FROM sys_dict_type WHERE id = :id AND deleted = 0 LIMIT 1)",
|
||||
new MapSqlParameterSource("id", id));
|
||||
}
|
||||
|
||||
|
|
|
@ -4,48 +4,45 @@ import java.util.Objects;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
import xyz.zhouxy.plusone.util.NumberUtil;
|
||||
import xyz.zhouxy.plusone.jdbc.PlusoneJdbcDaoSupport;
|
||||
|
||||
class DictValueDAO {
|
||||
private final NamedParameterJdbcTemplate jdbc;
|
||||
class DictValueDAO extends PlusoneJdbcDaoSupport {
|
||||
|
||||
DictValueDAO(NamedParameterJdbcTemplate jdbc) {
|
||||
this.jdbc = jdbc;
|
||||
DictValueDAO(@Nonnull NamedParameterJdbcTemplate jdbc) {
|
||||
super(jdbc);
|
||||
}
|
||||
|
||||
void updateDictValues(Dict entity) {
|
||||
MapSqlParameterSource deleteParam = new MapSqlParameterSource("dictType", entity.getId().orElseThrow());
|
||||
this.jdbc.update("DELETE FROM sys_dict_value WHERE dict_type = :dictType", deleteParam);
|
||||
update("DELETE FROM sys_dict_value WHERE dict_type = :dictType",
|
||||
"dictType", entity.getId().orElseThrow());
|
||||
int i = insertDictValues(entity.getId().orElseThrow(), entity);
|
||||
AssertResult.update(i, entity.count());
|
||||
assertResultEquals(i, entity.count());
|
||||
}
|
||||
|
||||
int insertDictValues(Long dictId, Dict entity) {
|
||||
if (Objects.isNull(dictId) || Objects.isNull(entity) || CollectionUtils.isEmpty(entity.getValues())) {
|
||||
return 0;
|
||||
}
|
||||
int[] i = this.jdbc.batchUpdate(
|
||||
return batchUpdate(
|
||||
"INSERT INTO sys_dict_value (dict_type, dict_key, label) VALUES (:dictType, :dictKey, :label)",
|
||||
entity.getValues().stream()
|
||||
.map(dictValue -> new MapSqlParameterSource()
|
||||
.addValue("dictType", dictId)
|
||||
.addValue("dictKey", dictValue.getKey())
|
||||
.addValue("label", dictValue.getLabel()))
|
||||
.toArray(SqlParameterSource[]::new));
|
||||
return NumberUtil.sum(i);
|
||||
entity.getValues(),
|
||||
dictValue -> new MapSqlParameterSource()
|
||||
.addValue("dictType", dictId)
|
||||
.addValue("dictKey", dictValue.getKey())
|
||||
.addValue("label", dictValue.getLabel()));
|
||||
}
|
||||
|
||||
Set<DictValue> selectDictValuesByDictId(long id) {
|
||||
return this.jdbc.queryForStream("""
|
||||
SELECT dict_key, label FROM sys_dict_value WHERE dict_type = :dictType
|
||||
""", new MapSqlParameterSource("dictType", id),
|
||||
(rs, rowNum) -> DictValue.of(rs.getInt("dict_key"), rs.getString("label")))
|
||||
return queryForStream(
|
||||
"SELECT dict_key, label FROM sys_dict_value WHERE dict_type = :dictType",
|
||||
"dictType", id,
|
||||
(rs, i) -> DictValue.of(rs.getInt("dict_key"), rs.getString("label")))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,15 +39,14 @@ class ActionDAO extends JdbcEntityDaoSupport<Action, Long> {
|
|||
.map(action -> action.getId().orElseThrow())
|
||||
.collect(Collectors.toSet());
|
||||
if (!ids.isEmpty()) {
|
||||
this.jdbc.update(
|
||||
"UPDATE sys_action SET deleted = id WHERE resource = :resource AND id NOT IN (:ids) AND deleted = 0",
|
||||
update("UPDATE sys_action SET deleted = id WHERE resource = :resource AND id NOT IN (:ids) AND deleted = 0",
|
||||
new MapSqlParameterSource()
|
||||
.addValue("resource", menuId)
|
||||
.addValue("ids", ids));
|
||||
}
|
||||
|
||||
// 更新存在的数据
|
||||
this.jdbc.batchUpdate("""
|
||||
batchUpdate("""
|
||||
UPDATE sys_action
|
||||
SET resource = :resource,
|
||||
identifier = :identifier,
|
||||
|
@ -56,22 +55,18 @@ class ActionDAO extends JdbcEntityDaoSupport<Action, Long> {
|
|||
updated_by = :updatedBy
|
||||
WHERE id = :id AND deleted = 0
|
||||
""",
|
||||
actions.stream()
|
||||
.filter(action -> action.getId().isPresent())
|
||||
.map(action -> generateParamSource(menuId, action))
|
||||
.toArray(MapSqlParameterSource[]::new));
|
||||
actions.stream().filter(action -> action.getId().isPresent()),
|
||||
action -> generateParamSource(menuId, action));
|
||||
|
||||
// 插入新添加的数据
|
||||
this.jdbc.batchUpdate("""
|
||||
batchUpdate("""
|
||||
INSERT INTO sys_action
|
||||
(id, resource, identifier, "label", create_time, created_by)
|
||||
VALUES
|
||||
(:id, :resource, :identifier, :label, :createTime, :createdBy)
|
||||
""",
|
||||
actions.stream()
|
||||
.filter(action -> action.getId().isEmpty())
|
||||
.map(action -> generateParamSource(menuId, IdUtil.getSnowflakeNextId(), action))
|
||||
.toArray(MapSqlParameterSource[]::new));
|
||||
actions.stream().filter(action -> action.getId().isEmpty()),
|
||||
action -> generateParamSource(menuId, IdUtil.getSnowflakeNextId(), action));
|
||||
}
|
||||
|
||||
List<Action> selectActionsByMenuId(long menuId) {
|
||||
|
@ -80,7 +75,8 @@ class ActionDAO extends JdbcEntityDaoSupport<Action, Long> {
|
|||
FROM sys_action a
|
||||
JOIN (SELECT id, resource FROM sys_menu WHERE id = :menuId AND deleted = 0) m ON a.resource = m.id
|
||||
WHERE a.deleted = 0
|
||||
""", new MapSqlParameterSource("menuId", menuId));
|
||||
""",
|
||||
"menuId", menuId);
|
||||
}
|
||||
|
||||
Collection<Action> selectActionsByIdIn(Collection<Long> actionIds) {
|
||||
|
@ -92,7 +88,8 @@ class ActionDAO extends JdbcEntityDaoSupport<Action, Long> {
|
|||
FROM sys_action a
|
||||
LEFT JOIN sys_menu m ON a.resource = m.id
|
||||
WHERE a.id IN (:actionIds) AND a.deleted = 0
|
||||
""", new MapSqlParameterSource("actionIds", actionIds));
|
||||
""",
|
||||
"actionIds", actionIds);
|
||||
}
|
||||
|
||||
private SqlParameterSource generateParamSource(Long menuId, Action action) {
|
||||
|
|
|
@ -8,6 +8,7 @@ import java.time.LocalDateTime;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
@ -17,6 +18,7 @@ import org.springframework.stereotype.Repository;
|
|||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import xyz.zhouxy.plusone.constant.EntityStatus;
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
import xyz.zhouxy.plusone.jdbc.JdbcRepositorySupport;
|
||||
import xyz.zhouxy.plusone.system.domain.model.menu.Menu.MenuType;
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
|
@ -38,7 +40,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
protected final Menu doFindById(@Nonnull Long id) {
|
||||
protected final Optional<Menu> doFindById(@Nonnull Long id) {
|
||||
return queryForObject("""
|
||||
SELECT
|
||||
id, parent_id, "type", "name", "path", title, icon, hidden, order_number, status, remarks,
|
||||
|
@ -46,7 +48,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
|
|||
FROM sys_menu
|
||||
WHERE id = :id AND deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("id", id));
|
||||
"id", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -62,9 +64,9 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
|
|||
""";
|
||||
MapSqlParameterSource paramSource = generateParamSource(id, entity);
|
||||
int i = update(sql, paramSource);
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
this.actionDAO.saveActions(id, entity.getActions());
|
||||
return entity;
|
||||
return find(id).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -92,12 +94,12 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
|
|||
|
||||
// 更新菜单
|
||||
int i = update(sql, generateParamSource(entity));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
|
||||
// 保存权限
|
||||
Long id = entity.getId().orElseThrow();
|
||||
this.actionDAO.saveActions(id, entity.getActions());
|
||||
return entity;
|
||||
return find(entity.getId().orElseThrow()).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -108,13 +110,13 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
|
|||
""",
|
||||
new MapSqlParameterSource("id", entity.getId().orElseThrow())
|
||||
.addValue("version", entity.getVersion()));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Long id) {
|
||||
return queryExists("SELECT 1 FROM sys_menu WHERE id = :id AND deleted = 0 LIMIT 1",
|
||||
new MapSqlParameterSource("id", id));
|
||||
return queryExists("SELECT EXISTS (SELECT 1 FROM sys_menu WHERE id = :id AND deleted = 0 LIMIT 1)",
|
||||
"id", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -129,7 +131,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
|
|||
FROM sys_menu
|
||||
WHERE id IN (:ids) AND deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("ids", ids));
|
||||
"ids", ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -147,7 +149,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
|
|||
LEFT JOIN sys_role_menu AS rm ON m.id = rm.menu_id
|
||||
WHERE rm.role_id = :roleId AND r.deleted = 0
|
||||
""",
|
||||
new MapSqlParameterSource("roleId", roleId));
|
||||
"roleId", roleId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -3,43 +3,38 @@ package xyz.zhouxy.plusone.system.domain.model.role;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
import xyz.zhouxy.plusone.util.NumberUtil;
|
||||
import xyz.zhouxy.plusone.jdbc.PlusoneJdbcDaoSupport;
|
||||
|
||||
class RoleMenuRefDAO {
|
||||
class RoleMenuRefDAO extends PlusoneJdbcDaoSupport {
|
||||
|
||||
private final NamedParameterJdbcTemplate jdbc;
|
||||
|
||||
public RoleMenuRefDAO(NamedParameterJdbcTemplate jdbc) {
|
||||
this.jdbc = jdbc;
|
||||
public RoleMenuRefDAO(@Nonnull NamedParameterJdbcTemplate jdbc) {
|
||||
super(jdbc);
|
||||
}
|
||||
|
||||
Set<MenuRef> selectMenuRefsByRoleId(long roleId) {
|
||||
return this.jdbc.queryForList("SELECT menu_id FROM sys_role_menu WHERE role_id = :roleId",
|
||||
new MapSqlParameterSource("roleId", roleId),
|
||||
return queryForStream("SELECT menu_id FROM sys_role_menu WHERE role_id = :roleId",
|
||||
"roleId", roleId,
|
||||
Long.TYPE)
|
||||
.stream()
|
||||
.map(MenuRef::of)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
void clearRoleMenuRefs(Role entity) {
|
||||
MapSqlParameterSource param = new MapSqlParameterSource("roleId", entity.getId().orElseThrow());
|
||||
this.jdbc.update("DELETE FROM sys_role_menu WHERE role_id = :roleId", param);
|
||||
update("DELETE FROM sys_role_menu WHERE role_id = :roleId", "roleId", entity.getId().orElseThrow());
|
||||
}
|
||||
|
||||
void saveRoleMenuRefs(Long roleId, Role entity) {
|
||||
String sql = "INSERT INTO sys_role_menu(role_id, menu_id) VALUES (:roleId, :menuId)";
|
||||
MapSqlParameterSource[] batchArgs = entity.getMenus()
|
||||
.stream()
|
||||
.map(menuRef -> new MapSqlParameterSource()
|
||||
int i = batchUpdate(
|
||||
"INSERT INTO sys_role_menu(role_id, menu_id) VALUES (:roleId, :menuId)",
|
||||
entity.getMenus(),
|
||||
menuRef -> new MapSqlParameterSource()
|
||||
.addValue("roleId", roleId)
|
||||
.addValue("menuId", menuRef.menuId()))
|
||||
.toArray(MapSqlParameterSource[]::new);
|
||||
int[] i = this.jdbc.batchUpdate(sql, batchArgs);
|
||||
AssertResult.update(entity.getMenus().size(), NumberUtil.sum(i));
|
||||
.addValue("menuId", menuRef.menuId()));
|
||||
assertResultEquals(i, entity.getMenus().size());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,43 +3,39 @@ package xyz.zhouxy.plusone.system.domain.model.role;
|
|||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
|
||||
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
|
||||
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
|
||||
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
import xyz.zhouxy.plusone.util.NumberUtil;
|
||||
import xyz.zhouxy.plusone.jdbc.PlusoneJdbcDaoSupport;
|
||||
|
||||
class RolePermissionRefDAO {
|
||||
private final NamedParameterJdbcTemplate jdbc;
|
||||
class RolePermissionRefDAO extends PlusoneJdbcDaoSupport {
|
||||
|
||||
public RolePermissionRefDAO(NamedParameterJdbcTemplate jdbc) {
|
||||
this.jdbc = jdbc;
|
||||
protected RolePermissionRefDAO(@Nonnull NamedParameterJdbcTemplate jdbc) {
|
||||
super(jdbc);
|
||||
}
|
||||
|
||||
Set<ActionRef> selectPermissionRefsByRoleId(long roleId) {
|
||||
return this.jdbc.queryForList("SELECT permission_id FROM sys_role_permission WHERE role_id = :roleId",
|
||||
new MapSqlParameterSource("roleId", roleId),
|
||||
return queryForStream("SELECT permission_id FROM sys_role_permission WHERE role_id = :roleId",
|
||||
"roleId", roleId,
|
||||
Long.TYPE)
|
||||
.stream()
|
||||
.map(ActionRef::of)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
void clearRolePermissionRefs(Role entity) {
|
||||
MapSqlParameterSource param = new MapSqlParameterSource("roleId", entity.getId().orElseThrow());
|
||||
this.jdbc.update("DELETE FROM sys_role_permission WHERE role_id = :roleId", param);
|
||||
update("DELETE FROM sys_role_permission WHERE role_id = :roleId",
|
||||
"roleId", entity.getId().orElseThrow());
|
||||
}
|
||||
|
||||
void saveRolePermissionRefs(Long roleId, Role entity) {
|
||||
String sql = "INSERT INTO sys_role_permission(role_id, permission_id) VALUES (:roleId, :permissionId)";
|
||||
SqlParameterSource[] batchArgs = entity.getPermissions()
|
||||
.stream()
|
||||
.map(menuRef -> new MapSqlParameterSource()
|
||||
int i = batchUpdate(
|
||||
"INSERT INTO sys_role_permission(role_id, permission_id) VALUES (:roleId, :permissionId)",
|
||||
entity.getPermissions(),
|
||||
actionRef -> new MapSqlParameterSource()
|
||||
.addValue("roleId", roleId)
|
||||
.addValue("permissionId", menuRef.actionId()))
|
||||
.toArray(MapSqlParameterSource[]::new);
|
||||
int[] i = this.jdbc.batchUpdate(sql, batchArgs);
|
||||
AssertResult.update(entity.getMenus().size(), NumberUtil.sum(i));
|
||||
.addValue("permissionId", actionRef.actionId()));
|
||||
assertResultEquals(i, entity.getMenus().size());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.sql.ResultSet;
|
|||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
|
@ -15,6 +16,7 @@ import org.springframework.stereotype.Repository;
|
|||
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import xyz.zhouxy.plusone.constant.EntityStatus;
|
||||
import xyz.zhouxy.plusone.exception.DataNotExistException;
|
||||
import xyz.zhouxy.plusone.jdbc.JdbcRepositorySupport;
|
||||
import xyz.zhouxy.plusone.util.AssertResult;
|
||||
|
||||
|
@ -36,12 +38,13 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
protected final Role doFindById(@Nonnull Long id) {
|
||||
protected final Optional<Role> doFindById(@Nonnull Long id) {
|
||||
return queryForObject("""
|
||||
SELECT "id","name","identifier","status","remarks","version"
|
||||
FROM "sys_role"
|
||||
WHERE id = :id AND deleted = 0
|
||||
""", new MapSqlParameterSource("id", id));
|
||||
""",
|
||||
"id", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -52,13 +55,13 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
|
|||
""",
|
||||
new MapSqlParameterSource("id", entity.getId().orElseThrow())
|
||||
.addValue("version", entity.getVersion()));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(Long id) {
|
||||
return queryExists("SELECT 1 FROM sys_role WHERE id = :id AND deleted = 0 LIMIT 1",
|
||||
new MapSqlParameterSource("id", id));
|
||||
return queryExists("SELECT EXISTS (SELECT 1 FROM sys_role WHERE id = :id AND deleted = 0 LIMIT 1)",
|
||||
"id", id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -70,10 +73,10 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
|
|||
VALUES
|
||||
(:id, :name, :identifier, :status, :remarks, :createTime, :createdBy)
|
||||
""", generateParamSource(id, entity));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
this.roleMenuRefDAO.saveRoleMenuRefs(id, entity);
|
||||
this.rolePermissionRefDAO.saveRolePermissionRefs(id, entity);
|
||||
return entity;
|
||||
return find(id).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -89,14 +92,14 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
|
|||
"version" = "version" + 1
|
||||
WHERE id = :id AND deleted = 0 AND "version" = :version
|
||||
""", generateParamSource(entity));
|
||||
AssertResult.update(i, 1);
|
||||
AssertResult.updateOneRow(i);
|
||||
|
||||
Long id = entity.getId().orElseThrow();
|
||||
this.roleMenuRefDAO.clearRoleMenuRefs(entity);
|
||||
this.roleMenuRefDAO.saveRoleMenuRefs(id, entity);
|
||||
this.rolePermissionRefDAO.clearRolePermissionRefs(entity);
|
||||
this.rolePermissionRefDAO.saveRolePermissionRefs(id, entity);
|
||||
return entity;
|
||||
return find(entity.getId().orElseThrow()).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -106,7 +109,8 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
|
|||
FROM sys_role AS r
|
||||
LEFT JOIN sys_account_role AS ar ON r.id = ar.role_id
|
||||
WHERE ar.account_id = :accountId AND r.deleted = 0
|
||||
""", new MapSqlParameterSource("accountId", accountId));
|
||||
""",
|
||||
"accountId", accountId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
6
pom.xml
6
pom.xml
|
@ -40,7 +40,7 @@
|
|||
<commons-math3.version>3.6.1</commons-math3.version>
|
||||
<commons-pool2.version>2.11.1</commons-pool2.version>
|
||||
<tencentcloud-sdk.version>3.1.681</tencentcloud-sdk.version>
|
||||
<fastdfs.version>1.29-SNAPSHOT</fastdfs.version>
|
||||
<fastdfs.version>1.30-SNAPSHOT</fastdfs.version>
|
||||
<okio.version>3.0.0</okio.version>
|
||||
<okhttp.version>4.10.0</okhttp.version>
|
||||
|
||||
|
@ -197,6 +197,10 @@
|
|||
<artifactId>jsr305</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<repositories>
|
||||
|
|
Loading…
Reference in New Issue