From f37d4db19242957651b687af035ff39c36d39c57 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 16 Jun 2020 15:47:06 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5=E5=85=AC=E5=85=B1=E5=B7=A5?= =?UTF-8?q?=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/application-dev.properties | 4 +- note-common/common-db/pom.xml | 81 ++++ .../db/common/HttpsClientRequestFactory.java | 123 ++++++ .../ckeri/boot/db/common/KellerRunner.java | 39 ++ .../boot/db/common/config/CommonConfig.java | 60 +++ .../boot/db/common/config/CorsConfig.java | 31 ++ .../db/common/config/EnvironmentConfig.java | 18 + .../boot/db/common/config/PublicConstant.java | 181 ++++++++ .../boot/db/common/config/RequestConfig.java | 17 + .../ckeri/boot/db/common/entity/EmailLog.java | 182 ++++++++ .../ckeri/boot/db/common/entity/NoteInfo.java | 185 ++++++++ .../boot/db/common/entity/NotesInfo.java | 167 ++++++++ .../boot/db/common/entity/TestTable.java | 56 +++ .../ckeri/boot/db/common/entity/UserCard.java | 151 +++++++ .../ckeri/boot/db/common/entity/UserInfo.java | 140 ++++++ .../boot/db/common/mybatis/BaseEntity.java | 85 ++++ .../boot/db/common/mybatis/BaseException.java | 12 + .../boot/db/common/mybatis/BaseMapper.java | 161 +++++++ .../db/common/mybatis/SqlFieldReader.java | 399 ++++++++++++++++++ .../boot/db/common/mybatis/TypeCaster.java | 111 +++++ .../mybatis/annotation/FieldAttribute.java | 45 ++ .../mybatis/annotation/IndexAttribute.java | 21 + .../mybatis/annotation/KeyAttribute.java | 24 ++ .../mybatis/annotation/SortAttribute.java | 18 + .../mybatis/annotation/TableAttribute.java | 26 ++ .../mybatis/annotation/package-info.java | 5 + .../mybatis/provider/BaseCreateProvider.java | 25 ++ .../mybatis/provider/BaseDeleteProvider.java | 69 +++ .../mybatis/provider/BaseInsertProvider.java | 101 +++++ .../mybatis/provider/BaseSelectProvider.java | 164 +++++++ .../mybatis/provider/BaseUpdateProvider.java | 65 +++ .../common/mybatis/provider/package-info.java | 4 + .../boot/db/common/proxy/ApiController.java | 48 +++ .../boot/db/common/proxy/FormController.java | 48 +++ .../boot/db/common/response/Response.java | 72 ++++ .../boot/db/common/response/ResultData.java | 84 ++++ .../boot/db/common/util/AliyunMapUtils.java | 143 +++++++ .../ckeri/boot/db/common/util/Console.java | 55 +++ .../ckeri/boot/db/common/util/DateUtils.java | 68 +++ .../ckeri/boot/db/common/util/FileUtils.java | 120 ++++++ .../ckeri/boot/db/common/util/JwtUtils.java | 136 ++++++ .../boot/db/common/util/MetadataUtils.java | 134 ++++++ .../ckeri/boot/db/common/util/PageUtil.java | 50 +++ .../boot/db/common/util/RequestUtil.java | 194 +++++++++ .../boot/db/common/util/ResponseUtils.java | 44 ++ .../db/common/util/RestTemplateUtils.java | 27 ++ .../boot/db/common/util/SendEmailUtils.java | 175 ++++++++ .../boot/db/common/util/StringUtils.java | 214 ++++++++++ note-common/common-util/pom.xml | 13 + note-common/pom.xml | 14 + 50 files changed, 4407 insertions(+), 2 deletions(-) create mode 100644 note-common/common-db/pom.xml create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/HttpsClientRequestFactory.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/KellerRunner.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CommonConfig.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CorsConfig.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/EnvironmentConfig.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/PublicConstant.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/RequestConfig.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/EmailLog.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NoteInfo.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NotesInfo.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/TestTable.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserCard.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserInfo.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseEntity.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseException.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseMapper.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/SqlFieldReader.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/TypeCaster.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/FieldAttribute.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/IndexAttribute.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/KeyAttribute.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/SortAttribute.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/TableAttribute.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/package-info.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseCreateProvider.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseDeleteProvider.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseInsertProvider.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseSelectProvider.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseUpdateProvider.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/package-info.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/ApiController.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/FormController.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/Response.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/ResultData.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/AliyunMapUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/Console.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/DateUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/FileUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/JwtUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/MetadataUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/PageUtil.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RequestUtil.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/ResponseUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RestTemplateUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/SendEmailUtils.java create mode 100644 note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/StringUtils.java create mode 100644 note-common/common-util/pom.xml create mode 100644 note-common/pom.xml diff --git a/note-admin/src/main/resources/application-dev.properties b/note-admin/src/main/resources/application-dev.properties index 58b8e4b..ca9c8cc 100644 --- a/note-admin/src/main/resources/application-dev.properties +++ b/note-admin/src/main/resources/application-dev.properties @@ -6,11 +6,11 @@ spring.application.name=KellerNotes #mysql\u9A71\u52A8\u7C7B spring.datasource.driverClassName = com.mysql.cj.jdbc.Driver #mysql\u8FDE\u63A5\u5730\u5740 -spring.datasource.url = jdbc:mysql://localhost:3307/kyle_notes?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT +spring.datasource.url = jdbc:mysql://115.29.142.129:3306/kyle_notes?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true&serverTimezone=GMT #mysql\u7528\u6237\u540D spring.datasource.username = root #mysql\u5BC6\u7801 -spring.datasource.password = root +spring.datasource.password = 123456 mybatis.mapper-locations=classpath:mappers/*.xml logging.level.com.cheri.keller.mapper=debug diff --git a/note-common/common-db/pom.xml b/note-common/common-db/pom.xml new file mode 100644 index 0000000..0fcb6dd --- /dev/null +++ b/note-common/common-db/pom.xml @@ -0,0 +1,81 @@ + + + + keller + com.cheri + 1.0-SNAPSHOT + + + + 1.8 + + + 4.0.0 + common-db + 公共依赖 + + + + com.cheri + common-util + 1.0-SNAPSHOT + compile + + + org.springframework.boot + spring-boot-starter-web + + + org.mybatis.spring.boot + mybatis-spring-boot-starter + 2.1.1 + + + org.projectlombok + lombok + + + com.alibaba + fastjson + 1.2.61 + compile + + + + + net.coobird + thumbnailator + 0.4.8 + + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + + com.drewnoakes + metadata-extractor + 2.14.0 + compile + + + + + javax.mail + mail + 1.4.7 + + + + + cn.hutool + hutool-all + 5.3.7 + + + \ No newline at end of file diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/HttpsClientRequestFactory.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/HttpsClientRequestFactory.java new file mode 100644 index 0000000..d4e2d61 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/HttpsClientRequestFactory.java @@ -0,0 +1,123 @@ +package com.ckeri.boot.db.common; + +import org.springframework.http.client.SimpleClientHttpRequestFactory; + +import javax.net.ssl.*; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.Socket; +import java.security.cert.X509Certificate; + +/** + * @author xxx + * @create 2018/07/16 11:41 + * @description 创建 HttpsClientRequestFactory 以支持 RestTemplate 调用 https 请求 + */ +public class HttpsClientRequestFactory extends SimpleClientHttpRequestFactory { + @Override + protected void prepareConnection(HttpURLConnection connection, String httpMethod) { + try { + if (!(connection instanceof HttpsURLConnection)) { + throw new RuntimeException("An instance of HttpsURLConnection is expected"); + } + + HttpsURLConnection httpsConnection = (HttpsURLConnection) connection; + + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + @Override + public X509Certificate[] getAcceptedIssuers() { + return null; + } + + @Override + public void checkClientTrusted(X509Certificate[] certs, String authType) { + } + + @Override + public void checkServerTrusted(X509Certificate[] certs, String authType) { + } + + } + }; + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); + httpsConnection.setSSLSocketFactory(new MyCustomSSLSocketFactory(sslContext.getSocketFactory())); + + httpsConnection.setHostnameVerifier(new HostnameVerifier() { + @Override + public boolean verify(String s, SSLSession sslSession) { + return true; + } + }); + + super.prepareConnection(httpsConnection, httpMethod); + } catch (Exception e) { + e.printStackTrace(); + } + } + + /** + * We need to invoke sslSocket.setEnabledProtocols(new String[] {"SSLv3"}); + * see http://www.oracle.com/technetwork/java/javase/documentation/cve-2014-3566-2342133.html (Java 8 section) + */ + private static class MyCustomSSLSocketFactory extends SSLSocketFactory { + + private final SSLSocketFactory delegate; + + public MyCustomSSLSocketFactory(SSLSocketFactory delegate) { + this.delegate = delegate; + } + + @Override + public String[] getDefaultCipherSuites() { + return delegate.getDefaultCipherSuites(); + } + + @Override + public String[] getSupportedCipherSuites() { + return delegate.getSupportedCipherSuites(); + } + + @Override + public Socket createSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException { + final Socket underlyingSocket = delegate.createSocket(socket, host, port, autoClose); + return overrideProtocol(underlyingSocket); + } + + @Override + public Socket createSocket(final String host, final int port) throws IOException { + final Socket underlyingSocket = delegate.createSocket(host, port); + return overrideProtocol(underlyingSocket); + } + + @Override + public Socket createSocket(final String host, final int port, final InetAddress localAddress, final int localPort) throws + IOException { + final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort); + return overrideProtocol(underlyingSocket); + } + + @Override + public Socket createSocket(final InetAddress host, final int port) throws IOException { + final Socket underlyingSocket = delegate.createSocket(host, port); + return overrideProtocol(underlyingSocket); + } + + @Override + public Socket createSocket(final InetAddress host, final int port, final InetAddress localAddress, final int localPort) throws + IOException { + final Socket underlyingSocket = delegate.createSocket(host, port, localAddress, localPort); + return overrideProtocol(underlyingSocket); + } + + private Socket overrideProtocol(final Socket socket) { + if (!(socket instanceof SSLSocket)) { + throw new RuntimeException("An instance of SSLSocket is expected"); + } + ((SSLSocket) socket).setEnabledProtocols(new String[]{"TLSv1"}); + return socket; + } + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/KellerRunner.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/KellerRunner.java new file mode 100644 index 0000000..8532018 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/KellerRunner.java @@ -0,0 +1,39 @@ +package com.ckeri.boot.db.common; + +import com.ckeri.boot.db.common.config.CommonConfig; +import com.ckeri.boot.db.common.config.PublicConstant; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * @author yangkaile + * @date 2020-02-26 16:38:55 + * 继承Application接口后项目启动时会按照执行顺序执行run方法 + * 通过设置Order的value来指定执行的顺序 + */ +@Component +@Order(value = 1) +public class KellerRunner implements ApplicationRunner { + @Resource + private CommonConfig config; + + @Override + public void run(ApplicationArguments args) { + PublicConstant.port = config.port; + PublicConstant.serviceUrl = "https://127.0.0.1:" + config.port; + PublicConstant.appName = config.appName; + PublicConstant.mailServerHost = config.mailServerHost; + PublicConstant.mailServerUser = config.mailServerUser; + PublicConstant.mailServerPassword = config.mailServerPassword; + + PublicConstant.nginxPath = config.nginxPath; + PublicConstant.nginxUrl = config.nginxUrl; + PublicConstant.imgPath = config.imgPath; + PublicConstant.thumPath = config.thumPath; + PublicConstant.webUrl = config.webUrl; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CommonConfig.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CommonConfig.java new file mode 100644 index 0000000..99ec15d --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CommonConfig.java @@ -0,0 +1,60 @@ +package com.ckeri.boot.db.common.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; + +/** + * 项目配置文件,从application.properties中加载 + * @author yangkaile + * @date 2019-05-30 09:38:05 + */ +@Configuration +@PropertySource("classpath:application.properties") +public class CommonConfig { + + /** + * 项目运行端口 + */ + @Value("${server.port:8080}") + public String port; + + /** + * 应用名 + */ + @Value(("${spring.application.name:KellerNote}")) + public String appName; + + /** + * 邮件服务器地址 + */ + @Value("${mail.server.host}") + public String mailServerHost; + /** + * 发件人名称 + */ + @Value("${mail.server.user}") + public String mailServerUser; + /** + * 发件人密码 + */ + @Value("${mail.server.password}") + public String mailServerPassword; + + + @Value("${nginx.path}") + public String nginxPath; + + @Value("${nginx.url}") + public String nginxUrl; + + @Value("${img.path}") + public String imgPath; + + @Value("${thum.path}") + public String thumPath; + + @Value("${web.url}") + public String webUrl; + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CorsConfig.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CorsConfig.java new file mode 100644 index 0000000..035c39e --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/CorsConfig.java @@ -0,0 +1,31 @@ +package com.ckeri.boot.db.common.config; + + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +/** + * @program: keller + * @author: jim + * @create: 2020-06-10 17:18 + */ +@Configuration +public class CorsConfig { + private CorsConfiguration buildConfig() {//设置的跨域访问 + CorsConfiguration corsConfiguration = new CorsConfiguration(); + corsConfiguration.addAllowedOrigin("*"); // 1 + corsConfiguration.addAllowedHeader("*"); // 2 + corsConfiguration.addAllowedMethod("*"); // 3 + return corsConfiguration; + } + + @Bean + public CorsFilter corsFilter() { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", buildConfig()); // 4 + return new CorsFilter(source); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/EnvironmentConfig.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/EnvironmentConfig.java new file mode 100644 index 0000000..057e019 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/EnvironmentConfig.java @@ -0,0 +1,18 @@ +package com.ckeri.boot.db.common.config; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * @author Aaron Du + * @version V1.0 + * @date 2020/6/10 18:42 + **/ +@Data +@Component +@ConfigurationProperties(prefix = "data.test") +public class EnvironmentConfig { + private String envName; + private String envconfig; +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/PublicConstant.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/PublicConstant.java new file mode 100644 index 0000000..47df0b8 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/PublicConstant.java @@ -0,0 +1,181 @@ +package com.ckeri.boot.db.common.config; + +/** + * 公用常量,项目中要到的一些常量 + * @author yangkaile + * @date 2019-09-16 14:41:23 + */ +public class PublicConstant { + + /** + * 默认的用户类型,即普通用户类型 + */ + public static final int DEFAULT_USER_TYPE = 0; + + /** + * 管理员的用户类型 + */ + public static final int ADMIN_USER_TYPE = 100; + + public static boolean notUserType(Integer userType){ + return !isUserType(userType); + } + + public static boolean isUserType(Integer userType){ + if(userType == null){ + return false; + } + return userType == DEFAULT_USER_TYPE || userType == ADMIN_USER_TYPE; + } + + /** + * 业务成功标示 + */ + public static final int SUCCESS = 0; + /** + * 业务失败标示 + */ + public static final int FAILED = 1; + + /** + * 注册类型 + */ + public static final int REGISTER_TYPE = 0; + + /** + * 登录类型 + */ + public static final int LOGIN_TYPE = 1; + + /** + * 重置密码类型 + */ + public static final int RESET_PASSWORD_TYPE = 2; + + /** + * 邮件验证码有效期 + */ + public static final int EMAIL_CODE_TIME = 5; + + /** + * 邮件验证码长度 + */ + public static final int EMAIL_CODE_LENGTH = 6; + + /** + * JWT 有效时间 12 小时 + */ + public static final long JWT_EXP_TIME = 12 * 60 * 60 * 1000; + + /** + * JWT 签名 + */ + public static final String JWT_SIGN_KEY = "kellerNotes20241002"; + + /** + * 应用启动的端口号 + */ + public static String port ; + + + /** + * 应用名 + */ + public static String appName ; + + /** + * 服务器访问地址 + */ + public static String serviceUrl; + + /** + * 邮件服务器地址 + */ + public static String mailServerHost; + + + /** + * 邮件服务器登录用户名 + */ + public static String mailServerUser; + + + /** + * 邮件服务器登录密码 + */ + public static String mailServerPassword; + + public static String nginxPath; + + public static String nginxUrl; + + public static String imgPath; + + public static String thumPath; + + public static String webUrl; + + public static final String DEFAULT_NOTES_NAME = "默认笔记本"; + public static final int DEFAULT_NOTES_STATUS = 1; + + /** + * 缩略图前缀名 + */ + public static final String THUM_PREFIX = "thum"; + + /** + * 缩略图最大宽度 + */ + public static final int THUM_MAX_WIDTH = 120; + + /** + * 缩略图最大高度 + */ + public static final int THUM_MAX_HEIGHT = 120; + + /** + * 富文本笔记类型 + */ + public static final int NOTE_TYPE_RICH_TEXT = 0; + + + /** + * MarkDown 笔记类型 + */ + public static final int NOTE_TYPE_MARK_DOWN = 1; + + public static final int NOTE_CONTENT_TEXT = 0; + + public static final int NOTE_CONTENT_HTML = 1; + + /** + * 用户id参数固定名称,不接收外部传入的用户id + */ + public static final String USER_ID_KEY = "kellerUserId"; + + /** + * 管理员id参数固定名称,不接收外部传入的管理员id + */ + public static final String ADMIN_ID_KEY = "kellerAdminId"; + + /** + * 通用,不做访问权限设置 + */ + public static final int AUTHORITY_COMMON = 1 << 0; + + /** + * 用户登录后可以访问 + */ + public static final int AUTHORITY_LOGON = 1 << 1; + + /** + * 管理员可以访问 + */ + public static final int AUTHORITY_ADMIN = 1 << 2; + + /** + * 超级管理员可以访问 + */ + public static final int AUTHORITY_SUPPER_ADMIN = 1 << 3; + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/RequestConfig.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/RequestConfig.java new file mode 100644 index 0000000..b0da597 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/config/RequestConfig.java @@ -0,0 +1,17 @@ +package com.ckeri.boot.db.common.config; + +public class RequestConfig { + public static final String URL = "URL"; + public static final String URI = "URI"; + public static final String REMOTE_ADDR = "REMOTE_ADDR"; + public static final String REMOTE_HOST = "REMOTE_HOST"; + public static final String REMOTE_PORT = "REMOTE_PORT"; + public static final String REMOTE_USER = "REMOTE_USER"; + + public static final String REQUEST_METHOD = "REQUEST_METHOD"; + + public static final String METHOD = "method"; + public static final String TOKEN = "token"; + + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/EmailLog.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/EmailLog.java new file mode 100644 index 0000000..457f0f6 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/EmailLog.java @@ -0,0 +1,182 @@ +package com.ckeri.boot.db.common.entity; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.annotation.*; + +import java.util.Date; + +/** + * @author yangkaile + * @date 2019-09-29 10:58:52 + */ +@TableAttribute(name = "email_log") +public class EmailLog extends BaseEntity { + @FieldAttribute + @KeyAttribute(autoIncr = true) + private int id; + /** + * 邮件发送类型 + */ + @FieldAttribute(value = "邮件发送类型,不能为空",notNull = true) + @IndexAttribute + private Integer type; + /** + * 收件人 + */ + @FieldAttribute(value = "收件人,不能为空",notNull = true) + @IndexAttribute + private String email; + /** + * 标题 + */ + @FieldAttribute(value = "邮件标题,不能为空",notNull = true,length = 200) + private String title; + /** + * 内容 + */ + @FieldAttribute(value = "邮件内容,不能为空",notNull = true,length = 500) + private String content; + /** + * 验证码 + * 包含验证码的邮件,需要将验证码单独填写,方便查询 + */ + @FieldAttribute("验证码") + private String code; + + @FieldAttribute(value = "发送结果描述,如:发送失败的原因等",length = 500) + private String result; + /** + * 状态码 + * 0 成功 + * 1 失败 + */ + @FieldAttribute(value = "发送状态",notNull = true) + private int statusCode; + + /** + * 发送时间,验证码邮件的有效时间为5分钟 + */ + @FieldAttribute(value = "发送时间",notNull = true) + @SortAttribute + private Date createTime = new Date(); + + /** + * 验证码是否已使用 0:未使用 1:已使用 + */ + @FieldAttribute("验证码是否已使用") + private int isUsed = 0; + + public EmailLog(){ + super(); + } + + + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public String getResult() { + return result; + } + + public void setResult(String result) { + this.result = result; + } + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public int getIsUsed() { + return isUsed; + } + + public void setIsUsed(int isUsed) { + this.isUsed = isUsed; + } + + @Override + public String toString() { + return "Email{" + + "id=" + id + + ", type=" + type + + ", email='" + email + '\'' + + ", title='" + title + '\'' + + ", content='" + content + '\'' + + ", code='" + code + '\'' + + ", result='" + result + '\'' + + ", statusCode=" + statusCode + + ", createTime=" + createTime + + ", isUsed=" + isUsed + + '}'; + } + + + /** + * 是否是有效的验证码 + * 要求成功发送,发送时间在5分钟内,且未使用过 + * @return + */ + public boolean isEfficientVerificationCode(){ + return (isUsed == 0 + && statusCode == 0 + ); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NoteInfo.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NoteInfo.java new file mode 100644 index 0000000..3c9bd89 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NoteInfo.java @@ -0,0 +1,185 @@ +package com.ckeri.boot.db.common.entity; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.annotation.*; +import java.util.Date; + +/** + * @author yangkaile + * @date 2020-04-05 10:14:10 + */ +@TableAttribute(name = "note_info",comment = "笔记详情表") +public class NoteInfo extends BaseEntity { + + @FieldAttribute + @KeyAttribute(autoIncr = true) + private Integer id; + + @FieldAttribute("用户ID") + @IndexAttribute + private Integer userId; + + @FieldAttribute("笔记本ID") + @IndexAttribute + private Integer notesId; + + @FieldAttribute("笔记类型 0:富文本笔记 1:MarkDown笔记") + private Integer type; + + @FieldAttribute("笔记标题") + private String title; + + @FieldAttribute(value = "纯文本笔记内容",length = 70000,detailed = true) + private String text; + + @FieldAttribute(value = "html格式的笔记内容",length = 70000,detailed = true) + private String html; + + @FieldAttribute("排序") + @SortAttribute + private Integer sort; + + @FieldAttribute("笔记创建时间") + private Date createTime = new Date(); + + @FieldAttribute("是否删除 0:未删除 1:已删除") + private Integer isDelete; + + @FieldAttribute("最后一次修改时间") + private Date updateTime; + + @FieldAttribute("最后一次修改人") + private Integer updateUserID; + + public NoteInfo() { + } + + public NoteInfo(Integer id) { + this.id = id; + } + + public NoteInfo(Integer userId, Integer notesId) { + this.userId = userId; + this.notesId = notesId; + } + + public NoteInfo(Integer userId, Integer notesId, String title) { + this.userId = userId; + this.notesId = notesId; + this.title = title; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public Integer getNotesId() { + return notesId; + } + + public void setNotesId(Integer notesId) { + this.notesId = notesId; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + public String getHtml() { + return html; + } + + public void setHtml(String html) { + this.html = html; + } + + public Integer getSort() { + return sort; + } + + public void setSort(Integer sort) { + this.sort = sort; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Integer getIsDelete() { + return isDelete; + } + + public void setIsDelete(Integer isDelete) { + this.isDelete = isDelete; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public Integer getUpdateUserID() { + return updateUserID; + } + + public void setUpdateUserID(Integer updateUserID) { + this.updateUserID = updateUserID; + } + + @Override + public String toString() { + return "NoteInfo{" + + "id=" + id + + ", userId=" + userId + + ", notesId=" + notesId + + ", type=" + type + + ", title='" + title + '\'' + + ", text='" + text + '\'' + + ", html='" + html + '\'' + + ", sort=" + sort + + ", createTime=" + createTime + + ", isDelete=" + isDelete + + ", updateTime=" + updateTime + + ", updateUserID=" + updateUserID + + '}'; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NotesInfo.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NotesInfo.java new file mode 100644 index 0000000..91c902e --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/NotesInfo.java @@ -0,0 +1,167 @@ +package com.ckeri.boot.db.common.entity; + + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.annotation.*; +import java.util.Date; + +/** + * @date 2020-03-31 15:07:17 + * @author yangkaile + * 笔记本实体类 + */ +@TableAttribute(name = "notes_info",comment = "笔记本详情") +public class NotesInfo extends BaseEntity { + @FieldAttribute + @KeyAttribute(autoIncr = true) + private Integer id; + + @FieldAttribute("用户Id") + @IndexAttribute + private Integer userId; + + @FieldAttribute(value = "笔记本标题",length = 50,notNull = true) + private String title; + + @FieldAttribute(value = "笔记本副标题",length = 200) + private String subTitle; + + @FieldAttribute("笔记本中的笔记总数") + private int noteCount; + + @FieldAttribute("排序") + @SortAttribute + private Integer sort; + + @FieldAttribute("创建时间") + private Date createTime = new Date(); + + @FieldAttribute("是否已删除,0 正常,1 已删除") + private int isDelete; + + @FieldAttribute("最后修改时间") + private Date updateTime; + + @FieldAttribute("最后修改人") + private Integer updateUserId; + + @FieldAttribute("笔记本状态 1 默认笔记本") + private int status; + + public NotesInfo() { + } + + public NotesInfo(Integer id) { + this.id = id; + } + + public NotesInfo(Integer userId, String title) { + this.userId = userId; + this.title = title; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public Integer getUserId() { + return userId; + } + + public void setUserId(Integer userId) { + this.userId = userId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getSubTitle() { + return subTitle; + } + + public void setSubTitle(String subTitle) { + this.subTitle = subTitle; + } + + public int getNoteCount() { + return noteCount; + } + + public void setNoteCount(int noteCount) { + this.noteCount = noteCount; + } + + public Integer getSort() { + return sort; + } + + public void setSort(Integer sort) { + this.sort = sort; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public int getIsDelete() { + return isDelete; + } + + public void setIsDelete(int isDelete) { + this.isDelete = isDelete; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public Integer getUpdateUserId() { + return updateUserId; + } + + public void setUpdateUserId(Integer updateUserId) { + this.updateUserId = updateUserId; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + @Override + public String toString() { + return "NotesInfo{" + + "id=" + id + + ", userId=" + userId + + ", title='" + title + '\'' + + ", subTitle='" + subTitle + '\'' + + ", noteCount=" + noteCount + + ", sort=" + sort + + ", createTime=" + createTime + + ", isDelete=" + isDelete + + ", updateTime=" + updateTime + + ", updateUserId=" + updateUserId + + ", status=" + status + + '}'; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/TestTable.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/TestTable.java new file mode 100644 index 0000000..e4adecb --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/TestTable.java @@ -0,0 +1,56 @@ +package com.ckeri.boot.db.common.entity; + +/** + * @author Aaron Du + * @version V1.0 + * @date 2020/5/23 17:42 + **/ +public class TestTable { + private Integer id; + private String name; + private String state; + private Integer age; + + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public Integer getAge() { + return age; + } + + public void setAge(Integer age) { + this.age = age; + } + + @Override + public String toString() { + return "TestTable{" + + "id=" + id + + ", name='" + name + '\'' + + ", state='" + state + '\'' + + ", age=" + age + + '}'; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserCard.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserCard.java new file mode 100644 index 0000000..b82a6e3 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserCard.java @@ -0,0 +1,151 @@ +package com.ckeri.boot.db.common.entity; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.annotation.*; +import java.util.Date; + +@TableAttribute(name = "user_card",comment = "用户名片表") +public class UserCard extends BaseEntity { + + @FieldAttribute("用户ID") + @KeyAttribute + private int userId; + + @FieldAttribute(value = "昵称",length = 50) + private String nickName; + + @FieldAttribute(value = "名片上要展示的邮箱地址",length = 100) + private String email; + + @FieldAttribute(value = "用户头像最初的文件名",length = 100) + private String portraitOriginName; + + @FieldAttribute(value = "用户头像名称",length = 100) + private String portraitName; + + @FieldAttribute(value = "个人签名",length = 100) + private String label; + + @FieldAttribute + private Date createTime = new Date(); + + @FieldAttribute + private Date updateTime; + + @FieldAttribute + private Integer updateUserId; + + private String protraitUrl; + + private String protraitThumUrl; + + public UserCard() { + } + + public UserCard(int userId) { + this.userId = userId; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public String getNickName() { + return nickName; + } + + public void setNickName(String nickName) { + this.nickName = nickName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPortraitOriginName() { + return portraitOriginName; + } + + public void setPortraitOriginName(String portraitOriginName) { + this.portraitOriginName = portraitOriginName; + } + + public String getPortraitName() { + return portraitName; + } + + public void setPortraitName(String portraitName) { + this.portraitName = portraitName; + } + + public String getLabel() { + return label; + } + + public void setLabel(String label) { + this.label = label; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public Integer getUpdateUserId() { + return updateUserId; + } + + public void setUpdateUserId(Integer updateUserId) { + this.updateUserId = updateUserId; + } + + public String getProtraitUrl() { + return protraitUrl; + } + + public void setProtraitUrl(String protraitUrl) { + this.protraitUrl = protraitUrl; + } + + public String getProtraitThumUrl() { + return protraitThumUrl; + } + + public void setProtraitThumUrl(String protraitThumUrl) { + this.protraitThumUrl = protraitThumUrl; + } + + @Override + public String toString() { + return "UserCard{" + + "userId=" + userId + + ", nickName='" + nickName + '\'' + + ", email='" + email + '\'' + + ", portraitOriginName='" + portraitOriginName + '\'' + + ", portraitName='" + portraitName + '\'' + + ", label='" + label + '\'' + + ", createTime=" + createTime + + ", updateTime=" + updateTime + + ", updateUserId=" + updateUserId + + '}'; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserInfo.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserInfo.java new file mode 100644 index 0000000..b8da2bc --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/entity/UserInfo.java @@ -0,0 +1,140 @@ +package com.ckeri.boot.db.common.entity; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.annotation.*; +import java.util.Date; + +/** + * @author yangkaile + * @date 2019-10-01 13:34:14 + */ +@TableAttribute(name = "user_info",comment = "用户信息表") +public class UserInfo extends BaseEntity { + @KeyAttribute(autoIncr = true) + @FieldAttribute + private int id; + + @FieldAttribute(value = "用户类型",notNull = true) + @IndexAttribute + private Integer type; + + + @FieldAttribute(value = "密码",length = 200) + private String password; + + @FieldAttribute(value = "邮箱",notNull = true,length = 200) + @IndexAttribute + private String email; + + @FieldAttribute + private Date createTime = new Date(); + + @FieldAttribute("用户账号状态") + @IndexAttribute + private Integer status ; + + @FieldAttribute("是否删除,1 表示删除") + @IndexAttribute + private Integer isDelete; + + @FieldAttribute("最后一次修改时间") + private Date updateTime = new Date(); + + @FieldAttribute("修改人") + private Integer updateUserId; + + public UserInfo() { + } + + public UserInfo(int id) { + this.id = id; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public Integer getIsDelete() { + return isDelete; + } + + public void setIsDelete(Integer isDelete) { + this.isDelete = isDelete; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public Integer getUpdateUserId() { + return updateUserId; + } + + public void setUpdateUserId(Integer updateUserId) { + this.updateUserId = updateUserId; + } + + @Override + public String toString() { + return "UserInfo{" + + "id=" + id + + ", type=" + type + + ", password='" + password + '\'' + + ", email='" + email + '\'' + + ", createTime=" + createTime + + ", status=" + status + + ", isDelete=" + isDelete + + ", updateTime=" + updateTime + + ", updateUserId=" + updateUserId + + '}'; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseEntity.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseEntity.java new file mode 100644 index 0000000..ce17924 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseEntity.java @@ -0,0 +1,85 @@ +package com.ckeri.boot.db.common.mybatis; + +/** + * @author yangkaile + * @date 2019-07-17 16:59:52 + * BaseEntity,使用复杂查询(带条件的增删改查和分页查询)时需要继承的父类 + * 该类提供了可供选择的多条件查询方式、排序方式、分页查询相关参数等 + * 数据实体类继承该类即可使用 + * + */ +public class BaseEntity { + /** + * 是否查询明细字段 + */ + private boolean baseKyleDetailed = true; + /** + * 多个查询条件是否用And连接 + */ + private Boolean baseKyleUseAnd = true; + /** + * 是否按排序关键字升序排列 + */ + private Boolean baseKyleUseASC = true; + /** + * 页面大小 + */ + private int baseKylePageSize = 10; + /** + * 要查询的页码 + */ + private int baseKyleCurrentPage = 1; + /** + * 根据页面大小和要查询的页码计算出的起始行号 + */ + private int baseKyleStartRows ; + public Boolean getBaseKyleUseAnd() { + return baseKyleUseAnd; + } + + public void setBaseKyleUseAnd(Boolean baseKyleUseAnd) { + this.baseKyleUseAnd = baseKyleUseAnd; + } + + public Boolean getBaseKyleUseASC() { + return baseKyleUseASC; + } + + public void setBaseKyleUseASC(Boolean baseKyleUseASC) { + this.baseKyleUseASC = baseKyleUseASC; + } + + public void setBaseKylePageSize(int baseKylePageSize) { + this.baseKylePageSize = baseKylePageSize; + this.baseKyleStartRows = this.baseKylePageSize * (this.baseKyleCurrentPage - 1); + } + + public int getBaseKylePageSize() { + return baseKylePageSize; + } + + public int getBaseKyleStartRows() { + return baseKyleStartRows; + } + + public void setBaseKyleStartRows(int baseKyleStartRows) { + this.baseKyleStartRows = baseKyleStartRows; + } + + public int getBaseKyleCurrentPage() { + return baseKyleCurrentPage; + } + + public void setBaseKyleCurrentPage(int baseKyleCurrentPage) { + this.baseKyleStartRows = this.baseKylePageSize * (this.baseKyleCurrentPage - 1); + this.baseKyleCurrentPage = baseKyleCurrentPage; + } + + public boolean isBaseKyleDetailed() { + return baseKyleDetailed; + } + + public void setBaseKyleDetailed(boolean baseKyleDetailed) { + this.baseKyleDetailed = baseKyleDetailed; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseException.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseException.java new file mode 100644 index 0000000..5ffc75e --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseException.java @@ -0,0 +1,12 @@ +package com.ckeri.boot.db.common.mybatis; + +/** + * @author yangkaile + * @date 2019-07-18 09:49:17 + * 自定义异常,用来处理BaseMapper使用过程中抛出的异常 + */ +public class BaseException extends RuntimeException{ + public BaseException(String message){ + super(message); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseMapper.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseMapper.java new file mode 100644 index 0000000..a618dcb --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/BaseMapper.java @@ -0,0 +1,161 @@ +package com.ckeri.boot.db.common.mybatis; + +import com.ckeri.boot.db.common.mybatis.provider.*; +import org.apache.ibatis.annotations.*; +import org.springframework.dao.DuplicateKeyException; + +import java.util.List; + +/** + * @author yangkaile + * @date 2019-07-12 15:27:00 + * BaseMapper提供了通用的Mapper + * 实现了insert、insertAndReturnKey、deleteById、SelectById、updateById等基本的增删改查方法 + * 数据实体的Mapper继承该接口即可 + * + * BaseMapper还提供了带条件的删除和查询操作,以及带条件的分页查询,需要实体类继承BaseEntity方可使用 + * + * @param + */ +public interface BaseMapper { + /** + * 创建表 + * @param entity + */ + @UpdateProvider(type = BaseCreateProvider.class , method = "create") + void baseCreate(T entity); + + /** + * 插入操作 + * 将实体类的所有字段和字段的值分别列出来,适用于主键不是自增的表 + * @param entity + * @return INSERT INTO tableName (id,name...) VALUES (#{id},#{name}...) + * @throws DuplicateKeyException 当唯一字段重复插入时,会抛该异常 + */ + @InsertProvider(type = BaseInsertProvider.class,method = "insert") + Integer baseInsert(T entity) throws DuplicateKeyException; + + /** + * 插入数据并返回自增的主键(建议使用id) + * 将实体类中除主键以外的字段和值分别列出来,适用于主键是自增的表 + * @param entity + * @return INSERT INTO tableName (name...) VALUES(#{name}...) + * @throws DuplicateKeyException 当唯一字段重复插入时,会抛该异常 + */ + @InsertProvider(type = BaseInsertProvider.class,method = "insertAndReturnKey") + @Options(useGeneratedKeys=true,keyProperty = "id", keyColumn = "id") + Integer baseInsertAndReturnKey(T entity) throws DuplicateKeyException; + + + /** + * 根据Id删除数据,要求必须有id字段 + * @param entity + * @return + */ + @DeleteProvider(type = BaseDeleteProvider.class,method = "deleteById") + Integer baseDeleteById(T entity); + + /** + * 根据条件删除 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * 多个查询条件用And连接 + * @param entity 实体对象 + * @return DELETE FROM router WHERE name = #{name} AND serviceName = #{serviceName} + */ + @SelectProvider(type= BaseDeleteProvider.class,method = "deleteByCondition") + Integer baseDeleteByCondition(T entity); + + /** + * 根据id 更新数据,空值不更新 ,要求必须有id字段 + * @param entity + * @return + */ + @UpdateProvider(type = BaseUpdateProvider.class,method = "updateById") + Integer baseUpdateById(T entity); + + /** + * 根据主键更新数据,空值不更新,要求数据至少有一个主键,且主键有值 + * @param entity + * @return + */ + @UpdateProvider(type = BaseUpdateProvider.class,method = "updateByKey") + Integer baseUpdateByKey(T entity); + + /** + * 根据Id 查找数据,要求必须有id 字段 + * @param entity + * @return + */ + @SelectProvider(type= BaseSelectProvider.class,method = "selectById") + T baseSelectById(T entity); + + /** + * 根据主键查询数据,要求至少有一个主键,且主键必须有值 + * @param entity + * @return + */ + @SelectProvider(type= BaseSelectProvider.class,method = "selectByKey") + T baseSelectByKey(T entity); + + + + /** + * 查询全部数据 + * @param entity + * @return + */ + @SelectProvider(type= BaseSelectProvider.class,method = "selectAll") + List baseSelectAll(T entity); + + /** + * 带条件的查询,该查询为动态查询,不可缓存 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * 传入对象中带@SortAttribute注解的字段作为排序字段 + * @param entity 实体对象 + * param and 多个查询条件组合方式 true:AND false:OR + * param asc 排序方式 null:不指定排序方式 true:按指定排序字段升序 false:按指定排序字段降序 + * @return SELECT id,name... FROM router WHERE name = #{name} AND serviceName = #{serviceName} ORDER BY createTime ASC + */ + @SelectProvider(type= BaseSelectProvider.class,method = "selectByCondition") + List baseSelectByCondition(T entity); + + + /** + * 查询记录总数 + * 返回的是 "SELECT COUNT(1) FROM 表名" 的结果 + * 不带查询条件 + * @param entity + * @return + */ + @SelectProvider(type = BaseSelectProvider.class,method = "selectCount") + Integer baseSelectCount(T entity); + + /** + * 根据条件查询记录总数 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * @param entity + * @return SELECT COUNT(1) FROM router WHERE name = #{name} AND serviceName = #{serviceName} + */ + @SelectProvider(type = BaseSelectProvider.class,method = "selectCountByCondition") + Integer baseSelectCountByCondition(T entity); + + + /** + * 分页查询 + * 返回 “SELECT 所有字段 FROM 表名 LIMIT startRows,pageSize” 的结果 + * 不带查询条件 + * @param entity + * @return + */ + @SelectProvider(type = BaseSelectProvider.class,method = "selectPageList") + List baseSelectPageList(T entity); + + /** + * 加条件的分页查询 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * @return SELECT id,name... FROM router WHERE name = #{name} AND serviceName = #{serviceName} ORDER BY createTime ASC LIMIT #{startRows},#{pageSize} + */ + @SelectProvider(type = BaseSelectProvider.class,method = "selectPageListByCondition") + List baseSelectPageListByCondition(T entity); + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/SqlFieldReader.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/SqlFieldReader.java new file mode 100644 index 0000000..c5b3da2 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/SqlFieldReader.java @@ -0,0 +1,399 @@ +package com.ckeri.boot.db.common.mybatis; + +import com.ckeri.boot.db.common.mybatis.annotation.*; +import com.ckeri.boot.db.common.util.Console; +import com.ckeri.boot.db.common.util.StringUtils; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Provider工具类 + * 提供获取读取表名、字段名等公用方法 + * @author yangkaile + * @date 2019-09-12 15:29:19 + */ +public class SqlFieldReader { + + public static ConcurrentHashMap tableNameMap = new ConcurrentHashMap<>(16); + + /** + * 读取表名,要求类上有@TableAttribute注解 + * @param entity 实体对象 + * @return tableName + */ + public static String getTableName(T entity) { + Class cls = entity.getClass(); + String tableName = tableNameMap.get(cls.getName()); + if(StringUtils.noEmpty(tableName)){ + return tableName; + } + TableAttribute table = entity.getClass().getAnnotation(TableAttribute.class); + if(table == null){ + throw new BaseException("需要解析表名,但未找到@TableAttribute注解"); + } + tableNameMap.put(cls.getName(),table.name()); + return table.name(); + } + + /** + * 将所有字段名以逗号拼接起来返回 + * 从属性前的@FieldAttribute注解解析要查询的字段名 + * 当所有属性都没有@FieldAttribute注解时,解析所有属性名作为字段名 + * @param entity 实体对象 + * @return id,name + */ + public static String getFieldStr(T entity){ + Class cls = entity.getClass(); + Field[] fields = cls.getDeclaredFields(); + //带@FieldAttribute注解的属性名 + StringBuilder builder = new StringBuilder(); + //所有属性名 + StringBuilder allFields = new StringBuilder(); + for(Field field:fields){ + allFields.append(field.getName()).append(","); + if(field.getAnnotation(FieldAttribute.class) != null){ + FieldAttribute fieldAttribute = field.getAnnotation(FieldAttribute.class); + //如果查询明细字段,返回明细字段 + if(entity.isBaseKyleDetailed()){ + builder.append(field.getName()).append(","); + //如果不查询明细字段,不返回明细字段 + }else { + if(!fieldAttribute.detailed()){ + builder.append(field.getName()).append(","); + } + } + + } + } + if(builder.length() > 0){ + return builder.substring(0,builder.length() - 1); + }else if(allFields.length() > 0){ + return allFields.substring(0,allFields.length() - 1); + }else { + return null; + } + } + + /** + * 根据索引字段生成查询条件 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * @param entity 实体对象 + * @param 实体类型 + * @return WHERE name = #{name} OR controllerName = #{controllerName} + */ + public static String getConditionSuffix(T entity){ + String condition; + if(entity.getBaseKyleUseAnd() == null){ + return ""; + } + if(entity.getBaseKyleUseAnd()){ + condition = "AND"; + }else { + condition = "OR"; + } + Class cls = entity.getClass(); + Field[] fields = cls.getDeclaredFields(); + StringBuilder builder = new StringBuilder(); + builder.append(" WHERE "); + try { + for(Field field:fields){ + if(field.getAnnotation(IndexAttribute.class) != null){ + if(SqlFieldReader.hasValue(entity,field.getName())){ + builder.append(field.getName()) + .append(" = #{").append(field.getName()).append("} ") + .append(condition).append(" "); + } + + } + } + int index = builder.lastIndexOf(condition); + if(index < 0){ + return ""; + } + return builder.substring(0,index); + + }catch (Exception e){ + e.printStackTrace(); + } + //注意,不要return null + return ""; + } + + /** + * 获取主键的查询条件 + * 传入的对象必须满足以下条件: + * 1. 必须有且只有一个带有@keyAttribute注解的字段,如果有多个,只取第一个 + * 2. 带有@KeyAttribute注解的字段必须有值 + * 这是为了避免产生因为没有设置@KeyAttribute注解而造成全部数据修改或删除的问题 + * @param entity + * @param + * @return WHERE userId = #{userId} + */ + public static String getConditionByKeySuffix(T entity) throws BaseException { + Class cls = entity.getClass(); + Field[] fields = cls.getDeclaredFields(); + StringBuilder builder = new StringBuilder(); + builder.append(" WHERE "); + try { + for(Field field:fields){ + if(field.getAnnotation(KeyAttribute.class) != null){ + if(hasValue(entity,field.getName())){ + builder.append(field.getName()) + .append(" = #{").append(field.getName()).append("} "); + }else { + throw new BaseException("@KeyAttribute修饰的字段不能为空"); + } + break; + } + } + int index = builder.lastIndexOf("="); + if(index < 0){ + throw new BaseException("没有找到@KeyAttribute修饰的字段"); + } + return builder.toString(); + }catch (Exception e){ + e.printStackTrace(); + throw new BaseException(e.getMessage()); + } + } + + /** + * + * @param entity + * @param + * @return + */ + public static String getSortSuffix(T entity){ + String condition; + if(entity.getBaseKyleUseASC() == null){ + return ""; + } + if(entity.getBaseKyleUseASC()){ + condition = "ASC"; + }else { + condition = "DESC"; + } + Class cls = entity.getClass(); + Field[] fields = cls.getDeclaredFields(); + StringBuilder builder = new StringBuilder(); + builder.append(" ORDER BY "); + try { + for(Field field:fields){ + if(field.getAnnotation(SortAttribute.class) != null){ + builder.append(field.getName()).append(" ") + .append(condition).append(","); + + } + } + int index = builder.lastIndexOf(","); + if(index < 0){ + return ""; + } + return builder.substring(0,index); + + }catch (Exception e){ + e.printStackTrace(); + } + return ""; + } + + /** + * 获取所有字段列表 + * 读取类中带@FieldAttribute注解的字段,如果都没有带该注解,则返回类中所有字段 + * @return {id,name} + */ + public static List getFields(T entity){ + Field[] fields = entity.getClass().getDeclaredFields(); + List fieldList = new ArrayList<>(); + List allList = new ArrayList<>(); + //带@FieldAttribute注解的属性名 + for(Field field:fields){ + allList.add(field.getName()); + if(field.getAnnotation(FieldAttribute.class) != null){ + fieldList.add(field.getName()); + } + } + if(fieldList.size() == 0){ + return allList; + } + return fieldList; + } + + /** + * 读取@TableAttribute注解,解析表名和描述 + * 读取@FieldAttribute注解,解析字段名和描述 + * 读取@KeyAttribute注解,解析主键 + * 读取@IndexAttribute注解,解析索引 + * + * 创建的数据表,含表名、数据表描述、字段名、字段描述、主键、自增主键、索引 + * @param entity + * @return + */ + public static String getCreateTableSql(T entity){ + TableAttribute table = entity.getClass().getAnnotation(TableAttribute.class); + if(table == null){ + throw new BaseException("要解析表名,未发现@TableAttribute注解"); + } + String tableName = table.name(); + String tableComment = table.comment(); + + StringBuilder builder = new StringBuilder(); + + /* + * 拼写基础建表语句 + */ + builder.append("create table ") + .append(tableName) + .append("( \n"); + + + // 添加字段 + builder.append(getAddFieldSql(entity)); + builder.append(") "); + + // 如果有表说明,添加表说明 + if(StringUtils.noEmpty(tableComment)){ + builder.append("comment '") + .append(tableComment) + .append("'; \n"); + }else { + builder.append("; \n"); + } + + //添加主键 + builder.append(getCreateKeySql(entity)); + + //添加索引 + builder.append(getCreateIndexSql(entity)); + + Console.print("",builder.toString()); + return builder.toString(); + } + + + public static String getAddFieldSql(T entity){ + Field[] fields = entity.getClass().getDeclaredFields(); + StringBuilder builder = new StringBuilder(); + + /* + 解析字段描述:是否唯一、是否必填、是否设置了最大长度等 + */ + for(Field field:fields){ + FieldAttribute fieldAttribute = field.getAnnotation(FieldAttribute.class); + if(fieldAttribute != null){ + + builder.append(field.getName()) + .append(" ") + .append(TypeCaster.getType(field.getType().getSimpleName(),fieldAttribute.length())); + if(fieldAttribute.notNull()){ + builder.append(" not null "); + } + + if(fieldAttribute.unique()){ + builder.append(" unique "); + } + + //如果有字段说明,添加字段说明 + if(StringUtils.noEmpty(fieldAttribute.value())) { + builder.append(" comment '") + .append(fieldAttribute.value()) + .append("'"); + } + builder.append(", \n"); + } + } + builder.deleteCharAt(builder.lastIndexOf(",")); + return builder.toString(); + } + + private static String getCreateKeySql(T entity){ + Field[] fields = entity.getClass().getDeclaredFields(); + StringBuilder builder = new StringBuilder(); + for(Field field:fields){ + KeyAttribute keyAttribute = field.getAnnotation(KeyAttribute.class); + if(keyAttribute != null){ + FieldAttribute fieldAttribute = field.getAnnotation(FieldAttribute.class); + if(fieldAttribute == null){ + return ""; + } + builder .append("alter table ") + .append(getTableName(entity)) + .append(" change ") + .append(field.getName()) + .append(" ") + .append(field.getName()) + .append(" ") + .append(TypeCaster.getType(field.getType().getSimpleName(),fieldAttribute.length())); + if(keyAttribute.autoIncr()){ + builder.append(" auto_increment "); + } + builder.append(" primary key comment '") + .append(fieldAttribute.value()) + .append("'; \n"); + + break; + } + } + return builder.toString(); + } + + + /** + * 获取索引字段列表 + * @return + */ + public static String getCreateIndexSql(T entity){ + + String tableName = getTableName(entity); + StringBuilder builder = new StringBuilder(); + + Field[] fields = entity.getClass().getDeclaredFields(); + for(Field field:fields){ + if(field.getAnnotation(IndexAttribute.class) != null){ + + builder.append("alter table ") + .append(tableName) + .append(" add index ") + .append(tableName) + .append("_index_") + .append(field.getName()) + .append(" (") + .append(field.getName()) + .append("); \n"); + } + } + return builder.toString(); + } + + + /** + * 判断一个对象的指定字段有没有值 + * @param entity 实体对象 + * @param fieldName 对象的字段名 + * @param 实体类型 + * @return 值存在且不为null:返回true; 否则:返回false + */ + public static boolean hasValue(T entity, String fieldName){ + try { + Class cls = entity.getClass(); + Method method = cls.getMethod("get" + StringUtils.captureName(fieldName)); + if(method.invoke(entity) == null){ + return false; + }else { + return true; + } + }catch (IllegalAccessException e){ + e.printStackTrace(); + }catch (NoSuchMethodException e){ + e.printStackTrace(); + }catch (InvocationTargetException e){ + e.printStackTrace(); + } + return false; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/TypeCaster.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/TypeCaster.java new file mode 100644 index 0000000..bcc9c9c --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/TypeCaster.java @@ -0,0 +1,111 @@ +package com.ckeri.boot.db.common.mybatis; + +import com.ckeri.boot.db.common.util.Console; +import com.ckeri.boot.db.common.util.StringUtils; + +import java.util.HashMap; +import java.util.Map; + +/** + * Java类型和mysql类型间的转换,仅创建数据表时使用 + * @author yangkaile + * @date 2019-09-12 09:08:43 + */ +public class TypeCaster { + /** + * varchar/varbinary类型,允许最大长度为65535,在这里限制:如果超过3000,转换为text/blob + */ + private static final int MAX = 3000; + + /** + * TINYTEXT 256 bytes + * TEXT 65,535 bytes ~64kb + * MEDIUMTEXT 16,777,215 bytes ~16Mb + * LONGTEXT 4,294,967,295 bytes ~4Gb + */ + private static final int TEXT_MAX = 65535; + + /** + * decimal类型的最大长度为65,根据平时使用的需要,设置为20,足够大多数场景使用了 + */ + private static final int DECIMAL_MAX = 20; + private static Map map = new HashMap<>(16); + + private static final String STRING = "string"; + private static final String INT = "int"; + private static final String INTEGER = "integer"; + private static final String LONG = "long"; + private static final String DATE = "date"; + private static final String BYTE_ARRAY = "byte[]"; + private static final String FLOAT = "float"; + private static final String DOUBLE = "double"; + static { + map.put(STRING,"varchar(50)"); + map.put(INT,"int"); + map.put(INTEGER,"int"); + map.put(LONG,"bigint"); + map.put(DATE,"datetime"); + map.put(BYTE_ARRAY,"varbinary(50)"); + map.put(FLOAT,"decimal(10,2)"); + map.put(DOUBLE,"decimal(10,2)"); + } + /** + * 根据Java数据类型和设置的长度,转换为MySQL的数据类型 + * @param key + * @param length + * @return + */ + public static String getType(String key,int length){ + if(StringUtils.isEmpty(key)){ + return null; + } + + if(length <= 0){ + return map.get(key.toLowerCase()); + } + + /* + float/Float/double/Double类型判断设置的长度是否符合规则,如果超长,将长度设置为允许的最大长度 + */ + if(FLOAT.equalsIgnoreCase(key) + || DOUBLE.equalsIgnoreCase(key)){ + length = length > DECIMAL_MAX ? DECIMAL_MAX:length; + return "decimal(" + length + ",2)"; + } + + //String 根据长度,转换为 varchar 或 text + if(STRING.equalsIgnoreCase(key)){ + if(length < MAX){ + return "varchar(" + length + ")"; + } + if(length < TEXT_MAX){ + return "text"; + } + + return "mediumtext"; + + + } + + //byte[] 根据长度,转换为 varbinary 或 blob + if(BYTE_ARRAY.equalsIgnoreCase(key)){ + if(length < MAX){ + return "varbinary(" + length + ")"; + } + return "blob"; + } + + return map.get(key.toLowerCase()); + } + + public static void main(String[] args){ + Console.println("String",getType("String",10000)); + Console.println("Integer",getType("Integer",100)); + Console.println("float",getType("float",100)); + Console.println("Float",getType("Float",10)); + Console.println("long",getType("long",10)); + Console.println("Long",getType("Long",10)); + Console.println("Date",getType("Date",10)); + Console.println("double",getType("double",10)); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/FieldAttribute.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/FieldAttribute.java new file mode 100644 index 0000000..b65bb80 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/FieldAttribute.java @@ -0,0 +1,45 @@ +package com.ckeri.boot.db.common.mybatis.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 字段名注解,用于要查询的字段名之前 + * 在select * from tableName时,代替*的位置 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface FieldAttribute { + /** + * 字段说明 + * @return + */ + String value() default ""; + + /** + * 是否必填字段,默认不是必填 + * @return + */ + boolean notNull() default false; + + /** + * 字段长度 ,仅可变长类型设置 + * String 、byte[] 类型分别对应 mysql 中 varchar、varbinary类型,需要设置长度,默认50 + * @return + */ + int length() default 0; + + /** + * 是否唯一,默认不唯一 + * @return + */ + boolean unique() default false; + + /** + * 是否是明细字段,如果是明细字段,在查询列表时不显示该字段 + * @return + */ + boolean detailed() default false; +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/IndexAttribute.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/IndexAttribute.java new file mode 100644 index 0000000..a96b1d5 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/IndexAttribute.java @@ -0,0 +1,21 @@ +package com.ckeri.boot.db.common.mybatis.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 索引字段注解,可以根据索引字段进行查找、删除操作 + * 注意:索引字段尽量使用包装类,如:Integer,避免使用 int long等基本类型 + * 因为条件查询会将有值的索引字段作为查询条件, + * 此时,如果字段类型为int,初始值为0,0 将作为查询条件。 + * @author yangkaile + * @date 2019-07-12 16:43:43 + * + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface IndexAttribute { + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/KeyAttribute.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/KeyAttribute.java new file mode 100644 index 0000000..d29c16d --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/KeyAttribute.java @@ -0,0 +1,24 @@ +package com.ckeri.boot.db.common.mybatis.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 数据库主键的注解 + * 1. 仅支持单字段作为主键使用,将该字段上添加该注解即可 + * 2. 当使用id字段作为主键时,不需要添加该注解 + * 3. BaseMapper里后缀为ById的方法均是依照id字段作为主键设计的 + * @author yangkaile + * @date 2019-7-17 20:39:40 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface KeyAttribute { + /** + * 是否是自增主键 + * @return + */ + boolean autoIncr() default false; +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/SortAttribute.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/SortAttribute.java new file mode 100644 index 0000000..34cb76a --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/SortAttribute.java @@ -0,0 +1,18 @@ +package com.ckeri.boot.db.common.mybatis.annotation; + +/** + * Created by yangkaile on 2019/7/14. + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 排序字段的注解 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SortAttribute { +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/TableAttribute.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/TableAttribute.java new file mode 100644 index 0000000..4405b23 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/TableAttribute.java @@ -0,0 +1,26 @@ +package com.ckeri.boot.db.common.mybatis.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 表注解,用在entity的类声明之前 + * value赋值为表名 + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface TableAttribute { + /** + * 表名 + * @return + */ + String name() ; + + /** + * 描述 + * @return + */ + String comment() default ""; +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/package-info.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/package-info.java new file mode 100644 index 0000000..b840e8c --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/annotation/package-info.java @@ -0,0 +1,5 @@ +/** + * 自定义注解,用于标注表名、字段名、索引等数据库映射关系 + * 工欲善其事,必先利其器 + */ +package com.ckeri.boot.db.common.mybatis.annotation; \ No newline at end of file diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseCreateProvider.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseCreateProvider.java new file mode 100644 index 0000000..715eb43 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseCreateProvider.java @@ -0,0 +1,25 @@ +package com.ckeri.boot.db.common.mybatis.provider; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.SqlFieldReader; + +/** + * 创建表的Provider + * @author yangkaile + * @date 2019-09-12 15:07:09 + */ +public class BaseCreateProvider { + + /** + * + * 创建表的同时要创建索引,会执行多条语句,在application.properties中要设置 allowMultiQueries=true + * spring.datasource.url = jdbc:mysql://localhost:3306/my_core + * ?useUnicode=true&characterEncoding=utf-8&useSSL=false&allowMultiQueries=true + * @param entity + * @param + * @return + */ + public static String create(T entity){ + return SqlFieldReader.getCreateTableSql(entity); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseDeleteProvider.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseDeleteProvider.java new file mode 100644 index 0000000..32ba4b0 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseDeleteProvider.java @@ -0,0 +1,69 @@ +package com.ckeri.boot.db.common.mybatis.provider; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.SqlFieldReader; +import com.ckeri.boot.db.common.util.Console; +import com.ckeri.boot.db.common.util.StringUtils; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author yangkaile + * @date 2019-07-18 09:56:43 + */ +public class BaseDeleteProvider { + + public static Map deleteByIdMap = new ConcurrentHashMap<>(16); + + /** + * 根据Id 删除数据,要求必须有id字段 + * @param entity + * @param + * @return DELETE FROM router WHERE id = #{id} + */ + public static String deleteById(T entity){ + Class cls = entity.getClass(); + String className = cls.getName(); + String sql = deleteByIdMap.get(className); + if(StringUtils.isEmpty(sql)){ + sql = getDeletePrefix(entity) + " WHERE id = #{id} "; + deleteByIdMap.put(className,sql); + } + Console.info("deleteById",sql,entity); + return sql; + } + + public static String deleteByKey(T entity){ + try { + String sql = getDeletePrefix(entity) + SqlFieldReader.getConditionByKeySuffix(entity); + Console.info("deleteByKey",sql,entity); + return sql; + }catch (Exception e){ + return null; + } + } + + /** + * 根据条件删除,该查询为动态查询,不可缓存 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * 多个查询条件用And连接 + * @param entity 实体对象 + * param and 多个查询条件组合方式 null:不指定查询条件 true:多个查询条件用AND连接 false:多个查询条件用OR连接 + * @param 对象类型 + * @return DELETE FROM router WHERE name = #{name} AND serviceName = #{serviceName} + */ + public static String deleteByCondition(T entity){ + String sql = getDeletePrefix(entity) + SqlFieldReader.getConditionSuffix(entity); + Console.info("deleteByCondition",sql,entity); + return sql; + } + + private static String getDeletePrefix(T entity){ + return "DELETE FROM " + SqlFieldReader.getTableName(entity) + " "; + } + + public static void main(String[] args){ + + } + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseInsertProvider.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseInsertProvider.java new file mode 100644 index 0000000..479c8b1 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseInsertProvider.java @@ -0,0 +1,101 @@ +package com.ckeri.boot.db.common.mybatis.provider; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.SqlFieldReader; +import com.ckeri.boot.db.common.util.Console; +import com.ckeri.boot.db.common.util.StringUtils; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Created by yangkaile on 2019/7/12. + */ +public class BaseInsertProvider { + /** + * 缓存insert语句 + */ + public static Map insertMap = new ConcurrentHashMap<>(16); + + public static Map insertAndReturnKeyMap = new ConcurrentHashMap<>(16); + + /** + * 基础的添加语句 + * 读取对象的所有字段属性,生成insert语句 + * @param entity + * @param + * @return + */ + public static String insert(T entity) { + Class cls = entity.getClass(); + String className = cls.getName(); + String sql = insertMap.get(className); + if(StringUtils.isEmpty(sql)){ + String fieldStr = SqlFieldReader.getFieldStr(entity); + + StringBuilder builder = new StringBuilder(); + builder.append("INSERT INTO ") + .append(SqlFieldReader.getTableName(entity)).append(" ") + .append("(").append(fieldStr).append(") ") + .append("VALUES("); + + StringBuilder valuesStr = new StringBuilder(); + String[] arrays = fieldStr.split(","); + for(String str:arrays){ + valuesStr.append("#{").append(str).append("}").append(","); + } + builder.append(valuesStr.substring(0,valuesStr.length() - 1)) + .append(") "); + sql = builder.toString(); + insertMap.put(className,sql); + } + Console.info("insert",sql,entity); + return sql; + } + + public static String insertAndReturnKey(T entity) { + Class cls = entity.getClass(); + String className = cls.getName(); + String sql = insertAndReturnKeyMap.get(className); + if(StringUtils.isEmpty(sql)){ + String fieldStr = SqlFieldReader.getFieldStr(entity); + String[] arrays = fieldStr.split(","); + + StringBuilder builder = new StringBuilder(); + + StringBuilder valuesStr = new StringBuilder(); + + builder.append("INSERT INTO ") + .append(SqlFieldReader.getTableName(entity)).append(" ") + .append("("); + for(String str:arrays){ + if("id".equals(str)){ + continue; + } + valuesStr.append(str).append(","); + } + builder.append(valuesStr.substring(0,valuesStr.length() - 1)); + + builder.append(") ").append("VALUES("); + + valuesStr = new StringBuilder(); + for(String str:arrays){ + if("id".equals(str)){ + continue; + } + valuesStr.append("#{").append(str).append("}").append(","); + } + builder.append(valuesStr.substring(0,valuesStr.length() - 1)) + .append(") "); + sql = builder.toString(); + insertAndReturnKeyMap.put(className,sql); + } + Console.info("insertAndReturnKey",sql,entity); + return sql; + } + + + public static void main(String[] args){ + + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseSelectProvider.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseSelectProvider.java new file mode 100644 index 0000000..4dd437f --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseSelectProvider.java @@ -0,0 +1,164 @@ +package com.ckeri.boot.db.common.mybatis.provider; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.SqlFieldReader; +import com.ckeri.boot.db.common.util.Console; +import com.ckeri.boot.db.common.util.StringUtils; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 基础的 Mybatis SQL 提供类 + * @author yangkaile + * @date 2019-07-12 15:44:55 + * + */ +public class BaseSelectProvider { + + public static Map selectPrefixWithDetailedMap = new ConcurrentHashMap<>(16); + public static Map selectPrefixMap = new ConcurrentHashMap<>(16); + + + /** + * 根据ID 查询数据 + * @param entity 实体对象 + * @param 实体类型 + * @return SELECT id,name... FROM route WHERE id = #{id} + */ + public static String selectById(T entity){ + String sql = getSelectPrefix(entity) + " WHERE id = #{id}"; + Console.info("selectById",sql,entity); + return sql; + } + + /** + * 根据主键查询数据,要求至少有一个主键,且主键必须有值 + * @param entity + * @param + * @return + */ + public static String selectByKey(T entity){ + try { + String sql = getSelectPrefix(entity) + SqlFieldReader.getConditionByKeySuffix(entity); + Console.info("selectByKey",sql,entity); + return sql; + }catch (Exception e){ + return null; + } + } + + + /** + * 查询所有数据,不带条件 + * @param entity 实体对象 + * @param 实体类型 + * @return SELECT id,name... FROM router + */ + public static String selectAll(T entity){ + String sql = getSelectPrefix(entity); + Console.info("selectAll",sql,entity); + return sql; + } + + + /** + * + * 带条件的查询,该查询为动态查询,不可缓存 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * 传入对象中带@SortAttribute注解的字段作为排序字段 + * @param entity 实体对象 + * param and 多个查询条件组合方式 null:不指定查询条件 true:多个查询条件用AND连接 false:多个查询条件用OR连接 + * param asc 排序方式 null:不指定排序方式 true:按指定排序字段升序 false:按指定排序字段降序 + * @param 实体类型 + * @return SELECT id,name... FROM router WHERE name = #{name} AND serviceName = #{serviceName} ORDER BY createTime ASC + */ + public static String selectByCondition(T entity){ + String sql = getSelectPrefix(entity) + + SqlFieldReader.getConditionSuffix(entity) + + SqlFieldReader.getSortSuffix(entity); + Console.info("selectByCondition",sql,entity); + return sql; + } + + /** + * 查询记录总数 + * @param entity + * @param + * @return SELECT COUNT(1) FROM router + */ + public static String selectCount(T entity){ + String sql = "SELECT COUNT(1) FROM " + SqlFieldReader.getTableName(entity); + Console.info("selectCount",sql,entity); + return sql; + } + + /** + * 根据条件查询记录总数 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * @param entity + * param and 多个查询条件组合方式 null:不指定查询条件 true:多个查询条件用AND连接 false:多个查询条件用OR连接 + * @param + * @return SELECT COUNT(1) FROM router WHERE name = #{name} AND serviceName = #{serviceName} + */ + public static String selectCountByCondition(T entity){ + String sql = selectCount(entity) + SqlFieldReader.getConditionSuffix(entity); + Console.info("selectCountByCondition",sql,entity); + return sql; + } + + /** + * 不加条件的分页查询 + * @param entity 实体对象 + * param startRows 起始行 + * param pageSize 查询页大小 + * @param 实体类型 + * @return SELECT id,name... FROM router LIMIT #{startRows},#{pageSize} + */ + public static String selectPageList(T entity){ + String sql = selectAll(entity) + " LIMIT #{baseKyleStartRows},#{baseKylePageSize}"; + Console.info("selectPageList",sql,entity); + return sql; + } + + /** + * 加条件的分页查询 + * 传入的对象中带@IndexAttribute注解的字段有值的都作为查询条件 + * @param entity + * param and 多个查询条件组合方式 null:不指定查询条件 true:多个查询条件用AND连接 false:多个查询条件用OR连接 + * param asc 排序方式 null:不指定排序方式 true:按指定排序字段升序 false:按指定排序字段降序 + * param startRows 起始行数 + * param pageSize 查询条数 + * @param + * @return SELECT id,name... FROM router WHERE name = #{name} AND serviceName = #{serviceName} ORDER BY createTime ASC LIMIT #{startRows},#{pageSize} + */ + public static String selectPageListByCondition(T entity){ + String sql = selectByCondition(entity) + " LIMIT #{baseKyleStartRows},#{baseKylePageSize}"; + Console.info("selectPageListByCondition",sql,entity); + return sql; + } + + /** + * 获取通用查询前缀 + * @param entity 实体类类型 + * @return SELECT 所有字段 FROM 表名 + */ + private static String getSelectPrefix(T entity){ + String className = entity.getClass().getName(); + String sql; + if(entity.isBaseKyleDetailed()){ + sql = selectPrefixWithDetailedMap.get(className); + }else { + sql = selectPrefixMap.get(className); + } + if(StringUtils.isEmpty(sql)){ + sql = "SELECT " + SqlFieldReader.getFieldStr(entity) + " FROM " + SqlFieldReader.getTableName(entity) + " "; + if(entity.isBaseKyleDetailed()){ + selectPrefixWithDetailedMap.put(className,sql); + }else { + selectPrefixMap.put(className,sql); + } + } + return sql; + + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseUpdateProvider.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseUpdateProvider.java new file mode 100644 index 0000000..ceea76f --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/BaseUpdateProvider.java @@ -0,0 +1,65 @@ +package com.ckeri.boot.db.common.mybatis.provider; + +import com.ckeri.boot.db.common.mybatis.BaseEntity; +import com.ckeri.boot.db.common.mybatis.SqlFieldReader; +import com.ckeri.boot.db.common.util.Console; + +import java.util.List; + +/** + * @author yangkaile + * @date 2019-07-18 14:27:30 + */ +public class BaseUpdateProvider { + + /** + * 根据id 更新数据,空值不更新 ,要求数据有id字段 + * @param entity + * @param + * @return UPDATE router SET methodName = #{methodName} ,createTime = #{createTime} WHERE id = #{id} + */ + public static String updateById(T entity){ + String sql = getUpdatePrefix(entity) + " WHERE id = #{id}"; + Console.info("updateById",sql,entity); + return sql; + } + + /** + * 根据主键更新数据,空值不更新,要求数据至少有一个主键,且主键有值 + * @param entity + * @param + * @return + */ + public static String updateByKey(T entity){ + try { + String sql = getUpdatePrefix(entity) + SqlFieldReader.getConditionByKeySuffix(entity); + Console.info("updateByKey",sql,entity); + return sql; + }catch (Exception e){ + return null; + } + } + + /** + * 获取更新操作的前缀部分 + * @param entity + * @return UPDATE 表名 SET + */ + private static String getUpdatePrefix(T entity){ + StringBuilder builder = new StringBuilder(); + builder.append("UPDATE ").append(SqlFieldReader.getTableName(entity)).append(" SET "); + List fields = SqlFieldReader.getFields(entity); + try{ + for(String field:fields){ + if(SqlFieldReader.hasValue(entity,field)){ + builder.append(field).append(" = #{") + .append(field).append("} ").append(","); + } + } + return builder.substring(0,builder.lastIndexOf(",")) ; + }catch (Exception e){ + e.printStackTrace(); + } + return null; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/package-info.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/package-info.java new file mode 100644 index 0000000..4d467de --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/mybatis/provider/package-info.java @@ -0,0 +1,4 @@ +/** + * 提供基础的 Mybatis SQL语句 + */ +package com.ckeri.boot.db.common.mybatis.provider; \ No newline at end of file diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/ApiController.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/ApiController.java new file mode 100644 index 0000000..f085872 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/ApiController.java @@ -0,0 +1,48 @@ +package com.ckeri.boot.db.common.proxy; +import com.ckeri.boot.db.common.util.RequestUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * @author yangkaile + * @date 2019-08-28 09:05:54 + * 接口转发 + */ +@RestController +@RequestMapping("/api") +@CrossOrigin(origins = "*",allowedHeaders="*", maxAge = 3600) +public class ApiController { + + @Resource + HttpServletRequest request; + + @Autowired + RestTemplate restTemplate; + + + /** + * json 格式的GET请求 + * @return + */ + @GetMapping + public ResponseEntity get(){ + Map params = RequestUtil.getParam(request); + return RequestUtil.doGet(request,params,restTemplate); + } + + + /** + * JSON 形式的 POST 请求 + * @return + */ + @PostMapping + public ResponseEntity post(){ + Map params = RequestUtil.getBodyParams(request); + return RequestUtil.doPost(request,params,restTemplate); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/FormController.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/FormController.java new file mode 100644 index 0000000..e04b29b --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/proxy/FormController.java @@ -0,0 +1,48 @@ +package com.ckeri.boot.db.common.proxy; +import com.ckeri.boot.db.common.util.RequestUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.client.RestTemplate; + +import javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; +import java.util.Map; + +/** + * @author yangkaile + * @date 2019-08-28 09:05:54 + * 接口转发 + */ +@RestController +@RequestMapping("/form") +@CrossOrigin(origins = "*",allowedHeaders="*", maxAge = 3600) +public class FormController { + + @Resource + HttpServletRequest request; + + @Autowired + RestTemplate restTemplate; + + /** + * 表单形式的GET请求 + * @return + */ + @GetMapping + public ResponseEntity get(){ + Map params = RequestUtil.getParam(request); + return RequestUtil.doGet(request,params,restTemplate); + } + + + /** + * 表单形式的 POST 请求 + * @return + */ + @PostMapping + public ResponseEntity post(){ + Map params = RequestUtil.getParam(request); + return RequestUtil.doPost(request,params,restTemplate); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/Response.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/Response.java new file mode 100644 index 0000000..99e079e --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/Response.java @@ -0,0 +1,72 @@ +package com.ckeri.boot.db.common.response; + +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; + +/** + * @author yangkaile + * @date 2018-10-22 14:29:07 + * 规定Controller统一的消息返回格式 + */ +public class Response { + /** + * 返回OK + * @param object + * @return + */ + public static ResponseEntity ok(ResultData object){ + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON).body(object); + } + + /** + * 返回OK + * @return + */ + public static ResponseEntity ok(){ + ResultData response = ResultData.success(); + return ResponseEntity.ok() + .contentType(MediaType.APPLICATION_JSON).body(response); + } + + /** + * 异常请求 + * @return + */ + public static ResponseEntity badRequest(){ + ResultData response = ResultData.error("请求参数异常"); + return ResponseEntity.status(HttpStatus.BAD_REQUEST) + .contentType(MediaType.APPLICATION_JSON).body(response); + } + + /** + * 没有登录 + * @return + */ + public static ResponseEntity unauthorized(){ + ResultData response = ResultData.error("用户未登录"); + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .contentType(MediaType.APPLICATION_JSON).body(response); + } + + /** + * 没有访问权限 + * @return + */ + public static ResponseEntity forbidden(){ + ResultData response = ResultData.error("没有权限"); + return ResponseEntity.status(HttpStatus.FORBIDDEN) + .contentType(MediaType.APPLICATION_JSON).body(response); + } + + /** + * 系统内部错误 + * @return + */ + public static ResponseEntity error(){ + ResultData response = ResultData.error("系统错误"); + return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) + .contentType(MediaType.APPLICATION_JSON).body(response); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/ResultData.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/ResultData.java new file mode 100644 index 0000000..4aca4c8 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/response/ResultData.java @@ -0,0 +1,84 @@ +package com.ckeri.boot.db.common.response; + +/** + * 规定Service统一的消息返回格式 + * 在Controller中统一返回ResponseEntity格式的数据,在ResponseEntity的body里,必须使用MyResponseObject格式的数据 + * @author yangkaile + * @date 2018-11-22 10:54:01 + */ +public class ResultData { + + /** + * 业务状态 0:成功 1:失败 + */ + private int success ; + /** + * 返回数据 + */ + private Object data ; + /** + * 文字描述,一般放业务处理失败时返回的错误信息 + */ + private String message ; + + public final static int SUCCESS_CODE_SUCCESS = 0; + public final static int SUCCESS_CODE_FAILED = 1; + + public ResultData() { + } + + public static ResultData success() { + ResultData resultData = new ResultData(); + resultData.setSuccess(SUCCESS_CODE_SUCCESS); + return resultData; + } + public static ResultData success(Object data) { + ResultData resultData = new ResultData(); + resultData.setSuccess(SUCCESS_CODE_SUCCESS); + resultData.setData(data); + return resultData; + } + public static ResultData error(String message) { + ResultData resultData = new ResultData(); + resultData.setSuccess(SUCCESS_CODE_FAILED); + resultData.setMessage(message); + return resultData; + } + public boolean isSuccess(){ + return success == SUCCESS_CODE_SUCCESS; + } + + + public int getSuccess() { + return success; + } + + public void setSuccess(int success) { + this.success = success; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + @Override + public String toString() { + return "ResultData{" + + "success=" + success + + ", data=" + data + + ", message='" + message + '\'' + + '}'; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/AliyunMapUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/AliyunMapUtils.java new file mode 100644 index 0000000..9647902 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/AliyunMapUtils.java @@ -0,0 +1,143 @@ +package com.ckeri.boot.db.common.util; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.springframework.http.*; +import org.springframework.web.client.RestTemplate; + +/** + * @author yangkaile + * @date 2019-05-30 17:28:44 + * 阿里云地图API 工具 + */ +public class AliyunMapUtils { + /** + * 阿里云地图API身份认证信息 + */ + private static final String APP_CODE = "c8b7ef0a794a4e7e96e6a309d150dd8c"; + + /** + * 阿里云地图API访问地址 + */ + private static final String URL = "https://regeo.market.alicloudapi.com/v3/geocode/regeo"; + + /** + * 阿里云地图API返回成功时的状态码 + */ + private static final String SUCCESS_CODE = "10000"; + /** + * 返回的状态码关键字 + */ + private static final String INFO_CODE = "infocode"; + /** + * 返回的消息内容关键字 + */ + private static final String REGEO_CODE = "regeocode"; + /** + * 返回的具体地址关键字 + */ + private static final String FORMATTED_ADDRESS = "formatted_address"; + + + /** + * 根据经纬度获取地址 + * @param longitude 经度 小数点后不超过6位 如 116.36486 + * @param latitude 纬度 小数点后不超过6位 如 40.084858 + * @return 地址 如:北京市昌平区霍营街道龙锦三街 + */ + private static String getAddress(float longitude, float latitude) { + String url = URL + "?location=" + longitude + "," + latitude; + String result = null; + try { + //Header中放入Authorization信息 :AppCode + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.add("Authorization", "APPCODE " + APP_CODE); + RestTemplate restTemplate = RestTemplateUtils.getTemplate(); + //发送Get请求 + HttpEntity requestEntity = new HttpEntity(null, httpHeaders); + ResponseEntity response = restTemplate.exchange(url, HttpMethod.GET, requestEntity, String.class); + Console.println("response",response); + if(response.getStatusCode() == HttpStatus.OK){ + result = getAddrByBody(response.getBody()); + } + + } catch (Exception e) { + e.printStackTrace(); + } + return result; + } + + /** + * 根据经纬度获取地址 + * @param longitude 经度 如 116° 21' 53.5" + * @param latitude 纬度 如 40° 5' 5.49" + * @return 地址 如:北京市海淀区青龙桥街道颐和园 + */ + public static String getAddress(String longitude, String latitude ){ + return getAddress(pointToFloat(longitude),pointToFloat(latitude)); + } + + /** + * 从返回的Body中解析出地址 + * { + * "infocode":"10000", + * "regeocode":{ + * "formatted_address":"北京市海淀区青龙桥街道颐和园", + * "addressComponent":{ + * "businessAreas":[[]], + * "country":"中国", + * "province":"北京市", + * "citycode":"010", + * "city":[], + * "adcode":"110108", + * "streetNumber":{ + * "number":"甲1号", + * "distance":"675.586", + * "street":"六郎庄路", + * "location":"116.278221,39.9850281", + * "direction":"东南"}, + * "towncode":"110108013000", + * "district":"海淀区", + * "neighborhood":{ + * "name":"颐和园", + * "type":"风景名胜;风景名胜;世界遗产" + * }, + * "township":"青龙桥街道", + * "building":{ + * "name":[], + * "type":[] + * } + * } + * }, + * "status":"1", + * "info":"OK" + * } + * @return 具体地址:如:北京市海淀区青龙桥街道颐和园 + */ + private static String getAddrByBody(String body){ + JSONObject jsonObject = JSON.parseObject(body); + if(SUCCESS_CODE.equals(jsonObject.getString(INFO_CODE))){ + return jsonObject.getJSONObject(REGEO_CODE).getString(FORMATTED_ADDRESS); + }else{ + return null; + } + } + + + /** + * 经纬度格式转换,从时分秒转换成float格式,保留小数点后6位 + * @param point 坐标点 格式:40° 5' 5.49" + * @return 转换后的格式:40.084858 + */ + private static float pointToFloat (String point ) { + Double du = Double.parseDouble(point.substring(0, point.indexOf("°")).trim()); + Double fen = Double.parseDouble(point.substring(point.indexOf("°")+1, point.indexOf("'")).trim()); + Double miao = Double.parseDouble(point.substring(point.indexOf("'")+1, point.indexOf("\"")).trim()); + Double duStr = du + fen / 60 + miao / 60 / 60 ; + String str = duStr.toString(); + if(str.substring(str.indexOf(".") + 1).length() > 6){ + return Float.parseFloat(str.substring(0,str.indexOf(".") + 6 + 1)); + } + return Float.parseFloat(str); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/Console.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/Console.java new file mode 100644 index 0000000..8c6423f --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/Console.java @@ -0,0 +1,55 @@ +package com.ckeri.boot.db.common.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author yangkaile + * @date 2019-04-16 11:00:56 + * 控制台日志输出工具类 + */ +public class Console { + + private static Logger logger = LoggerFactory.getLogger(Console.class); + + public static void print(String title,Object ... objects){ + System.out.println("=======" + title + "========"); + for(Object object : objects){ + System.out.print(object + "\t"); + } + System.out.println(); + } + + public static void println(String title,Object ... objects){ + System.out.println("=======" + title + "========"); + for(Object object : objects){ + System.out.println(object); + } + System.out.println(); + } + + public static void info(String title,Object ... objects){ + if(logger.isInfoEnabled()){ + StringBuilder builder = new StringBuilder(); + builder.append("======").append(title).append("======"); + for (Object object:objects){ + builder.append("\n").append(object); + } + builder.append("\n"); + logger.info(builder.toString()); + } + } + + public static void error(String title,Object ... objects){ + if(logger.isErrorEnabled()){ + StringBuilder builder = new StringBuilder(); + builder.append("======").append(title).append("======"); + for (Object object:objects){ + builder.append("\n").append(object); + } + builder.append("\n"); + logger.error(builder.toString()); + } + } + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/DateUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/DateUtils.java new file mode 100644 index 0000000..472cb9f --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/DateUtils.java @@ -0,0 +1,68 @@ +package com.ckeri.boot.db.common.util; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 时间处理工具类,获取指定格式的日期字符串 + * @author yangkaile + * @date 2019-05-30 08:55:13 + */ +public class DateUtils { + /** + * 获取时间字符串 + * @param date + * @return + */ + public static String getDate(Date date){ + SimpleDateFormat simpleDateFormat = + new SimpleDateFormat("yyyy-MM-dd"); + return simpleDateFormat.format(date); + } + public static String getDate(){ + return getDate(new Date()); + } + + /** + * 获取日期时间字符串 + * @param date + * @return + */ + public static String getDateTime(Date date){ + SimpleDateFormat simpleDateFormat = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return simpleDateFormat.format(date); + } + + public static String getDateTime(){ + return getDateTime(new Date()); + } + + public static String getTimeMaskSecond(){ + SimpleDateFormat simpleDateFormat = + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + return simpleDateFormat.format(new Date()); + } + + + /** + * 获取时间标识,年月日时分秒毫秒,用于文件名 + * @param date + * @return + */ + public static String getTimeMask(Date date){ + SimpleDateFormat simpleDateFormat = + new SimpleDateFormat("yyyyMMddHHmmssSSS"); + return simpleDateFormat.format(date); + } + + public static String getTimeMask(){ + return getTimeMask(new Date()); + } + + public static void main(String[] args){ + Console.print("getDate",DateUtils.getDate()); + Console.print("getDateTime",DateUtils.getDateTime()); + Console.print("getTimeMask",DateUtils.getTimeMask()); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/FileUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/FileUtils.java new file mode 100644 index 0000000..0509455 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/FileUtils.java @@ -0,0 +1,120 @@ +package com.ckeri.boot.db.common.util; + +import com.ckeri.boot.db.common.config.PublicConstant; +import net.coobird.thumbnailator.Thumbnails; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; + +/** + * 文件处理工具类,获取文件名、后缀名、保存文件等 + * @author yangkaile + * @date 2019-05-30 09:10:12 + */ +public class FileUtils { + /** + * 文件后缀名分隔符 + */ + public static final String SUFFIX_SPLIT = "."; + + /** + * 获取文件名的后缀,如 jpg/txt等 + * @param fileName + * @return + */ + public static String getSuffix(String fileName){ + return fileName.substring(fileName.lastIndexOf(SUFFIX_SPLIT) + 1); + } + /** + * 获取文件名的后缀和分隔符,如 .jpg/.txt等 + * @param fileName + * @return + */ + public static String getSuffixWithSpilt(String fileName){ + return fileName.substring(fileName.lastIndexOf(SUFFIX_SPLIT)); + } + + + + /** + * 获取原图保存路径 + * @param fileName 文件名 + * @return 完整的保存路径 + */ + public static String getImgPath(String fileName){ + return PublicConstant.nginxPath + PublicConstant.imgPath + fileName; + } + + /** + * 获取原图访问地址 + * @param fileName + * @return + */ + public static String getImgUrl(String fileName){ + return PublicConstant.nginxUrl + PublicConstant.imgPath + fileName; + } + + /** + * 获取缩略图保存路径 + * @param fileName 文件名 + * @return 完整的保存路径 + */ + public static String getThumPath(String fileName){ + return PublicConstant.nginxPath + PublicConstant.thumPath + PublicConstant.THUM_PREFIX + fileName; + } + + /** + * 获取缩略图访问地址 + * @param fileName + * @return + */ + public static String getThumUrl(String fileName){ + return PublicConstant.nginxUrl + PublicConstant.thumPath + PublicConstant.THUM_PREFIX + fileName; + } + + /** + * 保存图片 + * @param file + * @param name + * @return + * @throws IOException + */ + public static String saveImg (MultipartFile file, String name) throws IOException { + //解析文件后缀名 + String suffix = FileUtils.getSuffixWithSpilt(file.getOriginalFilename()); + //构建原图保存路径 + String fileName = name + suffix; + //保存原图 + File img = new File(FileUtils.getImgPath(fileName)); + file.transferTo(img); + return fileName; + } + + /** + * 保存图片和缩略图 + * @param file + * @param name + * @return + * @throws IOException + */ + public static String saveImgAndThum (MultipartFile file,String name) throws IOException{ + //解析文件后缀名 + String suffix = FileUtils.getSuffixWithSpilt(file.getOriginalFilename()); + //构建原图保存路径 + String fileName = name + suffix; + //保存原图 + File img = new File(FileUtils.getImgPath(fileName)); + file.transferTo(img); + + //保存缩略图 + File thum = new File(FileUtils.getThumPath(fileName)); + Thumbnails.of(img).size(PublicConstant.THUM_MAX_WIDTH,PublicConstant.THUM_MAX_HEIGHT).toFile(thum); + + return fileName; + } + + public static void main(String[] args){ + Console.print("getSuffix",getSuffix("abc.jpg")); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/JwtUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/JwtUtils.java new file mode 100644 index 0000000..9c2f881 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/JwtUtils.java @@ -0,0 +1,136 @@ +package com.ckeri.boot.db.common.util; + +import com.ckeri.boot.db.common.config.PublicConstant; +import com.ckeri.boot.db.common.entity.UserInfo; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.JwtBuilder; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; + +import java.util.Date; + +/** + * @author yangkaile + * @date 2020-03-05 17:05:11 + * + * Jwt 工具类,用于生成及解析JWT + */ +public class JwtUtils { + + private static String userNameKey = "userName"; + + private static String userTypeKey = "userType"; + + private static String typeKey = "type"; + + private static String codeKey = "code"; + + /** + * 获取登录的 JWT + * @param userInfo + * @return + */ + public static String getJwtForLogin(UserInfo userInfo){ + return getJwtString(userInfo, PublicConstant.LOGIN_TYPE,null); + } + + public static String getJwtForResetPassword(UserInfo userInfo,String code){ + return getJwtString(userInfo,PublicConstant.RESET_PASSWORD_TYPE,code); + } + + + /** + * 生成 JWT + * 如果是重置密码的JWT,其中包含邮件验证码 + * @param userInfo 用户信息 + * @param type JWT 类型 + * @return + */ + private static String getJwtString(UserInfo userInfo,int type,String code){ + long now=System.currentTimeMillis(); + JwtBuilder jwtBuilder = Jwts.builder() + .setId(userInfo.getId() + "") + //设置应用名 + .setSubject(PublicConstant.appName) + //签发时间 + .setIssuedAt( new Date() ) + //过期时间 + .setExpiration( new Date( now + PublicConstant.JWT_EXP_TIME ) ) + //自定义内容 + .claim(userNameKey,userInfo.getEmail()) + .claim(userTypeKey,userInfo.getType()) + .claim(typeKey,type) + //签名 密钥 + .signWith(SignatureAlgorithm.HS256, PublicConstant.JWT_SIGN_KEY); + if(type == PublicConstant.RESET_PASSWORD_TYPE){ + jwtBuilder.claim(codeKey,code); + } + return jwtBuilder.compact(); + } + + private static Claims getClaims(String jwtString,int type){ + try { + Claims claims = Jwts.parser() + .setSigningKey(PublicConstant.JWT_SIGN_KEY) + .parseClaimsJws(jwtString) + .getBody(); + String subject = claims.getSubject(); + //校验应用名 + if(!subject.equals(PublicConstant.appName)){ + return null; + } + //校验 JWT 类型 + int jwtType = claims.get(typeKey,Integer.class); + if(jwtType != type){ + return null; + } + return claims; + }catch (Exception e){ + Console.error("checkJwt","JWT 解析失败",jwtString,e.getMessage()); + return null; + } + } + + /** + * 从JWT中获取到UserId + * @param jwtString + * @return + */ + public static Integer getUserIdForLogin(String jwtString){ + Claims claims = getClaims(jwtString,PublicConstant.LOGIN_TYPE); + if(claims == null){ + return null; + } + return Integer.parseInt(claims.getId()); + } + + /** + * 从JWT中获取到email + * @param jwtString + * @return + */ + public static String getEmailForResetPassword(String jwtString){ + Claims claims = getClaims(jwtString,PublicConstant.RESET_PASSWORD_TYPE); + if(claims == null){ + return null; + } + return claims.get(userNameKey,String.class); + } + public static String getCodeForResetPassword(String jwtString){ + Claims claims = getClaims(jwtString,PublicConstant.RESET_PASSWORD_TYPE); + if(claims == null){ + return null; + } + return claims.get(codeKey,String.class); + } + + public static Integer getUserTypeForResetPassword(String jwtString){ + Claims claims = getClaims(jwtString,PublicConstant.RESET_PASSWORD_TYPE); + if(claims == null){ + return null; + } + return claims.get(userTypeKey,Integer.class); + } + + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/MetadataUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/MetadataUtils.java new file mode 100644 index 0000000..a38d6d3 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/MetadataUtils.java @@ -0,0 +1,134 @@ +package com.ckeri.boot.db.common.util; + +import com.drew.imaging.ImageProcessingException; +import com.drew.imaging.jpeg.JpegMetadataReader; +import com.drew.imaging.jpeg.JpegProcessingException; +import com.drew.imaging.mp4.Mp4MetadataReader; +import com.drew.metadata.Directory; +import com.drew.metadata.Metadata; +import com.drew.metadata.Tag; +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** + * 多媒体文件元数据工具类,用来解析图片和视频的元数据 + * @author yangkaile + * @date 2019-05-30 15:40:15 + */ +public class MetadataUtils { + /** + * 图片高度 + */ + public static final String IMAGE_HEIGHT = "Exif Image Height"; + /** + * 图片宽度 + */ + public static final String IMAGE_WIDTH = "Exif Image Width"; + /** + * 拍摄时间 + */ + public static final String CREATE_TIME = "Date/Time Original"; + + /** + * 纬度 + */ + public static final String LATITUDE = "GPS Latitude"; + + /** + * 经度 + */ + public static final String LONGITUDE = "GPS Longitude"; + + /** + * 拍摄设备 + */ + public static final String MAKE = "Make"; + + /** + * 设备型号 + */ + public static final String MODEL = "Model"; + + + + /** + * 相机拍摄: + * 拍摄时间 [Exif SubIFD] Date/Time Original + * 图片宽度 [Exif SubIFD] Exif Image Width + * 图片高度 [Exif SubIFD] Exif Image Height + * + * 纬度 [GPS] GPS Latitude - 40° 5' 5.49" + * 经度 [GPS] GPS Longitude - 116° 21' 53.5" + */ + public static Map readJpeg(File file) { + Metadata metadata; + Map result = new HashMap<>(16); + try { + metadata = JpegMetadataReader.readMetadata(file); + Iterator it = metadata.getDirectories().iterator(); + while (it.hasNext()) { + Directory exif = it.next(); + Iterator tags = exif.getTags().iterator(); + //遍历图片Exif信息的,取出需要的信息放入Map中 + while (tags.hasNext()) { + Tag tag = tags.next(); + if(IMAGE_HEIGHT.equals(tag.getTagName())){ + result.put(IMAGE_HEIGHT,tag.getDescription().substring(0,tag.getDescription().indexOf(" "))); + } + if(IMAGE_WIDTH.equals(tag.getTagName())){ + result.put(IMAGE_WIDTH,tag.getDescription().substring(0,tag.getDescription().indexOf(" "))); + } + if(CREATE_TIME.equals(tag.getTagName())){ + result.put(CREATE_TIME,tag.getDescription()); + } + if(LATITUDE.equals(tag.getTagName())){ + result.put(LATITUDE,tag.getDescription()); + } + if(LONGITUDE.equals(tag.getTagName())){ + result.put(LONGITUDE,tag.getDescription()); + } + if(MAKE.equals(tag.getTagName())){ + result.put(MAKE,tag.getDescription()); + } + if(MODEL.equals(tag.getTagName())){ + result.put(MODEL,tag.getDescription()); + } + System.out.println(tag); + } + } + } catch (JpegProcessingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return result; + } + + + public static Map readMp4(File file) { + Metadata metadata; + Map result = new HashMap<>(16); + try { + metadata = Mp4MetadataReader.readMetadata(file); + Iterator it = metadata.getDirectories().iterator(); + while (it.hasNext()) { + Directory exif = it.next(); + Iterator tags = exif.getTags().iterator(); + //遍历图片Exif信息的,取出需要的信息放入Map中 + while (tags.hasNext()) { + Tag tag = tags.next(); + + System.out.println(tag); + } + } + } catch (ImageProcessingException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return result; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/PageUtil.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/PageUtil.java new file mode 100644 index 0000000..0fe5bfc --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/PageUtil.java @@ -0,0 +1,50 @@ +package com.ckeri.boot.db.common.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Aaron Du + * @version V1.0 + * @date 2020/5/23 19:51 + **/ +public class PageUtil { + + private int code=0; + private String msg; + private Long count; //总条数 + private List data = new ArrayList(); //装前台当前页的数据 + //getter/setter方法... + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMsg() { + return msg; + } + + public void setMsg(String msg) { + this.msg = msg; + } + + public Long getCount() { + return count; + } + + public void setCount(Long count) { + this.count = count; + } + + public List getData() { + return data; + } + + public void setData(List data) { + this.data = data; + } +} \ No newline at end of file diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RequestUtil.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RequestUtil.java new file mode 100644 index 0000000..170d1cf --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RequestUtil.java @@ -0,0 +1,194 @@ +package com.ckeri.boot.db.common.util; + +import com.alibaba.fastjson.JSONObject; +import com.ckeri.boot.db.common.config.PublicConstant; +import com.ckeri.boot.db.common.config.RequestConfig; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.RestTemplate; + +import javax.servlet.http.HttpServletRequest; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +/** + * 请求处理工具类,记录请求日志、解析请求参数等 + * @author yangkaile + * @date 2019-10-11 16:19:26 + */ +public class RequestUtil { + + /** + * 记录请求成功的日志(使用json提交参数的请求) + * @param request 请求 + * @param params 请求参数 + * @param response 应答 + */ + public static void successLog(HttpServletRequest request, Map params, ResponseEntity response){ + Console.info("response success",getHeader(request),params,response.getBody()); + } + + /** + * 记录请求失败的日志(使用json提交参数的请求) + * @param request 请求 + * @param params 参数 + * @param response 应答 + */ + private static void errorLog(HttpServletRequest request, Map params, ResponseEntity response){ + Console.error("response success",getHeader(request),params,response.getBody()); + } + + + private static HashMap getHeader(HttpServletRequest request){ + HashMap headerMap = new HashMap<>(16); + //请求的URL地址 + headerMap.put(RequestConfig.URL,request.getRequestURL().toString()); + //请求的资源 + headerMap.put(RequestConfig.URI,request.getRequestURI()); + //请求方式 GET/POST + headerMap.put(RequestConfig.REQUEST_METHOD,request.getMethod()); + + //来访者的IP地址 + headerMap.put(RequestConfig.REMOTE_ADDR,request.getRemoteAddr()); + //来访者的HOST + headerMap.put(RequestConfig.REMOTE_HOST,request.getRemoteHost()); + //来访者的端口 + headerMap.put(RequestConfig.REMOTE_PORT,request.getRemotePort() + ""); + //来访者的用户名 + headerMap.put(RequestConfig.REMOTE_USER,request.getRemoteUser()); + + + //自定义的Header (接口名) + headerMap.put(RequestConfig.METHOD,request.getHeader(RequestConfig.METHOD)); + //自定义的Header (TOKEN) + headerMap.put(RequestConfig.TOKEN,request.getHeader(RequestConfig.TOKEN)); + return headerMap; + } + + /** + * 读取 Body 中的参数,并将其转换成 Map + * @param request + * @return + */ + public static Map getBodyParams(HttpServletRequest request){ + BufferedReader streamReader = null; + StringBuilder responseStrBuilder = new StringBuilder(); + String inputStr; + try { + streamReader = new BufferedReader( new InputStreamReader(request.getInputStream(), "UTF-8")); + while ((inputStr = streamReader.readLine()) != null) { + responseStrBuilder.append(inputStr); + } + + String str = responseStrBuilder.toString(); + if(str.isEmpty()){ + return null; + } + JSONObject jsonObject = JSONObject.parseObject(str); + Map params = jsonObject.getInnerMap(); + if(params == null || params.size() < 1){ + return null; + } + return params; + } catch (Exception e) { + e.printStackTrace(); + return null; + }finally { + try{ + streamReader.close(); + }catch (Exception e){ + e.printStackTrace(); + } + } + } + + + public static Map getParam(HttpServletRequest request){ + Map paramMap = new HashMap<>(16); + //request对象封装的参数是以Map的形式存储的 + Map map = request.getParameterMap(); + for(Map.Entry entry :map.entrySet()){ + String paramName = entry.getKey(); + String paramValue = ""; + String[] paramValueArr = entry.getValue(); + for (int i = 0; paramValueArr!=null && i < paramValueArr.length; i++) { + if (i == paramValueArr.length-1) { + paramValue += paramValueArr[i]; + }else { + paramValue += paramValueArr[i]+","; + } + } + paramMap.put(paramName,paramValue); + } + if(paramMap.size() == 0){ + return null; + } + return paramMap; + } + + /** + * 根据请求参数获取到URL,会解析请求中的 JWT,并将解析出的 UserId 拼接在请求中 + * @param request + * @return + */ + private static String getUrl(Map params,HttpServletRequest request){ + //从 JWT 中解析出 UserId + Integer userId = JwtUtils.getUserIdForLogin(request.getHeader(RequestConfig.TOKEN)); + HashMap headers = getHeader(request); + StringBuilder builder = new StringBuilder(); + + builder.append(PublicConstant.serviceUrl).append("/") + .append(headers.get(RequestConfig.METHOD)); + builder.append("?"); + //请求参数中添加 userId + builder.append(PublicConstant.USER_ID_KEY).append("=").append(userId).append("&"); + if(params == null){ + return builder.toString(); + } + for(String key :params.keySet()){ + //过滤掉请求中的 userId + if(PublicConstant.USER_ID_KEY.equals(key)){ + continue; + } + builder.append(key) + .append("={") + .append(key) + .append("}&"); + } + Console.info(builder.toString()); + return builder.toString(); + } + + public static ResponseEntity doGet(HttpServletRequest request,Map params,RestTemplate restTemplate){ + ResponseEntity responseEntity ; + try { + String url = getUrl(params,request); + if(params == null){ + responseEntity = restTemplate.getForEntity(url, String.class); + }else{ + responseEntity = restTemplate.getForEntity(url, String.class,params); + } + successLog(request,params,responseEntity); + }catch (Exception e){ + responseEntity = ResponseUtils.getResponseFromException(e); + errorLog(request,params,responseEntity); + } + return responseEntity; + } + + + + public static ResponseEntity doPost(HttpServletRequest request,Map params,RestTemplate restTemplate){ + ResponseEntity responseEntity; + try { + responseEntity = restTemplate.postForEntity(getUrl(params,request),null,String.class,params); + successLog(request,params,responseEntity); + }catch (Exception e){ + responseEntity = ResponseUtils.getResponseFromException(e); + errorLog(request,params,responseEntity); + } + return responseEntity; + } + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/ResponseUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/ResponseUtils.java new file mode 100644 index 0000000..b80268f --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/ResponseUtils.java @@ -0,0 +1,44 @@ +package com.ckeri.boot.db.common.util; + +import com.ckeri.boot.db.common.response.Response; +import com.ckeri.boot.db.common.response.ResultData; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.client.HttpClientErrorException; + +/** + * 应答解析工具类 + * @author yangkaile + * @date 2019-10-28 14:16:07 + */ +public class ResponseUtils { + /** + * 根据组件返回的错误码重组应答报文 + * @param exception + * @return + */ + public static ResponseEntity getResponseFromException(Exception exception){ + ResponseEntity response; + if(exception instanceof HttpClientErrorException){ + HttpClientErrorException errorException = (HttpClientErrorException) exception; + switch (errorException.getStatusCode()){ + case FORBIDDEN: response = Response.forbidden(); break; + case BAD_REQUEST: response = Response.badRequest();break; + case UNAUTHORIZED: response = Response.unauthorized();break; + case INTERNAL_SERVER_ERROR: response = Response.error();break; + default:{ + ResultData resultData = ResultData.error("ERROR"); + response = ResponseEntity.status(errorException.getStatusCode()).contentType(MediaType.APPLICATION_JSON).body(resultData); + } + } + + }else { + response = Response.badRequest(); + } + return response; + } + + public static ResultData getResultDataFromException(HttpClientErrorException exception){ + return (ResultData)getResponseFromException(exception).getBody(); + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RestTemplateUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RestTemplateUtils.java new file mode 100644 index 0000000..fd39142 --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/RestTemplateUtils.java @@ -0,0 +1,27 @@ +package com.ckeri.boot.db.common.util; + +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import com.ckeri.boot.db.common.HttpsClientRequestFactory; +import org.springframework.web.client.RestTemplate; + +/** + * @author yangkaile + * @date 2020-03-19 09:33:03 + */ +public class RestTemplateUtils { + + public static RestTemplate getHttpsTemplate(){ + RestTemplate restTemplate = new RestTemplate(new HttpsClientRequestFactory()); + return init(restTemplate); + } + public static RestTemplate getTemplate(){ + RestTemplate restTemplate = new RestTemplate(); + return init(restTemplate); + } + + private static RestTemplate init(RestTemplate restTemplate){ + restTemplate.getMessageConverters().clear(); + restTemplate.getMessageConverters().add(new FastJsonHttpMessageConverter()); + return restTemplate; + } +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/SendEmailUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/SendEmailUtils.java new file mode 100644 index 0000000..afde36a --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/SendEmailUtils.java @@ -0,0 +1,175 @@ +package com.ckeri.boot.db.common.util; + +import com.ckeri.boot.db.common.config.PublicConstant; +import com.ckeri.boot.db.common.entity.EmailLog; + +import javax.mail.Message; +import javax.mail.Session; +import javax.mail.Transport; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import java.util.Properties; + +/** + * 邮件发送工具类 + * SendEmailUtils.getSender( + * myConfig.mailServerHost, + * myConfig.mailServerUser, + * myConfig.mailServerPassword) + * .sendSimpleMail("atomiclong@aliyun.com", + * "你好", + * "邮件内容"); + * @author yangkaile + * @date 2018-09-11 14:34:03 + */ +public class SendEmailUtils { + /** + * 邮件验证码标题 + */ + public static final String TITLE ="【From】" + PublicConstant.appName; + + /** + * 邮件验证码正文内容 + */ + public static final String RegisterBody = + "验证码:%1$s,用于账号: %2$s 注册,泄露有风险。" + + PublicConstant.EMAIL_CODE_TIME + "分钟内使用有效。"; + + public static final String LoginBody = + "验证码:%1$s,用于账号: %2$s 登录,泄露有风险。" + + PublicConstant.EMAIL_CODE_TIME + "分钟内使用有效。"; + + public static final String ResetPasswordBody = + "验证码:%1$s,用于账号: %2$s 找回密码,泄露有风险。" + + PublicConstant.EMAIL_CODE_TIME + "分钟内使用有效。"; + + public static final String ResetPasswordLinkBody = + "您好!我们已收到您的账号: %1$s 重置密码的申请," + + "请点击链接重置密码: " + PublicConstant.webUrl + + "/ResetPassword/%2$s ,该链接使用一次后失效"; + + + public static Session session= null; + + /** + * 初始化Session + * @return + */ + private static Session initSession(){ + if(session == null) { + try { + Properties prop = new Properties(); + //邮件服务器地址 + prop.setProperty("mail.host", PublicConstant.mailServerHost); + //邮件发送协议 + prop.setProperty("mail.transport.protocol", "smtp"); + //是否需要身份验证 + prop.setProperty("mail.smtp.auth", "true"); + + prop.setProperty("mail.smtp.socketFactory.class","javax.net.ssl.SSLSocketFactory"); + prop.setProperty("mail.smtp.socketFactory.port", "465"); + prop.setProperty("mail.smtp.port", "465"); + //创建session + session = Session.getInstance(prop); + //开启Session的debug模式,这样就可以查看到程序发送Email的运行状态 + session.setDebug(true); + } catch (Exception e) { + e.printStackTrace(); + } + } + return session; + } + + /** + * 发送简单邮件 + * @param toEmailAddress 收件人地址 + * @param title 邮件标题 + * @param content 邮件内容 + * @throws Exception + */ + private static void sendSimpleMail(String toEmailAddress,String title,String content) + throws Exception { + Session session = initSession(); + //创建邮件对象 + MimeMessage message = new MimeMessage(session); + //指明邮件的发件人 + message.setFrom(new InternetAddress(PublicConstant.mailServerUser)); + //指明邮件的收件人 + message.setRecipient(Message.RecipientType.TO, new InternetAddress(toEmailAddress)); + //邮件的标题 + message.setSubject(title); + //邮件的文本内容 + message.setContent(content, "text/html;charset=UTF-8"); + //返回创建好的邮件对象 + Transport transport = session.getTransport(); + //使用邮箱的用户名和密码连上邮件服务器,发送邮件时,发件人需要提交邮箱的用户名和密码给smtp服务器,用户名和密码都通过验证之后才能够正常发送邮件给收件人 + transport.connect(PublicConstant.mailServerHost,PublicConstant.mailServerUser,PublicConstant.mailServerPassword); + transport.sendMessage(message, message.getAllRecipients()); + transport.close(); + } + + /** + * 发送邮件验证码 + * 1.随机生成指定位数的验证码 + * 2.创建邮件实体类,设置收件人地址、邮件标题、邮件内容、验证码 + * 3.发送邮件并记录发送结果 + * 4.返回包含发送结果的邮件实体类 + * @param email 收件人邮箱 + * @return 邮件实体类EmailEntity + */ + public static EmailLog sendVCode(int type, String email, String code){ + EmailLog entity = new EmailLog(); + entity.setEmail(email); + entity.setType(type); + entity.setTitle(TITLE); + String body; + switch (type){ + case PublicConstant.REGISTER_TYPE : + body = String.format(RegisterBody,code,email); + break; + case PublicConstant.LOGIN_TYPE : + body = String.format(LoginBody,code,email); + break; + case PublicConstant.RESET_PASSWORD_TYPE : + body = String.format(ResetPasswordBody,code,email); + break; + default:return null; + } + entity.setContent(body); + entity.setCode(code); + try { + sendSimpleMail(entity.getEmail(),entity.getTitle(),entity.getContent()); + }catch (Exception e){ + Console.error("send sendVerificationCode error :",e.getMessage()); + entity.setResult(e.getMessage()); + entity.setStatusCode(PublicConstant.FAILED); + } + return entity; + } + + /** + * 发送重置验证码邮件,该邮件中会包含一个重置密码的链接 + * @param email + * @return + */ + public static EmailLog sendResetPasswordEmail(String email,String code,String token){ + EmailLog entity = new EmailLog(); + entity.setEmail(email); + entity.setType(PublicConstant.RESET_PASSWORD_TYPE ); + entity.setTitle(TITLE); + String body = String.format(ResetPasswordLinkBody,email,token); + + entity.setContent(body); + entity.setCode(code); + try { + sendSimpleMail(entity.getEmail(),entity.getTitle(),entity.getContent()); + }catch (Exception e){ + Console.error("send sendResetPasswordEmail error :",e.getMessage()); + entity.setResult(e.getMessage()); + entity.setStatusCode(PublicConstant.FAILED); + } + return entity; + } + + +} diff --git a/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/StringUtils.java b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/StringUtils.java new file mode 100644 index 0000000..3f8bdcd --- /dev/null +++ b/note-common/common-db/src/main/java/com/ckeri/boot/db/common/util/StringUtils.java @@ -0,0 +1,214 @@ +package com.ckeri.boot.db.common.util; + +import java.util.Random; +import java.util.UUID; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 字符串处理工具类,生成随机数、格式校验、判断空字符串等 + * @author yangkaile + * @date 2018-08-28 16:15:10 + */ +public class StringUtils { + + /** + * 纯数字集合 + */ + private static final String numbersChar = "0123456789"; + + /** + * 大小写字母、数字集合 + */ + private static final String allChar = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + /** + * 手机号校验规则:1开头的11位数字 + */ + private static final String PHONE_NUMBER_PATTERN = "^1+\\d{10}$"; + + /** + * 用户名校验规则:允许字母、数字、下划线 + */ + private static final String USER_NAME_PATTERN = "^[a-zA-Z0-9_]+$"; + + /** + * 邮箱校验规则:**@**.** + */ + private static final String EMAIL_ADDRESS_PATTERN = "^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\])|" + + "(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$"; + + /** + * 校验是否是用户名 + * @param string + * @return + */ + public static boolean isUserName(String string) { + if(isEmpty(string)){ + return false; + } + Pattern pattern = Pattern.compile(USER_NAME_PATTERN); + Matcher matcher = pattern.matcher(string); + return matcher.matches(); + } + + /** + * 校验是否是手机号 + * @param string + * @return + */ + public static boolean isPhoneNo(String string) { + if(isEmpty(string)){ + return false; + } + Pattern pattern = Pattern.compile(PHONE_NUMBER_PATTERN); + Matcher matcher = pattern.matcher(string); + return matcher.matches(); + + } + + + public static boolean notPhoneOrEmail(String string){ + return !isEmail(string) && !isPhoneNo(string); + } + + public static boolean isPhoneOrEmail(String string){ + return isEmail(string) || isPhoneNo(string); + } + + /** + * 校验是否是邮箱 + * @param string + * @return + */ + public static boolean isEmail(String string) { + if(isEmpty(string)){ + return false; + } + Pattern pattern = Pattern.compile(EMAIL_ADDRESS_PATTERN); + Matcher matcher = pattern.matcher(string); + return matcher.matches(); + } + + public static boolean notEmail(String string){ + return !isEmail(string); + } + + + /** + * 只要有一个为空的,就返回 true + * 判断一系列字符串中是否有空的(包含:空字符串、null、纯空格字符) + * @param parameters 需要判断的字符串,可以是多个 + * @return + */ + public static boolean isEmpty(Object... parameters){ + for(Object param:parameters){ + if(param == null){ + return true; + } + if(param instanceof String){ + String str = (String) param; + if(str.isEmpty()){ + return true; + } + } + } + return false; + } + + /** + * 仅当所有元素都有值才返回 true + * 判断一组对象中没有空值,仅当所有参数都有值时才会返回 true + * @param parameters + * @return + */ + public static boolean noEmpty(Object... parameters){ + return !isEmpty(parameters); + } + + /** + * 只要有一个元素有值,就返回 true + * 判断一组元素是否有值 + * @param parameters + * @return + */ + public static boolean hasValue(Object ... parameters){ + for(Object param:parameters){ + if(param != null){ + if(param instanceof String){ + String str = (String)param; + return !str.isEmpty(); + }else{ + return true; + } + } + + } + return false; + } + + /** + * 仅当所有元素都没值才返回true + * @param parameters + * @return + */ + public static boolean noValue(Object ... parameters){ + return !hasValue(parameters); + } + + + /** + * 将字符串的首字母转大写 + * @param str 需要转换的字符串 + * @return + */ + public static String captureName(String str) { + // 进行字母的ascii编码前移,效率要高于截取字符串进行转换的操作 + char[] cs=str.toCharArray(); + cs[0]-=32; + return String.valueOf(cs); + } + + /** + * 生成指定长度的数字字符串 + * @param length + * 字符串长度 + * @return + */ + public static String getNumberString(int length) { + StringBuffer sb = new StringBuffer(); + Random random = new Random(); + for (int i = 0; i < length; i++) { + sb.append(numbersChar.charAt(random.nextInt(numbersChar.length()))); + } + return sb.toString(); + } + + /** + * 生成指定长度的字符串(含大小写字母及数字) + * @param length + * @return + */ + public static String getAllCharString(int length){ + StringBuffer sb = new StringBuffer(); + Random random = new Random(); + for (int i = 0; i < length; i++) { + sb.append(allChar.charAt(random.nextInt(allChar.length()))); + } + return sb.toString(); + } + + /** + * 获取UUID(32位的字母数字的集合) + * @return + */ + public static String getUUID(){ + return UUID.randomUUID().toString().replace("-","").toUpperCase(); + } + + public static void main(String[] args){ + Console.print("",isEmail("guyexing@cc.com")); + Console.print("UUID",getUUID()); + } + +} diff --git a/note-common/common-util/pom.xml b/note-common/common-util/pom.xml new file mode 100644 index 0000000..9b1bd74 --- /dev/null +++ b/note-common/common-util/pom.xml @@ -0,0 +1,13 @@ + + + + keller + com.cheri + 1.0-SNAPSHOT + ../../pom.xml + + 4.0.0 + common-util + \ No newline at end of file diff --git a/note-common/pom.xml b/note-common/pom.xml new file mode 100644 index 0000000..3bba201 --- /dev/null +++ b/note-common/pom.xml @@ -0,0 +1,14 @@ + + + + keller + com.cheri + 1.0-SNAPSHOT + + 4.0.0 + note-common + 工具类 + + \ No newline at end of file -- Gitee