diff --git a/note-admin/src/main/resources/application-dev.properties b/note-admin/src/main/resources/application-dev.properties
index 58b8e4b4113e0afb6fe4b9e578be6f1aeb793ccc..ca9c8cc901af2cb53cf7016e3bbfff62bfbac0b4 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 0000000000000000000000000000000000000000..0fcb6dd67435c7b64e4aab533bb4a91ef7be81c7
--- /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 0000000000000000000000000000000000000000..d4e2d61cb603805b9270a22159cc207fbff3eff7
--- /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 0000000000000000000000000000000000000000..85320184cb32a6425d70ad58913fce6dd7e009b2
--- /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 0000000000000000000000000000000000000000..99ec15dc76aa89c12f1bd5572076b0fee0ed8f36
--- /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 0000000000000000000000000000000000000000..035c39e1cac4e098135e0031c875f55096b976f6
--- /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 0000000000000000000000000000000000000000..057e019ad2b8286282e674299c6bc6514d902c3a
--- /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 0000000000000000000000000000000000000000..47df0b8b2649855c0e01deb94db9ea26cd95f960
--- /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 0000000000000000000000000000000000000000..b0da59752754dc721722e16f1dc0aa47155d152d
--- /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 0000000000000000000000000000000000000000..457f0f60fc79f4a2e5e3a9784d58325cc1fda8ab
--- /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 0000000000000000000000000000000000000000..3c9bd89da7b04527f8baeaa489a03b9a8d6b0931
--- /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 0000000000000000000000000000000000000000..91c902e9694e5982f5639339d0fef746f516c465
--- /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 0000000000000000000000000000000000000000..e4adecb0d6eabad0b952a45bf955361e0c459895
--- /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 0000000000000000000000000000000000000000..b82a6e349485870a71a3f275cec7491e10b4daf6
--- /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 0000000000000000000000000000000000000000..b8da2bc48311374b4085cb9fc5d18d4078a122e5
--- /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 0000000000000000000000000000000000000000..ce17924f8d4dff32c668e778d87dbc8c09e447e3
--- /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 0000000000000000000000000000000000000000..5ffc75e58fa4aad7b4e5fb6a8bec21a7d329a7f4
--- /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 0000000000000000000000000000000000000000..a618dcb701836e1a9d295b46dce103b784c5f113
--- /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 0000000000000000000000000000000000000000..c5b3da2d907a9126b81b670b90935b847e7e4076
--- /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 0000000000000000000000000000000000000000..bcc9c9c913eb7f8408d37cbf52ca96a901a52781
--- /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 0000000000000000000000000000000000000000..b65bb8044ff630c0c1e47587126b707f10b5d775
--- /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 0000000000000000000000000000000000000000..a96b1d5264fa7f7e8b8b871d3f77f469c6be9cb6
--- /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 0000000000000000000000000000000000000000..d29c16d40df145a9779ba5079bf164317d05f655
--- /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 0000000000000000000000000000000000000000..34cb76a8ea51674eccd35d9cec52156a23a9ea12
--- /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 0000000000000000000000000000000000000000..4405b23524fa92db3377c0629f22fd34a3d02524
--- /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 0000000000000000000000000000000000000000..b840e8c995df9e4dee372245ceba732ff3a9cdde
--- /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 0000000000000000000000000000000000000000..715eb43e679d1c8ab5886681dd6bf0f7f3aae0ad
--- /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 0000000000000000000000000000000000000000..32ba4b0502deef496f4ee8a66f94829cb34c26fe
--- /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 0000000000000000000000000000000000000000..479c8b1240cbb25d436d61ee3dcd39249c64ee93
--- /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 0000000000000000000000000000000000000000..4dd437fadfaf5ea3ea30999b7353c51eb0a74774
--- /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 0000000000000000000000000000000000000000..ceea76fb86027b441f68b158358e1fb965de6aec
--- /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 0000000000000000000000000000000000000000..4d467de940b9937e12ec61179b180fbdd9c3da0e
--- /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 0000000000000000000000000000000000000000..f085872792e4ccdda9f49de21e37dacedbd70d33
--- /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 0000000000000000000000000000000000000000..e04b29bb33b8241af3a5071382c5c4192dea5484
--- /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 0000000000000000000000000000000000000000..99e079efa5aac4ebbd9b6703388e711c43514e7a
--- /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 0000000000000000000000000000000000000000..4aca4c8e48c47920f3e2f9eb34cae79553cc0d12
--- /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 0000000000000000000000000000000000000000..964790268ac3dd661e452d6285803ec209f0b734
--- /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 0000000000000000000000000000000000000000..8c6423f534147575248aec3d1bd4e41a84f89348
--- /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 0000000000000000000000000000000000000000..472cb9fc74fe3a8fd00282bed17f410f8c0a72b9
--- /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 0000000000000000000000000000000000000000..050945549cde43a9dd78002d0ba77c7bf2a73ec7
--- /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 0000000000000000000000000000000000000000..9c2f881bcb63071a291ae73d8f6e67304b9db250
--- /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 0000000000000000000000000000000000000000..a38d6d3282354397e82091d1375d01e411a0d27d
--- /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 0000000000000000000000000000000000000000..0fe5bfc59f8fa7dc73187dc97678a4418a0e68db
--- /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 0000000000000000000000000000000000000000..170d1cf9166907b5cddcd85ac8e6e21ae9fe3a01
--- /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 0000000000000000000000000000000000000000..b80268fe9b81a4ff5a736599fda1768d6b817dc4
--- /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 0000000000000000000000000000000000000000..fd39142d9dbbe53c87eb36469aad746b1d08dbd9
--- /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 0000000000000000000000000000000000000000..afde36aaedc23c71e988051cbffab43e4809140a
--- /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 0000000000000000000000000000000000000000..3f8bdcd04821173cc7a1b5a6077a7ff68cd25c71
--- /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 0000000000000000000000000000000000000000..9b1bd74e511d866dd794da5f1393bb86faf90fd7
--- /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 0000000000000000000000000000000000000000..3bba201c454b49f4a357ef0dfcbba21bcbbcf255
--- /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