Compare commits

...

9 Commits

27 changed files with 515 additions and 103 deletions

View File

@ -4,6 +4,8 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler.ExceptionInfoHolder;
/** /**
* AllExceptionHandlerConfig * AllExceptionHandlerConfig
*/ */
@ -12,7 +14,7 @@ import org.springframework.context.annotation.Configuration;
public class AllExceptionHandlerConfig { public class AllExceptionHandlerConfig {
@Bean @Bean
AllExceptionHandler getAllExceptionHandler() { AllExceptionHandler getAllExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
return new AllExceptionHandler(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder()); return new AllExceptionHandler(exceptionInfoHolder);
} }
} }

View File

@ -40,9 +40,8 @@ import xyz.zhouxy.plusone.util.RestfulResult;
@Order(Ordered.LOWEST_PRECEDENCE - 1) @Order(Ordered.LOWEST_PRECEDENCE - 1)
@Slf4j @Slf4j
public class DefaultExceptionHandler extends BaseExceptionHandler { public class DefaultExceptionHandler extends BaseExceptionHandler {
public DefaultExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
public DefaultExceptionHandler() { super(exceptionInfoHolder);
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder());
set(IllegalArgumentException.class, 4010000, "格式错误", HttpStatus.FORBIDDEN); set(IllegalArgumentException.class, 4010000, "格式错误", HttpStatus.FORBIDDEN);
set(DataAccessException.class, 6030000, "数据库错误", HttpStatus.INTERNAL_SERVER_ERROR, true); set(DataAccessException.class, 6030000, "数据库错误", HttpStatus.INTERNAL_SERVER_ERROR, true);
set(MethodArgumentNotValidException.class, set(MethodArgumentNotValidException.class,

View File

@ -31,6 +31,11 @@
<artifactId>spring-webmvc</artifactId> <artifactId>spring-webmvc</artifactId>
</dependency> </dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency> <dependency>
<groupId>xyz.zhouxy.plusone</groupId> <groupId>xyz.zhouxy.plusone</groupId>
<artifactId>plusone-commons</artifactId> <artifactId>plusone-commons</artifactId>

View File

@ -41,6 +41,14 @@ public final class AssertResult {
} }
} }
public static void updateOneRow(int i) {
update(i, 1);
}
public static void updateOneRow(Object i, String format) {
update(i, 1, format);
}
public static void exist(boolean expression) { public static void exist(boolean expression) {
if (!expression) { if (!expression) {
throw new DataNotExistException(); throw new DataNotExistException();

View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?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> <modelVersion>4.0.0</modelVersion>
<parent> <parent>
<groupId>xyz.zhouxy</groupId> <groupId>xyz.zhouxy</groupId>
@ -84,6 +86,11 @@
<groupId>com.tencentcloudapi</groupId> <groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-sms</artifactId> <artifactId>tencentcloud-sdk-java-sms</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.csource</groupId>
<artifactId>fastdfs-client-java</artifactId>
</dependency>
</dependencies> </dependencies>
</project> </project>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -10,6 +10,7 @@ import javax.annotation.Nonnull;
import org.springframework.jdbc.core.ResultSetExtractor; import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper; 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.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource; import org.springframework.jdbc.core.namedparam.SqlParameterSource;
@ -35,6 +36,10 @@ public abstract class JdbcEntityDaoSupport<T extends Entity<ID>, ID extends Seri
return this.jdbc.query(sql, paramSource, this.resultSetExtractor); return this.jdbc.query(sql, paramSource, this.resultSetExtractor);
} }
protected final T queryForObject(String sql, String paramName, Object value) {
return this.jdbc.query(sql, new MapSqlParameterSource(paramName, value), this.resultSetExtractor);
}
protected final List<T> queryForList(String sql) { protected final List<T> queryForList(String sql) {
return this.jdbc.query(sql, this.rowMapper); return this.jdbc.query(sql, this.rowMapper);
} }
@ -43,19 +48,36 @@ public abstract class JdbcEntityDaoSupport<T extends Entity<ID>, ID extends Seri
return this.jdbc.query(sql, parameterSource, this.rowMapper); return this.jdbc.query(sql, parameterSource, this.rowMapper);
} }
protected final List<T> queryForList(String sql, String paramName, Object value) {
return this.jdbc.query(sql, new MapSqlParameterSource(paramName, value), this.rowMapper);
}
protected final Stream<T> queryForStream(String sql, SqlParameterSource parameterSource) { protected final Stream<T> queryForStream(String sql, SqlParameterSource parameterSource) {
return this.jdbc.queryForStream(sql, parameterSource, this.rowMapper); return this.jdbc.queryForStream(sql, parameterSource, this.rowMapper);
} }
protected final Stream<T> queryForStream(String sql, String paramName, Object value) {
return this.jdbc.queryForStream(sql, new MapSqlParameterSource(paramName, value), this.rowMapper);
}
protected final <E> Stream<E> queryForStream(String sql, SqlParameterSource parameterSource, Class<E> elementType) { protected final <E> Stream<E> queryForStream(String sql, SqlParameterSource parameterSource, Class<E> elementType) {
return this.jdbc.queryForList(sql, parameterSource, elementType).stream(); return this.jdbc.queryForList(sql, parameterSource, elementType).stream();
} }
protected final <E> Stream<E> queryForStream(String sql, String paramName, Object value, Class<E> elementType) {
return this.jdbc.queryForList(sql, new MapSqlParameterSource(paramName, value), elementType).stream();
}
protected final boolean queryExists(String sql, SqlParameterSource parameterSource) { protected final boolean queryExists(String sql, SqlParameterSource parameterSource) {
Boolean isExists = this.jdbc.query(sql, parameterSource, ResultSet::next); Boolean isExists = this.jdbc.query(sql, parameterSource, ResultSet::next);
return Boolean.TRUE.equals(isExists); return Boolean.TRUE.equals(isExists);
} }
protected final boolean queryExists(String sql, String paramName, Object value) {
Boolean isExists = this.jdbc.query(sql, new MapSqlParameterSource(paramName, value), ResultSet::next);
return Boolean.TRUE.equals(isExists);
}
protected final int update(String sql, SqlParameterSource parameterSource) { protected final int update(String sql, SqlParameterSource parameterSource) {
return this.jdbc.update(sql, parameterSource); return this.jdbc.update(sql, parameterSource);
} }

View File

@ -0,0 +1,94 @@
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.EnableAutoConfiguration;
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)
@EnableAutoConfiguration
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);
}
}
}

View File

@ -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);
}
}

View File

@ -0,0 +1,32 @@
package xyz.zhouxy.plusone.oss;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties;
import lombok.Getter;
import lombok.Setter;
@Getter
@Setter
@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;
@Getter
@Setter
public static class ConnectionPool {
private Boolean enabled;
private Integer maxCountPerEntry;
private Integer maxIdleTime;
private Integer maxWaitTimeInMs;
}
}

View File

@ -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;
}
}
}

View File

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

View File

@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
import xyz.zhouxy.plusone.constant.RegexConsts; import xyz.zhouxy.plusone.constant.RegexConsts;
import xyz.zhouxy.plusone.validator.BaseValidator; import xyz.zhouxy.plusone.validator.BaseValidator;
class BaseValidator2Test { class BaseValidatorTest {
@Test @Test
void testValid() { void testValid() {

View File

@ -1,34 +1,57 @@
{ {"properties": [
"properties": [ {
{ "name": "plusone.application.name",
"name": "plusone.application.name", "type": "java.lang.String",
"type": "java.lang.String", "description": "A description for 'plusone.application.name'"
"description": "A description for 'plusone.application.name'" },
}, {
{ "name": "plusone.server.port",
"name": "plusone.server.port", "type": "java.lang.Integer",
"type": "java.lang.Integer", "description": "A description for 'plusone.server.port'"
"description": "A description for 'plusone.server.port'" },
}, {
{ "name": "plusone.debug",
"name": "plusone.debug", "type": "java.lang.Boolean",
"type": "java.lang.Boolean", "description": "A description for 'plusone.debug'"
"description": "A description for 'plusone.debug'" },
}, {
{ "name": "plusone.mail.host",
"name": "plusone.mail.host", "type": "java.lang.String",
"type": "java.lang.String", "description": "A description for 'plusone.mail.host'"
"description": "A description for 'plusone.mail.host'" },
}, {
{ "name": "plusone.mail.password",
"name": "plusone.mail.password", "type": "java.lang.String",
"type": "java.lang.String", "description": "A description for 'plusone.mail.password'"
"description": "A description for 'plusone.mail.password'" },
}, {
{ "name": "plusone.exception.handle-all-exception",
"name": "plusone.exception.handle-all-exception", "type": "java.lang.Boolean",
"type": "java.lang.Boolean", "description": "A description for 'plusone.exception.handle-all-exception'"
"description": "A description for 'plusone.exception.handle-all-exception'" },
} {
] "name": "fastdfs.http_anti_steal_token",
} "type": "java.lang.String",
"description": "A description for 'fastdfs.http_anti_steal_token'"
},
{
"name": "fastdfs.http_secret_key",
"type": "java.lang.String",
"description": "A description for 'fastdfs.http_secret_key'"
},
{
"name": "fastdfs.http_tracker_http_port",
"type": "java.lang.String",
"description": "A description for 'fastdfs.http_tracker_http_port'"
},
{
"name": "fastdfs.network_timeout_in_seconds",
"type": "java.lang.String",
"description": "A description for 'fastdfs.network_timeout_in_seconds'"
},
{
"name": "fastdfs.tracker_servers",
"type": "java.util.List",
"description": "A description for 'fastdfs.tracker_servers'"
}
]}

View File

@ -63,7 +63,16 @@ plusone:
exception: exception:
handle-all-exception: false handle-all-exception: false
# 日志配置 fastdfs:
logging: connect_timeout_in_seconds: 5
level: network_timeout_in_seconds: 30
root: debug 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

View File

@ -9,3 +9,8 @@ plusone:
code: Plusone code: Plusone
template: template:
code: 【Plusone】验证码%s10分钟内有效请勿泄露。 code: 【Plusone】验证码%s10分钟内有效请勿泄露。
# 日志配置
logging:
level:
root: info
'[xyz.zhouxy.plusone]': debug

View File

@ -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));
}
}
}

View File

@ -0,0 +1,16 @@
spring:
profiles:
active: secret
plusone:
# 邮件发送相关参数
mail:
subject:
code: Plusone
template:
code: 【Plusone】验证码%s10分钟内有效请勿泄露。
# 日志配置
logging:
level:
root: info
'[xyz.zhouxy.plusone]': debug

View File

@ -7,15 +7,14 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.bind.annotation.RestControllerAdvice;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler; 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.system.application.exception.AccountLoginException;
import xyz.zhouxy.plusone.util.RestfulResult; import xyz.zhouxy.plusone.util.RestfulResult;
@RestControllerAdvice @RestControllerAdvice
public class AccountLoginExceptionHandler extends BaseExceptionHandler { public class AccountLoginExceptionHandler extends BaseExceptionHandler {
protected AccountLoginExceptionHandler() { public AccountLoginExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder()); super(exceptionInfoHolder);
} }
@ExceptionHandler({ AccountLoginException.class }) @ExceptionHandler({ AccountLoginException.class })

View File

@ -15,7 +15,6 @@ import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.exception.SameTokenInvalidException; import cn.dev33.satoken.exception.SameTokenInvalidException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler; import xyz.zhouxy.plusone.exception.handler.BaseExceptionHandler;
import xyz.zhouxy.plusone.exception.handler.ExceptionInfoHolderFactory;
import xyz.zhouxy.plusone.util.RestfulResult; import xyz.zhouxy.plusone.util.RestfulResult;
/** /**
@ -27,8 +26,9 @@ import xyz.zhouxy.plusone.util.RestfulResult;
@Slf4j @Slf4j
public class SaTokenExceptionHandler extends BaseExceptionHandler { public class SaTokenExceptionHandler extends BaseExceptionHandler {
public SaTokenExceptionHandler() {
super(ExceptionInfoHolderFactory.newDefaultExceptionInfoHolder()); public SaTokenExceptionHandler(ExceptionInfoHolder exceptionInfoHolder) {
super(exceptionInfoHolder);
set(NotPermissionException.class, 4030103, "会话未能通过权限认证", HttpStatus.FORBIDDEN); set(NotPermissionException.class, 4030103, "会话未能通过权限认证", HttpStatus.FORBIDDEN);
set(NotRoleException.class, 4030103, "会话未能通过角色认证", HttpStatus.FORBIDDEN); set(NotRoleException.class, 4030103, "会话未能通过角色认证", HttpStatus.FORBIDDEN);
set(DisableServiceException.class, 4030202, "账号指定服务已被封禁", HttpStatus.FORBIDDEN); set(DisableServiceException.class, 4030202, "账号指定服务已被封禁", HttpStatus.FORBIDDEN);

View File

@ -34,7 +34,7 @@ import xyz.zhouxy.plusone.validator.InvalidInputException;
@Service @Service
public class AccountContextService { public class AccountContextService {
private final static StpLogic adminAuthLogic = AuthLogic.adminAuthLogic; private static final StpLogic adminAuthLogic = AuthLogic.adminAuthLogic;
@Resource @Resource
private AccountQueries accountQueries; private AccountQueries accountQueries;
@ -95,7 +95,7 @@ public class AccountContextService {
case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal)); case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal));
default -> throw InvalidInputException.unsupportedPrincipalTypeException("输入邮箱地址或手机号"); default -> throw InvalidInputException.unsupportedPrincipalTypeException("输入邮箱地址或手机号");
}; };
Assert.notNull(account, () -> AccountLoginException.accountNotExistException()); Assert.notNull(account, AccountLoginException::accountNotExistException);
mailAndSmsVerifyService.checkOtp(principal, command.getOtp()); mailAndSmsVerifyService.checkOtp(principal, command.getOtp());
} }

View File

@ -49,9 +49,9 @@ public class AdminLoginService {
case EMAIL -> accountRepository.findByEmail(Email.of(principal)); case EMAIL -> accountRepository.findByEmail(Email.of(principal));
case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal)); case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal));
}; };
Assert.notNull(account, () -> AccountLoginException.accountNotExistException()); Assert.notNull(account, AccountLoginException::accountNotExistException);
var isPasswordCorrect = account.checkPassword(command.getPassword()); var isPasswordCorrect = account.checkPassword(command.getPassword());
Assert.isTrue(isPasswordCorrect, () -> AccountLoginException.passwordErrorException()); Assert.isTrue(isPasswordCorrect, AccountLoginException::passwordErrorException);
adminAuthLogic.login(account.getId().orElseThrow(), command.isRememberMe()); adminAuthLogic.login(account.getId().orElseThrow(), command.isRememberMe());
var accountDetails = accountQueries.queryAccountDetails(account.getId().orElseThrow()); var accountDetails = accountQueries.queryAccountDetails(account.getId().orElseThrow());
@ -66,7 +66,7 @@ public class AdminLoginService {
case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal)); case MOBILE_PHONE -> accountRepository.findByMobilePhone(MobilePhone.of(principal));
default -> throw InvalidInputException.unsupportedPrincipalTypeException("输入邮箱地址或手机号"); default -> throw InvalidInputException.unsupportedPrincipalTypeException("输入邮箱地址或手机号");
}; };
Assert.notNull(account, () -> AccountLoginException.accountNotExistException()); Assert.notNull(account, AccountLoginException::accountNotExistException);
mailAndSmsVerifyService.checkOtp(principal, command.getOtp()); mailAndSmsVerifyService.checkOtp(principal, command.getOtp());

View File

@ -41,7 +41,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
new MapSqlParameterSource() new MapSqlParameterSource()
.addValue("id", entity.getId().orElseThrow()) .addValue("id", entity.getId().orElseThrow())
.addValue("version", entity.getVersion())); .addValue("version", entity.getVersion()));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
} }
@Override @Override
@ -53,7 +53,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
FROM sys_account FROM sys_account
WHERE id = :id AND deleted = 0 WHERE id = :id AND deleted = 0
""", """,
new MapSqlParameterSource("id", id)); "id", id);
} }
@Override @Override
@ -65,7 +65,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
FROM sys_account FROM sys_account
WHERE email = :email AND deleted = 0 WHERE email = :email AND deleted = 0
""", """,
new MapSqlParameterSource("email", email.value())); "email", email.value());
} }
@Override @Override
@ -77,7 +77,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
FROM sys_account FROM sys_account
WHERE mobile_phone = :mobilePhone AND deleted = 0 WHERE mobile_phone = :mobilePhone AND deleted = 0
""", """,
new MapSqlParameterSource("mobilePhone", mobilePhone.value())); "mobilePhone", mobilePhone.value());
} }
@Override @Override
@ -89,31 +89,31 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
FROM sys_account FROM sys_account
WHERE username = :username AND deleted = 0 WHERE username = :username AND deleted = 0
""", """,
new MapSqlParameterSource("username", username.value())); "username", username.value());
} }
@Override @Override
public boolean exists(Long id) { public boolean exists(Long id) {
return queryExists("SELECT 1 FROM sys_account WHERE id = :id AND deleted = 0 LIMIT 1", return queryExists("SELECT 1 FROM sys_account WHERE id = :id AND deleted = 0 LIMIT 1",
new MapSqlParameterSource("id", id)); "id", id);
} }
@Override @Override
public boolean existsUsername(Username username) { public boolean existsUsername(Username username) {
return queryExists("SELECT 1 FROM sys_account WHERE username = :username AND deleted = 0 LIMIT 1", return queryExists("SELECT 1 FROM sys_account WHERE username = :username AND deleted = 0 LIMIT 1",
new MapSqlParameterSource("username", username.value())); "username", username.value());
} }
@Override @Override
public boolean existsEmail(Email email) { public boolean existsEmail(Email email) {
return queryExists("SELECT 1 FROM sys_account WHERE email = :email AND deleted = 0 LIMIT 1", return queryExists("SELECT 1 FROM sys_account WHERE email = :email AND deleted = 0 LIMIT 1",
new MapSqlParameterSource("email", email.value())); "email", email.value());
} }
@Override @Override
public boolean existsMobilePhone(MobilePhone mobilePhone) { public boolean existsMobilePhone(MobilePhone mobilePhone) {
return queryExists("SELECT 1 FROM sys_account WHERE mobile_phone = :mobile_phone AND deleted = 0 LIMIT 1", return queryExists("SELECT 1 FROM sys_account WHERE mobile_phone = :mobile_phone AND deleted = 0 LIMIT 1",
new MapSqlParameterSource("mobile_phone", mobilePhone.value())); "mobile_phone", mobilePhone.value());
} }
@Override @Override
@ -127,7 +127,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
LEFT JOIN sys_account_role ar ON a.id = ar.account_id LEFT JOIN sys_account_role ar ON a.id = ar.account_id
WHERE ar.role_id = :roleId AND a.deleted = 0 WHERE ar.role_id = :roleId AND a.deleted = 0
""", """,
new MapSqlParameterSource("roleId", roleId)); "roleId", roleId);
} }
@Override @Override
@ -142,7 +142,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
:createdBy, :createTime) :createdBy, :createTime)
""", """,
generateParamSource(id, entity)); generateParamSource(id, entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
this.accountRoleDAO.insertAccountRoleRefs(id, entity.getRoleIds()); this.accountRoleDAO.insertAccountRoleRefs(id, entity.getRoleIds());
return entity; return entity;
} }
@ -166,7 +166,7 @@ public class AccountRepositoryImpl extends JdbcRepositorySupport<Account, Long>
WHERE id = :id AND deleted = 0 AND "version" = :version WHERE id = :id AND deleted = 0 AND "version" = :version
""", """,
generateParamSource(entity)); generateParamSource(entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
this.accountRoleDAO.saveAccountRoleRefs(entity); this.accountRoleDAO.saveAccountRoleRefs(entity);
return entity; return entity;
} }

View File

@ -36,7 +36,7 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
@Override @Override
public Dict doFindById(@Nonnull Long id) { public Dict doFindById(@Nonnull Long id) {
return queryForObject("SELECT id, dict_type, dict_label, \"version\" WHERE id = :id AND deleted = 0", return queryForObject("SELECT id, dict_type, dict_label, \"version\" WHERE id = :id AND deleted = 0",
new MapSqlParameterSource("id", id)); "id", id);
} }
@Override @Override
@ -47,7 +47,7 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
VALUES (:dictType, :dictLabel, :createTime, :createdBy) VALUES (:dictType, :dictLabel, :createTime, :createdBy)
""", """,
generateParamSource(id, entity)); generateParamSource(id, entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
this.dictValueDAO.insertDictValues(id, entity); this.dictValueDAO.insertDictValues(id, entity);
return find(id); return find(id);
} }
@ -64,7 +64,7 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
WHERE id = :id AND deleted = 0 AND "version" = :version WHERE id = :id AND deleted = 0 AND "version" = :version
""", """,
generateParamSource(entity)); generateParamSource(entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
this.dictValueDAO.updateDictValues(entity); this.dictValueDAO.updateDictValues(entity);
return find(entity.getId().orElseThrow()); return find(entity.getId().orElseThrow());
} }
@ -76,7 +76,7 @@ public class DictRepositoryImpl extends JdbcRepositorySupport<Dict, Long> implem
WHERE id = :id AND deleted = 0 AND "version" = :version WHERE id = :id AND deleted = 0 AND "version" = :version
""", """,
generateParamSource(entity)); generateParamSource(entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
} }
@Override @Override

View File

@ -46,7 +46,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
FROM sys_menu FROM sys_menu
WHERE id = :id AND deleted = 0 WHERE id = :id AND deleted = 0
""", """,
new MapSqlParameterSource("id", id)); "id", id);
} }
@Override @Override
@ -62,7 +62,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
"""; """;
MapSqlParameterSource paramSource = generateParamSource(id, entity); MapSqlParameterSource paramSource = generateParamSource(id, entity);
int i = update(sql, paramSource); int i = update(sql, paramSource);
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
this.actionDAO.saveActions(id, entity.getActions()); this.actionDAO.saveActions(id, entity.getActions());
return entity; return entity;
} }
@ -92,7 +92,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
// 更新菜单 // 更新菜单
int i = update(sql, generateParamSource(entity)); int i = update(sql, generateParamSource(entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
// 保存权限 // 保存权限
Long id = entity.getId().orElseThrow(); Long id = entity.getId().orElseThrow();
@ -108,13 +108,13 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
""", """,
new MapSqlParameterSource("id", entity.getId().orElseThrow()) new MapSqlParameterSource("id", entity.getId().orElseThrow())
.addValue("version", entity.getVersion())); .addValue("version", entity.getVersion()));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
} }
@Override @Override
public boolean exists(Long id) { public boolean exists(Long id) {
return queryExists("SELECT 1 FROM sys_menu WHERE id = :id AND deleted = 0 LIMIT 1", return queryExists("SELECT 1 FROM sys_menu WHERE id = :id AND deleted = 0 LIMIT 1",
new MapSqlParameterSource("id", id)); "id", id);
} }
@Override @Override
@ -129,7 +129,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
FROM sys_menu FROM sys_menu
WHERE id IN (:ids) AND deleted = 0 WHERE id IN (:ids) AND deleted = 0
""", """,
new MapSqlParameterSource("ids", ids)); "ids", ids);
} }
@Override @Override
@ -147,7 +147,7 @@ public class MenuRepositoryImpl extends JdbcRepositorySupport<Menu, Long> implem
LEFT JOIN sys_role_menu AS rm ON m.id = rm.menu_id LEFT JOIN sys_role_menu AS rm ON m.id = rm.menu_id
WHERE rm.role_id = :roleId AND r.deleted = 0 WHERE rm.role_id = :roleId AND r.deleted = 0
""", """,
new MapSqlParameterSource("roleId", roleId)); "roleId", roleId);
} }
@Override @Override

View File

@ -41,7 +41,8 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
SELECT "id","name","identifier","status","remarks","version" SELECT "id","name","identifier","status","remarks","version"
FROM "sys_role" FROM "sys_role"
WHERE id = :id AND deleted = 0 WHERE id = :id AND deleted = 0
""", new MapSqlParameterSource("id", id)); """,
"id", id);
} }
@Override @Override
@ -52,13 +53,13 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
""", """,
new MapSqlParameterSource("id", entity.getId().orElseThrow()) new MapSqlParameterSource("id", entity.getId().orElseThrow())
.addValue("version", entity.getVersion())); .addValue("version", entity.getVersion()));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
} }
@Override @Override
public boolean exists(Long id) { public boolean exists(Long id) {
return queryExists("SELECT 1 FROM sys_role WHERE id = :id AND deleted = 0 LIMIT 1", return queryExists("SELECT 1 FROM sys_role WHERE id = :id AND deleted = 0 LIMIT 1",
new MapSqlParameterSource("id", id)); "id", id);
} }
@Override @Override
@ -70,7 +71,7 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
VALUES VALUES
(:id, :name, :identifier, :status, :remarks, :createTime, :createdBy) (:id, :name, :identifier, :status, :remarks, :createTime, :createdBy)
""", generateParamSource(id, entity)); """, generateParamSource(id, entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
this.roleMenuRefDAO.saveRoleMenuRefs(id, entity); this.roleMenuRefDAO.saveRoleMenuRefs(id, entity);
this.rolePermissionRefDAO.saveRolePermissionRefs(id, entity); this.rolePermissionRefDAO.saveRolePermissionRefs(id, entity);
return entity; return entity;
@ -89,7 +90,7 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
"version" = "version" + 1 "version" = "version" + 1
WHERE id = :id AND deleted = 0 AND "version" = :version WHERE id = :id AND deleted = 0 AND "version" = :version
""", generateParamSource(entity)); """, generateParamSource(entity));
AssertResult.update(i, 1); AssertResult.updateOneRow(i);
Long id = entity.getId().orElseThrow(); Long id = entity.getId().orElseThrow();
this.roleMenuRefDAO.clearRoleMenuRefs(entity); this.roleMenuRefDAO.clearRoleMenuRefs(entity);
@ -106,7 +107,8 @@ public class RoleRepositoryImpl extends JdbcRepositorySupport<Role, Long> implem
FROM sys_role AS r FROM sys_role AS r
LEFT JOIN sys_account_role AS ar ON r.id = ar.role_id LEFT JOIN sys_account_role AS ar ON r.id = ar.role_id
WHERE ar.account_id = :accountId AND r.deleted = 0 WHERE ar.account_id = :accountId AND r.deleted = 0
""", new MapSqlParameterSource("accountId", accountId)); """,
"accountId", accountId);
} }
@Override @Override