diff --git a/smtweb-framework/.gitignore b/smtweb-framework/.gitignore
new file mode 100644
index 0000000..59bb4c9
--- /dev/null
+++ b/smtweb-framework/.gitignore
@@ -0,0 +1,27 @@
+# ---> Java
+# Compiled class file
+*.class
+
+# Log file
+*.log
+
+# BlueJ files
+*.ctxt
+
+# Mobile Tools for Java (J2ME)
+.mtj.tmp/
+
+# Package Files #
+*.jar
+*.war
+*.nar
+*.ear
+*.zip
+*.tar.gz
+*.rar
+
+# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
+hs_err_pid*
+
+.idea
+*.iml
diff --git a/smtweb-framework/pom.xml b/smtweb-framework/pom.xml
new file mode 100644
index 0000000..f4a9585
--- /dev/null
+++ b/smtweb-framework/pom.xml
@@ -0,0 +1,34 @@
+
+
+ 4.0.0
+
+ cc.smtweb
+ smtweb-framework
+ pom
+ 2.2.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.3.1.RELEASE
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 1.8
+ 1.8
+ true
+
+
+
+ sw-framework-core
+ sw-framework-auth
+ sw-framework-file
+ sw-framework-web
+ ../smtweb-system/sw-system-bpm
+
+
diff --git a/smtweb-framework/sw-framework-auth/pom.xml b/smtweb-framework/sw-framework-auth/pom.xml
new file mode 100644
index 0000000..e376dcd
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/pom.xml
@@ -0,0 +1,132 @@
+
+
+ cc.smtweb
+ sw-framework-auth
+ 2.2.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.6
+
+
+
+ 4.0.0
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ cc.smtweb
+ sw-framework-core
+ 2.2.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-test
+ test
+
+
+
+ org.junit.platform
+ junit-platform-launcher
+ 1.6.2
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.6.2
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.6.2
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+ 5.6.2
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.6.2
+ test
+
+
+ org.springframework
+ spring-test
+ 5.2.7.RELEASE
+ test
+
+
+
+ org.mockito
+ mockito-all
+ 1.10.19
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+ verify
+
+ jar-no-fork
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+ 2.6
+
+
+ config/*.yaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nexus-releases
+ Nexus Release Repository
+ http://47.92.149.153:7000/repository/maven-releases/
+
+
+ nexus-snapshots
+ Nexus Snapshot Repository
+ http://47.92.149.153:7000/repository/maven-snapshots/
+
+
+
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/captcha/ImageMaker.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/captcha/ImageMaker.java
new file mode 100644
index 0000000..5cd1f42
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/captcha/ImageMaker.java
@@ -0,0 +1,66 @@
+package cc.smtweb.framework.auth.captcha;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+
+public class ImageMaker {
+ private static final String signChar = "()+-*/=";
+
+ // 生成png图片
+ public void make() throws IOException {
+ int fontHeight = 34;
+ int width = 19;
+ int height = fontHeight * (62 + signChar.length());
+ // 创建BufferedImage对象
+
+ BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ // ---------- 增加下面的代码使得背景透明 -----------------
+ Graphics2D g2d = image.createGraphics();
+ image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
+ g2d.dispose();
+
+ // 画图
+ g2d = image.createGraphics();
+ g2d.setColor(new Color(0,0,0));
+
+ // 画图
+ Font font = new Font("Courier New", Font.BOLD, 30);
+ g2d.setFont(font);
+
+ System.out.println(font.getMaxCharBounds(g2d.getFontRenderContext()));
+
+ int top = 25;
+ for (int i = 0; i < 10; i++) {
+ g2d.drawString(i + "", 0, top);
+ top += fontHeight;
+ }
+
+ for (int i = 0; i < 26; i++) {
+ g2d.drawString((char)(i + (int)'a') + "", 0, top);
+ top += fontHeight;
+ }
+
+ for (int i = 0; i < 26; i++) {
+ g2d.drawString((char)(i + (int)'A') + "", 0, top);
+ top += fontHeight;
+ }
+
+ for (int i = 0; i < signChar.length(); i++) {
+ g2d.drawString(signChar.charAt(i) + "", 0, top);
+ top += fontHeight;
+ }
+
+ // 释放对象
+ g2d.dispose();
+
+ // 保存文件
+ ImageIO.write(image, "png", new File("/var/tmp/test.png"));
+ }
+
+ public static void main(String[] args) throws IOException {
+ new ImageMaker().make();
+ }
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/spring/AuthAutoConfiguration.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/spring/AuthAutoConfiguration.java
new file mode 100644
index 0000000..aec848f
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/spring/AuthAutoConfiguration.java
@@ -0,0 +1,21 @@
+package cc.smtweb.framework.auth.spring;
+
+import cc.smtweb.framework.core.mvc.config.ControllerConfig;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author kevin
+ */
+@Configuration
+@ComponentScan
+public class AuthAutoConfiguration {
+
+ /** 配置自定义service扫描路径 {module}/{service}/{method} */
+ @Bean
+ public ControllerConfig authControllerConfig() {
+ return new ControllerConfig("auth", "cc.smtweb.framework.auth.web");
+ }
+
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/spring/cache/RealmCache.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/spring/cache/RealmCache.java
new file mode 100644
index 0000000..313377a
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/spring/cache/RealmCache.java
@@ -0,0 +1,60 @@
+package cc.smtweb.framework.auth.spring.cache;
+
+import cc.smtweb.framework.core.annotation.SwCache;
+import cc.smtweb.framework.core.cache.AbstractCache;
+import cc.smtweb.framework.core.db.jdbc.JdbcEngine;
+import cc.smtweb.framework.core.mvc.realm.service.PermChecker;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.util.*;
+
+/**
+ * 用户权限集合缓存器,@todo 权限部分需要重写
+ * @author xkliu
+ */
+@Log4j2
+@SwCache(ident = "PERM_CHECKER", title = "用户权限")
+public class RealmCache extends AbstractCache {
+ @Autowired
+ private JdbcEngine dbEngine;
+
+ private static final long ENTERPRISE_ADMIN_ID = 1;
+
+ @Override
+ protected String getId(PermChecker bean) {
+ return "1";//todo
+ }
+
+ @Override
+ protected List loadAll() {
+ return null;
+ }
+
+
+ protected PermChecker load(Long key) {
+ // admin
+ if (key == ENTERPRISE_ADMIN_ID) {
+ return PermChecker.build(new HashSet<>(Collections.singletonList("*")));
+ }
+
+ // TODO: 合并相同角色,自己到缓存里面获取
+ Set permissions = new HashSet<>();
+
+ List permList = dbEngine.queryStringList("SELECT menu_api_perm FROM sys_menu WHERE menu_id in\n" +
+ "(SELECT rmp_menu_id from sys_role_menu_privilege WHERE rmp_role_id in\n" +
+ "(SELECT role_id FROM sw_user.sys_role WHERE role_id IN" +
+ "(SELECT ur_role_id FROM sw_user.sys_user_role WHERE ur_user_id=?)))", key);
+
+ if (permList != null) {
+ for (String perm: permList) {
+ for (String item: perm.split(",")) {
+ permissions.add(item.trim());
+ }
+ }
+ }
+
+ return PermChecker.build(permissions);
+ }
+
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/LoginAckVO.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/LoginAckVO.java
new file mode 100644
index 0000000..d0d6a33
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/LoginAckVO.java
@@ -0,0 +1,11 @@
+package cc.smtweb.framework.auth.web.entity;
+
+import lombok.Data;
+
+@Data
+public class LoginAckVO {
+ private Long userId;
+ private String userAvatar;
+ private String userName;
+ private String token;
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/LoginVO.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/LoginVO.java
new file mode 100644
index 0000000..f71673a
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/LoginVO.java
@@ -0,0 +1,12 @@
+package cc.smtweb.framework.auth.web.entity;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class LoginVO implements Serializable {
+ private String username;
+
+ private String password;
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/MenuPO.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/MenuPO.java
new file mode 100644
index 0000000..9016cb5
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/MenuPO.java
@@ -0,0 +1,29 @@
+package cc.smtweb.framework.auth.web.entity;
+
+import cc.smtweb.framework.core.annotation.SwColumn;
+import cc.smtweb.framework.core.annotation.SwTable;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@SwTable("sw_user.sys_menu")
+public class MenuPO implements Serializable {
+ @SwColumn(type={SwColumn.Type.ID})
+ private Long menuId;
+
+ @SwColumn(type={SwColumn.Type.PARENT_ID})
+ private Long menuParentId;
+
+ private String menuName;
+
+ private Long menuSiteId;
+
+
+ private String menuPermiss;
+
+ private String menuUrl;
+
+ @SwColumn(type={SwColumn.Type.ORDER})
+ private Integer menuSort;
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/UserPO.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/UserPO.java
new file mode 100644
index 0000000..e73b405
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/entity/UserPO.java
@@ -0,0 +1,28 @@
+package cc.smtweb.framework.auth.web.entity;
+
+import cc.smtweb.framework.core.annotation.SwColumn;
+import cc.smtweb.framework.core.annotation.SwTable;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@SwTable("sw_user.sys_user")
+public class UserPO implements Serializable {
+ @SwColumn(type={SwColumn.Type.ID})
+ private Long userId;
+
+ private String userNickCode;
+
+ private String userNickName;
+
+ private Long userCreatePartyId;
+
+ private String userPwd;
+
+ private String userPhone;
+
+ private Integer userStatus;
+
+ private String userAvatar;
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/service/AuthService.java b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/service/AuthService.java
new file mode 100644
index 0000000..4fbb2db
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/java/cc/smtweb/framework/auth/web/service/AuthService.java
@@ -0,0 +1,89 @@
+package cc.smtweb.framework.auth.web.service;
+
+import cc.smtweb.framework.auth.web.entity.LoginAckVO;
+import cc.smtweb.framework.auth.web.entity.LoginVO;
+import cc.smtweb.framework.auth.web.entity.UserPO;
+import cc.smtweb.framework.core.*;
+import cc.smtweb.framework.core.annotation.*;
+import cc.smtweb.framework.core.session.SessionManager;
+import cc.smtweb.framework.core.session.UserSession;
+import cc.smtweb.framework.core.db.DbEngine;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang3.StringUtils;
+
+@Slf4j
+@SwService
+public class AuthService {
+ @SwParam
+ private DbEngine dbEngine;
+
+ @SwParam
+ private SessionManager sessionManager;
+
+ @SwPerm(SwPerm.NONE)
+ public R login(@SwBody LoginVO loginPO) {
+ if (StringUtils.isBlank(loginPO.getUsername())) {
+ return R.error("账号不能为空");
+ }
+
+ if (StringUtils.isBlank(loginPO.getPassword())) {
+ return R.error("密码不能为空");
+ }
+
+ UserPO user = dbEngine.queryEntity("select user_id,user_nick_name,user_nick_code,user_pwd,user_create_party_id from sw_user.sys_user where user_nick_code=?", UserPO.class, loginPO.getUsername());
+
+ if (user == null) {
+ return R.error("账号不存在");
+ }
+
+ // digest:md5("goodpj" + user.userId + password)
+ String pass = DigestUtils.md5Hex("goodpj" + user.getUserId() + loginPO.getPassword());
+
+ if (!pass.equals(user.getUserPwd())) {
+ return R.error("账号或者密码出错");
+ }
+
+ UserSession userSession = new UserSession();
+ userSession.setUserId(user.getUserId());
+ userSession.setSiteId(user.getUserCreatePartyId());
+
+ String token = sessionManager.login(userSession);
+
+ LoginAckVO data = new LoginAckVO();
+
+ data.setUserId(user.getUserId());
+ data.setUserName(user.getUserNickName());
+ data.setUserAvatar(user.getUserAvatar());
+ data.setToken(token);
+
+ return R.success(data);
+ }
+
+ @SwPerm()
+ public R ping(@SwParam("msg") String msg) {
+ return R.success(msg);
+ }
+
+ @SwPerm("user:edit")
+ public R config(@SwParam("username") String username) {
+ return R.success("config: " + username);
+ }
+
+
+ /**
+ * 退出登录
+ * @return code
+ */
+ public R logout() {
+ sessionManager.logout();
+ return R.success();
+ }
+
+ // defaultRun 命名的函数是默认函数
+// @SwPerm(SwPerm.NONE)
+// public R defaultRun(@SwPathParam String path) {
+// return R.success(path).put("dao", authDao);
+// }
+
+}
diff --git a/smtweb-framework/sw-framework-auth/src/main/resources/META-INF/spring.factories b/smtweb-framework/sw-framework-auth/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000..82bd9bb
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ cc.smtweb.framework.auth.spring.AuthAutoConfiguration
diff --git a/smtweb-framework/sw-framework-auth/src/main/resources/auth/courier_new_34_19.png b/smtweb-framework/sw-framework-auth/src/main/resources/auth/courier_new_34_19.png
new file mode 100644
index 0000000..44eada2
Binary files /dev/null and b/smtweb-framework/sw-framework-auth/src/main/resources/auth/courier_new_34_19.png differ
diff --git a/smtweb-framework/sw-framework-auth/src/main/resources/config/application-dev.yaml b/smtweb-framework/sw-framework-auth/src/main/resources/config/application-dev.yaml
new file mode 100644
index 0000000..2422f31
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/resources/config/application-dev.yaml
@@ -0,0 +1,64 @@
+smtweb:
+ machine-id: 1
+ file:
+ local-path: /data/files/
+ host: http://127.0.0.1
+ url: http://127.0.0.1:8888/files/
+ db:
+ default:
+ rule:
+ prefix: _smt_
+ replace: smt_
+server:
+ port: 8888
+ servlet:
+ context-path: /
+feign:
+ hystrix:
+ enabled: false
+logging:
+ level:
+ root: INFO
+ cc.smtweb: DEBUG
+spring:
+ # 设置服务名
+ application:
+ name: smtweb_user
+ main:
+ allow-bean-definition-overriding: true
+ banner-mode: console
+ mvc:
+ static-path-pattern: /static/**
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ password:
+ datasource:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/smt_user?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=CTT&allowMultiQueries=true
+ username: root
+ password: 1681860
+ # 连接池配置
+ hikari:
+ pool-name: HikariPool
+ minimum-idle: 10
+ maximum-pool-size: 100
+ connection-timeout: 60000
+ idle-timeout: 600000
+ max-lifetime: 1800000
+ servlet:
+ multipart:
+ max-file-size: 104857600000
+ max-request-size: 10485760000000
+ profiles:
+ include: role
+ cache:
+ type: caffeine
+ cache-names:
+ - core
+ caffeine:
+ spec: maximumSize=1024,expireAfterWrite=2h
+
+
+
+
diff --git a/smtweb-framework/sw-framework-auth/src/main/resources/config/application-prod.yaml b/smtweb-framework/sw-framework-auth/src/main/resources/config/application-prod.yaml
new file mode 100644
index 0000000..d6f1168
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/resources/config/application-prod.yaml
@@ -0,0 +1,35 @@
+sme:
+ machine-id: 1
+ file-local-path: /data/files/smart/
+ file-host: http://auth.smtweb.cc
+ file-url: ${sme.file-host}:${server.port}${server.servlet.context-path}/${sme.file-local-path}
+server:
+ port: 10001
+ servlet:
+ context-path: /
+logging:
+ level:
+ smtweb: DEBUG
+
+spring:
+ main:
+ allow-bean-definition-overriding: true
+ mvc:
+ static-path-pattern: /static/**
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ datasource:
+ user:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/smt_user?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=CTT&allowMultiQueries=true
+ username: smt
+ password: smt_123456
+
+ servlet:
+ multipart:
+ max-file-size: 104857600000
+ max-request-size: 10485760000000
+
+
+
diff --git a/smtweb-framework/sw-framework-auth/src/main/resources/config/application.yaml b/smtweb-framework/sw-framework-auth/src/main/resources/config/application.yaml
new file mode 100644
index 0000000..caf4dfc
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/src/main/resources/config/application.yaml
@@ -0,0 +1,3 @@
+spring:
+ profiles:
+ active: dev
\ No newline at end of file
diff --git a/smtweb-framework/sw-framework-auth/target/classes/META-INF/spring.factories b/smtweb-framework/sw-framework-auth/target/classes/META-INF/spring.factories
new file mode 100644
index 0000000..82bd9bb
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/target/classes/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+ cc.smtweb.framework.auth.spring.AuthAutoConfiguration
diff --git a/smtweb-framework/sw-framework-auth/target/classes/auth/courier_new_34_19.png b/smtweb-framework/sw-framework-auth/target/classes/auth/courier_new_34_19.png
new file mode 100644
index 0000000..44eada2
Binary files /dev/null and b/smtweb-framework/sw-framework-auth/target/classes/auth/courier_new_34_19.png differ
diff --git a/smtweb-framework/sw-framework-auth/target/classes/config/application-dev.yaml b/smtweb-framework/sw-framework-auth/target/classes/config/application-dev.yaml
new file mode 100644
index 0000000..2422f31
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/target/classes/config/application-dev.yaml
@@ -0,0 +1,64 @@
+smtweb:
+ machine-id: 1
+ file:
+ local-path: /data/files/
+ host: http://127.0.0.1
+ url: http://127.0.0.1:8888/files/
+ db:
+ default:
+ rule:
+ prefix: _smt_
+ replace: smt_
+server:
+ port: 8888
+ servlet:
+ context-path: /
+feign:
+ hystrix:
+ enabled: false
+logging:
+ level:
+ root: INFO
+ cc.smtweb: DEBUG
+spring:
+ # 设置服务名
+ application:
+ name: smtweb_user
+ main:
+ allow-bean-definition-overriding: true
+ banner-mode: console
+ mvc:
+ static-path-pattern: /static/**
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ password:
+ datasource:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/smt_user?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=CTT&allowMultiQueries=true
+ username: root
+ password: 1681860
+ # 连接池配置
+ hikari:
+ pool-name: HikariPool
+ minimum-idle: 10
+ maximum-pool-size: 100
+ connection-timeout: 60000
+ idle-timeout: 600000
+ max-lifetime: 1800000
+ servlet:
+ multipart:
+ max-file-size: 104857600000
+ max-request-size: 10485760000000
+ profiles:
+ include: role
+ cache:
+ type: caffeine
+ cache-names:
+ - core
+ caffeine:
+ spec: maximumSize=1024,expireAfterWrite=2h
+
+
+
+
diff --git a/smtweb-framework/sw-framework-auth/target/classes/config/application-prod.yaml b/smtweb-framework/sw-framework-auth/target/classes/config/application-prod.yaml
new file mode 100644
index 0000000..d6f1168
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/target/classes/config/application-prod.yaml
@@ -0,0 +1,35 @@
+sme:
+ machine-id: 1
+ file-local-path: /data/files/smart/
+ file-host: http://auth.smtweb.cc
+ file-url: ${sme.file-host}:${server.port}${server.servlet.context-path}/${sme.file-local-path}
+server:
+ port: 10001
+ servlet:
+ context-path: /
+logging:
+ level:
+ smtweb: DEBUG
+
+spring:
+ main:
+ allow-bean-definition-overriding: true
+ mvc:
+ static-path-pattern: /static/**
+ redis:
+ host: 127.0.0.1
+ port: 6379
+ datasource:
+ user:
+ driver-class-name: com.mysql.cj.jdbc.Driver
+ url: jdbc:mysql://127.0.0.1:3306/smt_user?useUnicode=true&characterEncoding=utf-8&useTimezone=true&serverTimezone=CTT&allowMultiQueries=true
+ username: smt
+ password: smt_123456
+
+ servlet:
+ multipart:
+ max-file-size: 104857600000
+ max-request-size: 10485760000000
+
+
+
diff --git a/smtweb-framework/sw-framework-auth/target/classes/config/application.yaml b/smtweb-framework/sw-framework-auth/target/classes/config/application.yaml
new file mode 100644
index 0000000..caf4dfc
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/target/classes/config/application.yaml
@@ -0,0 +1,3 @@
+spring:
+ profiles:
+ active: dev
\ No newline at end of file
diff --git a/smtweb-framework/sw-framework-auth/target/maven-archiver/pom.properties b/smtweb-framework/sw-framework-auth/target/maven-archiver/pom.properties
new file mode 100644
index 0000000..55808f3
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/target/maven-archiver/pom.properties
@@ -0,0 +1,5 @@
+#Generated by Apache Maven
+#Tue Nov 02 19:04:59 CST 2021
+version=2.1.0-SNAPSHOT
+groupId=cc.smtweb
+artifactId=sw-framework-auth
diff --git a/smtweb-framework/sw-framework-auth/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst b/smtweb-framework/sw-framework-auth/target/maven-status/maven-compiler-plugin/compile/default-compile/createdFiles.lst
new file mode 100644
index 0000000..e69de29
diff --git a/smtweb-framework/sw-framework-auth/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst b/smtweb-framework/sw-framework-auth/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
new file mode 100644
index 0000000..d6ab0c6
--- /dev/null
+++ b/smtweb-framework/sw-framework-auth/target/maven-status/maven-compiler-plugin/compile/default-compile/inputFiles.lst
@@ -0,0 +1,9 @@
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\web\entity\LoginAckVO.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\web\entity\UserPO.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\spring\cache\RealmCache.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\AuthApplication.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\web\entity\MenuPO.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\web\entity\LoginVO.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\captcha\ImageMaker.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\spring\AuthAutoConfiguration.java
+E:\jujia\git\6.0\sw\smtweb-framework\sw-framework-auth\src\main\java\cc\smtweb\framework\auth\web\service\AuthService.java
diff --git a/smtweb-framework/sw-framework-core/doc/TODO.mk b/smtweb-framework/sw-framework-core/doc/TODO.mk
new file mode 100644
index 0000000..4f5bf71
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/doc/TODO.mk
@@ -0,0 +1,8 @@
+20210710
+
+1. 定时器手动触发 (done)
+2. 优化BeanReadUtils的TableName预先进行转换
+2. updateEntity支持悲观锁,并能抛出异常
+3. 缓存支持自定义 key
+4. 序列号生成器
+5. redis配置database(0~15) (done)
diff --git a/smtweb-framework/sw-framework-core/pom.xml b/smtweb-framework/sw-framework-core/pom.xml
new file mode 100644
index 0000000..1aadd07
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/pom.xml
@@ -0,0 +1,202 @@
+
+
+ cc.smtweb
+ sw-framework-core
+ 2.2.0-SNAPSHOT
+
+
+ org.springframework.boot
+ spring-boot-starter-parent
+ 2.5.6
+
+
+
+ 4.0.0
+
+
+
+ UTF-8
+ UTF-8
+ 1.8
+ 1.8
+ 1.8
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+ com.fasterxml.jackson.core
+ jackson-core
+
+
+
+ org.springframework.boot
+ spring-boot-starter-jdbc
+
+
+
+
+ io.lettuce
+ lettuce-core
+ 6.1.5.RELEASE
+
+
+ org.apache.commons
+ commons-pool2
+ 2.11.1
+
+
+
+ commons-codec
+ commons-codec
+ 1.15
+
+
+
+
+ com.esotericsoftware
+ kryo
+ 4.0.0
+
+
+ org.projectlombok
+ lombok
+ 1.18.22
+
+
+
+ org.apache.commons
+ commons-lang3
+ 3.12.0
+
+
+
+ org.apache.commons
+ commons-jexl3
+ 3.2.1
+
+
+
+ org.apache.tika
+ tika-core
+ 2.1.0
+
+
+
+ com.github.ben-manes.caffeine
+ caffeine
+
+
+
+ mysql
+ mysql-connector-java
+ 8.0.27
+ runtime
+
+
+ commons-collections
+ commons-collections
+ 3.2.2
+ compile
+
+
+
+ org.junit.platform
+ junit-platform-launcher
+ 1.6.2
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.6.2
+ test
+
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.6.2
+ test
+
+
+ org.junit.vintage
+ junit-vintage-engine
+ 5.6.2
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-params
+ 5.6.2
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-source-plugin
+
+
+ attach-sources
+ verify
+
+ jar-no-fork
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+ config/*.yaml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ nexus-releases
+ Nexus Release Repository
+ http://47.92.149.153:7000/repository/maven-releases/
+
+
+ nexus-snapshots
+ Nexus Snapshot Repository
+ http://47.92.149.153:7000/repository/maven-snapshots/
+
+
+
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreApplication.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreApplication.java
new file mode 100644
index 0000000..5c73f81
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreApplication.java
@@ -0,0 +1,11 @@
+package cc.smtweb.framework.core;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class CoreApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(CoreApplication.class, args);
+ }
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreApplicationStartedListener.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreApplicationStartedListener.java
new file mode 100644
index 0000000..c369fcc
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreApplicationStartedListener.java
@@ -0,0 +1,33 @@
+package cc.smtweb.framework.core;
+
+import cc.smtweb.framework.core.cache.CacheManager;
+import cc.smtweb.framework.core.mvc.controller.scan.ApplicationScanner;
+import cc.smtweb.framework.core.systask.TaskStartEvent;
+import cc.smtweb.framework.core.systask.WebStartedEvent;
+import lombok.SneakyThrows;
+import org.springframework.boot.context.event.ApplicationStartedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.stereotype.Component;
+
+/**
+ * 执行接口扫描任务
+ */
+@Component
+public class CoreApplicationStartedListener implements ApplicationListener {
+ @SneakyThrows
+ @Override
+ public void onApplicationEvent(ApplicationStartedEvent event) {
+ System.out.println("onApplicationEvent=============");
+ ConfigurableApplicationContext applicationContext = event.getApplicationContext();
+
+ applicationContext.publishEvent(new TaskStartEvent());
+ //包扫描
+ ApplicationScanner.scan(applicationContext);
+ //初始化缓存
+ CacheManager.getIntance().init();
+
+ // 通知 controller 正式使用
+ applicationContext.publishEvent(new WebStartedEvent());
+ }
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreAutoConfiguration.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreAutoConfiguration.java
new file mode 100644
index 0000000..f576544
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/CoreAutoConfiguration.java
@@ -0,0 +1,33 @@
+package cc.smtweb.framework.core;
+
+import cc.smtweb.framework.core.db.jdbc.IdGenerator;
+import cc.smtweb.framework.core.mvc.config.ControllerConfig;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableScheduling;
+
+/**
+ * @author kevin
+ */
+@Configuration
+@ComponentScan
+@EnableScheduling
+public class CoreAutoConfiguration {
+ /**
+ * ID生成器的分步式机器码(1-1023)
+ */
+ @Value("${smtweb.machine-id}")
+ private int machineId;
+
+ @Bean
+ public IdGenerator idGenerator() {
+ return new IdGenerator(machineId);
+ }
+
+ @Bean
+ public ControllerConfig coreControllerConfig() {
+ return new ControllerConfig("core", "cc.smtweb.framework.core");
+ }
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/R.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/R.java
new file mode 100644
index 0000000..26a302d
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/R.java
@@ -0,0 +1,117 @@
+package cc.smtweb.framework.core;
+
+import cc.smtweb.framework.core.exception.ExceptionMessage;
+
+import java.util.Date;
+
+/**
+ * 〈返回结果集〉
+ *
+ * @author kevin
+ * @since 1.0.0
+ */
+public class R extends SwMap {
+ protected R() {
+ this(0);
+ }
+
+ protected R(int code) {
+ put("now", new Date());
+ put("code", code);
+ }
+
+ public static R success() {
+ return new R();
+ }
+
+ public static R success(Object data) {
+ return new R().put("data", data);
+ }
+
+ public static R success(String name, Object data) {
+ return new R().put(name, data);
+ }
+
+ public static R error() {
+ return error(ExceptionMessage.INNER_ERROR.getMsg());
+ }
+
+ public static R error(String msg) {
+ R r = new R(ExceptionMessage.INNER_ERROR.getCode());
+ r.put("msg", msg);
+ return r;
+ }
+
+ public static R error(int code, String msg) {
+ R r = new R(code);
+ r.put("msg", msg);
+ return r;
+ }
+
+ public static R errorf(String format, Object...args) {
+ R r = new R(ExceptionMessage.INNER_ERROR.getCode());
+ r.put("msg", String.format(format, args));
+ return r;
+ }
+
+// public static R error(ExceptionMessage cm) {
+// R r = new R(cm.getCode());
+// r.put("msg", cm.getMsg());
+// return r;
+// }
+
+// public static R error(ExceptionMessage cm, Throwable ex) {
+// R r = new R(cm.getCode());
+// r.put("msg", cm.getMsg());
+// r.put("exception", ex.getMessage());
+// return r;
+// }
+
+ public static R error(String msg, Throwable ex) {
+ R r = new R(ExceptionMessage.INNER_ERROR.getCode());
+ r.put("msg", msg);
+ r.put("exception", ex.getMessage());
+ return r;
+ }
+
+ public static R error(ExceptionMessage cm, String msg) {
+ R r = new R(cm.getCode());
+ r.put("msg", msg);
+ return r;
+ }
+
+ @Override
+ public R put(String key, Object value) {
+ super.put(key, value);
+ return this;
+ }
+
+ public R putNotNull(String key, Object value) {
+ if (value != null) {
+ super.put(key, value);
+ }
+
+ return this;
+ }
+
+ public void setMessage(ExceptionMessage cm) {
+ this.put("code", cm.getCode());
+ this.put("msg", cm.getMsg());
+ }
+
+ public void setData(Object data) {
+ this.put("data", data);
+ }
+
+ public int readCode() {
+ return this.readInt("code");
+ }
+
+ public String readMsg() {
+ return this.readString("msg");
+ }
+
+ public boolean readSuccess() {
+ return this.readInt("code", -1) == 0;
+ }
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwException.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwException.java
new file mode 100644
index 0000000..387315c
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwException.java
@@ -0,0 +1,53 @@
+package cc.smtweb.framework.core;
+
+import cc.smtweb.framework.core.exception.ExceptionMessage;
+
+/**
+ * 〈全局异常〉
+ *
+ * @author kevin
+ * @since 1.0.0
+ */
+public class SwException extends RuntimeException {
+
+ private static final long serialVersionUID = 8096609992852791423L;
+
+// private ExceptionMessage cm;
+
+ public SwException() {
+ }
+
+ public SwException(String msg) {
+ super(msg);
+ }
+
+ public SwException(int code, String msg) {
+ super(msg);
+ }
+
+ public SwException(String msg, Throwable e) {
+ super(msg, e);
+ }
+
+ public SwException(Throwable e) {
+ super(e.getMessage(), e);
+ }
+
+ public SwException(ExceptionMessage cm) {
+ super(cm.getMsg());
+ }
+
+ public SwException(ExceptionMessage cm, Throwable e) {
+ super(cm.getMsg(), e);
+ }
+
+ public SwException(ExceptionMessage cm, String msg) {
+ super(msg);
+ }
+
+
+// public ExceptionMessage getCm() {
+// return cm;
+// }
+
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwIpAddr.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwIpAddr.java
new file mode 100644
index 0000000..8a55568
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwIpAddr.java
@@ -0,0 +1,9 @@
+package cc.smtweb.framework.core;
+
+import lombok.Data;
+
+@Data
+public class SwIpAddr {
+ private String ip;
+ private int port;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwMap.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwMap.java
new file mode 100644
index 0000000..6f61eb7
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/SwMap.java
@@ -0,0 +1,93 @@
+package cc.smtweb.framework.core;
+
+import cc.smtweb.framework.core.util.MapUtil;
+
+import java.util.HashMap;
+import java.util.Set;
+
+/**
+ * 通用map对象,用于无具体类型的传值
+ * @author kevin
+ */
+public class SwMap extends HashMap {
+ public SwMap() {}
+
+ public SwMap(int initialCapacity) {
+ super(initialCapacity);
+ }
+
+ public String readString(String name) {
+ return MapUtil.readString(this, name, null);
+ }
+
+ public String readString(String name, String defaultValue) {
+ return MapUtil.readString(this, name, defaultValue);
+ }
+
+ public Long readLong(String name) {
+ return MapUtil.readLong(this, name, null);
+ }
+
+ public Long readLong(String name, Long defaultValue) {
+ return MapUtil.readLong(this, name, defaultValue);
+ }
+
+ public Long[] readLongArray(String name) {
+ return MapUtil.readLongArray(this, name, null);
+ }
+
+ public Long[] readLongArray(String name, Long[] defaultValue) {
+ return MapUtil.readLongArray(this, name, defaultValue);
+ }
+
+ public Set readLongSet(String name) {
+ return MapUtil.readLongSet(this, name);
+ }
+
+ public Integer readInt(String name) {
+ return MapUtil.readInt(this, name, null);
+ }
+
+ public Integer readInt(String name, Integer defaultValue) {
+ return MapUtil.readInt(this, name, defaultValue);
+ }
+
+ public Float readFloat(String name) {
+ return MapUtil.readFloat(this, name, null);
+ }
+
+ public Float readFloat(String name, Float defaultValue) {
+ return MapUtil.readFloat(this, name, defaultValue);
+ }
+
+ public Double readDouble(String name) {
+ return MapUtil.readDouble(this, name, null);
+ }
+
+ public Double readDouble(String name, Double defaultValue) {
+ return MapUtil.readDouble(this, name, defaultValue);
+ }
+
+ public Boolean readBool(String name) {
+ return MapUtil.readBool(this, name, null);
+ }
+
+ public Boolean readBool(String name, Boolean defaultValue) {
+ return MapUtil.readBool(this, name, defaultValue);
+ }
+
+ @Override
+ public SwMap put(String name, Object value) {
+ if (value != null) {
+ super.put(name, value);
+ } else {
+ super.remove(name);
+ }
+
+ return this;
+ }
+
+ public static SwMap of(String name, Object value) {
+ return new SwMap().put(name, value);
+ }
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwAction.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwAction.java
new file mode 100644
index 0000000..112ed75
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwAction.java
@@ -0,0 +1,21 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 配置在@SwService中的函数,对应API请求,默认公用函数不用配置拦截器的函数,
+ * 也可以作为拦截实现的基类
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface SwAction {
+ /**
+ * 重写API请求地址,不配置使用: 服务类地址 + “/” + 函数名
+ * @return API请求地址
+ */
+ String value() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwAttr.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwAttr.java
new file mode 100644
index 0000000..e9c3675
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwAttr.java
@@ -0,0 +1,16 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 参数注解,request定制的上下文内容,定制使用
+ * @author kevin
+ *
+ */
+
+@Target( { ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SwAttr {
+ String value() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwBean.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwBean.java
new file mode 100644
index 0000000..31b4376
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwBean.java
@@ -0,0 +1,22 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 被该注释修饰的类提供服务,如Dao,Service等
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE, ElementType.METHOD})
+public @interface SwBean {
+ String value() default "";
+
+ /**
+ * 是否强行生成对象,不检查单例
+ * @return 是否强行生成对象
+ */
+ boolean alwaysCreate() default false;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwBody.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwBody.java
new file mode 100644
index 0000000..50ff91b
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwBody.java
@@ -0,0 +1,15 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.*;
+
+/**
+ * 参数注解,当编译器无法找到参数名称时,需要用该注解标明参数名称,当然你也可以用该参数标注参数别名与表单域字段名同意
+ * @author kevin
+ *
+ */
+@Target( { ElementType.PARAMETER})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SwBody {
+ String value() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwCache.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwCache.java
new file mode 100644
index 0000000..b6dbbd4
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwCache.java
@@ -0,0 +1,26 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 被该注释修饰的类提供缓存服务
+ *
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface SwCache {
+ //唯一标识
+ String ident();
+ //标题,展示用
+ String title();
+ //依赖的缓存ident,多个用英文逗号分隔
+ String depends() default "";
+ //是否懒加载
+ boolean lazy() default false;
+ //失效时间,单位分钟
+ long timeout() default 0;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwColumn.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwColumn.java
new file mode 100644
index 0000000..c4d88ed
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwColumn.java
@@ -0,0 +1,38 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 被该注释修饰的方法对应了字段名和类型
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface SwColumn {
+ String value() default "";
+
+ /** 字段作用,前端用RefType表示 */
+ Type[] type() default {};
+
+ public static enum Type {
+ // 主键
+ ID,
+ // 上级ID,树结构需要
+ PARENT_ID,
+ // 排序字段,树结构需要
+ ORDER,
+ // 编码字段
+ CODE,
+ // 名词字段
+ NAME,
+ // 主表ID,MapToOne
+ MASTER_ID,
+ // 创建时间
+ CREATE_TIME,
+ // 更新时间
+ LAST_TIME,
+ }
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwColumnForeign.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwColumnForeign.java
new file mode 100644
index 0000000..fa1ada1
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwColumnForeign.java
@@ -0,0 +1,21 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 被该注释修饰的方法对应了外键表名和字段名,名称可选
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface SwColumnForeign {
+ // 外键表名
+ String table() default "";
+ // ID字段名
+ String id() default "";
+ // 唯一名称字段名
+ String code() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwConstruct.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwConstruct.java
new file mode 100644
index 0000000..ed9eef5
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwConstruct.java
@@ -0,0 +1,20 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 通过对@SwService/@SwBean类中的函数注解,服务启动时会调用一次被注解的函数
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface SwConstruct {
+ /**
+ * 销毁顺序,值越小越先创建
+ * @return 销毁顺序值
+ */
+ int order() default 0;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwDestroy.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwDestroy.java
new file mode 100644
index 0000000..da89811
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwDestroy.java
@@ -0,0 +1,20 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 通过对@SwService/@SwBean类中的函数注解,服务停止时会调用一次被注解的函数
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD})
+public @interface SwDestroy {
+ /**
+ * 销毁顺序,值越大越先销毁
+ * @return 销毁顺序值
+ */
+ int order() default 0;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwHeaderParam.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwHeaderParam.java
new file mode 100644
index 0000000..69af9d4
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwHeaderParam.java
@@ -0,0 +1,16 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.*;
+
+
+/**
+ * 路径注解
+ * @author kevin
+ *
+ */
+@Target( { ElementType.PARAMETER, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SwHeaderParam {
+ String value() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwParam.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwParam.java
new file mode 100644
index 0000000..033d671
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwParam.java
@@ -0,0 +1,18 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.*;
+
+
+/**
+ * 参数注解,当编译器无法找到参数名称时,需要用该注解标明参数名称,当然你也可以用该参数标注参数别名与表单域字段名同意
+ * @author kevin
+ *
+ */
+@Target( { ElementType.PARAMETER, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SwParam {
+ String value() default "";
+ /** 注入类型,有多个类实现/子类时使用 */
+ Class> type() default Object.class;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwPathParam.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwPathParam.java
new file mode 100644
index 0000000..c4ced93
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwPathParam.java
@@ -0,0 +1,16 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.*;
+
+
+/**
+ * 路径注解
+ * @author kevin
+ *
+ */
+@Target( { ElementType.PARAMETER, ElementType.FIELD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface SwPathParam {
+// String value() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwPerm.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwPerm.java
new file mode 100644
index 0000000..0ef2c48
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwPerm.java
@@ -0,0 +1,21 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 被该注释修饰的方法都会经过切面拦截校验权限,默认是需要已登录权限
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.TYPE})
+public @interface SwPerm {
+ /** 无权限控制的值,在函数上注解@SwPerm(SwPerm.NONE) */
+ static final String NONE = "*";
+ static final String SESSION = "";
+
+ /** 权限定义值 */
+ String value() default SESSION;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwScheduling.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwScheduling.java
new file mode 100644
index 0000000..261f1f0
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwScheduling.java
@@ -0,0 +1,30 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 通过对@SwService/@SwBean类中的函数注解,定时任务方法注解
+ *
+ * @author xkliu
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value={ElementType.METHOD})
+public @interface SwScheduling {
+ /**
+ * 时间触发条件,如果值是单数字就是用秒定时,否则就是采用linux/unux crondtab 样式
+ */
+ String value();
+
+ /**
+ * 定时任务分组条件, 有值时同一分组不允许并发执行
+ */
+ String group() default "";
+
+ /**
+ * 是否支持多服务同时运行
+ */
+ boolean multiServer() default false;
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwService.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwService.java
new file mode 100644
index 0000000..ba25e6c
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwService.java
@@ -0,0 +1,16 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 被该注释修饰的类提供控制器服务
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface SwService {
+ String value() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwTable.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwTable.java
new file mode 100644
index 0000000..464f322
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/annotation/SwTable.java
@@ -0,0 +1,17 @@
+package cc.smtweb.framework.core.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 被该注释修饰的类对应了数据库表名(库+表的形式,如 sw_user.sys_user)
+ * @author kevin
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface SwTable {
+ /** 库名+表名 */
+ String value() default "";
+}
diff --git a/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/cache/AbstractCache.java b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/cache/AbstractCache.java
new file mode 100644
index 0000000..f7b5262
--- /dev/null
+++ b/smtweb-framework/sw-framework-core/src/main/java/cc/smtweb/framework/core/cache/AbstractCache.java
@@ -0,0 +1,493 @@
+package cc.smtweb.framework.core.cache;
+
+import cc.smtweb.framework.core.annotation.SwCache;
+import cc.smtweb.framework.core.annotation.SwParam;
+import cc.smtweb.framework.core.cache.ISwCache;
+import cc.smtweb.framework.core.redis.RedisBroadcastEvent;
+import cc.smtweb.framework.core.redis.RedisManager;
+import cc.smtweb.framework.core.util.CommUtil;
+import cc.smtweb.framework.core.util.kryo.KryoTool;
+import com.github.benmanes.caffeine.cache.Caffeine;
+import com.github.benmanes.caffeine.cache.LoadingCache;
+import com.github.benmanes.caffeine.cache.RemovalCause;
+import com.github.benmanes.caffeine.cache.Scheduler;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.checkerframework.checker.nullness.qual.NonNull;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import java.io.Serializable;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 封装caffeine的抽象Cache类,实现内存缓存,并支持用redis广播进行数据缓存同步
+ *
+ * @param <> 缓存的值类
+ * @author zhenggm
+ */
+@Slf4j
+public abstract class AbstractCache implements ISwCache {
+ protected final static int LS_NONE = 0;
+ protected final static int LS_LOADING = 1;
+ protected final static int LS_LOADED = 2;
+
+ private final static String split_char = "-";
+ //唯一标识
+ protected String ident;
+ //展示名称
+ protected String title;
+ //是否懒加载,懒加载时,将不从库loadall
+ protected boolean lazy;
+ //依赖
+ protected String[] depends;
+
+ //数据加载状态
+ private short loadStatu = LS_NONE;
+ private Class pTypeClass = null;
+
+
+ private LoadingCache cache;
+ private Map cacheOrg = new ConcurrentHashMap<>();
+ //本地缓存对象,按List缓存,减轻redis压力
+ protected Map> mapListLocal = new ConcurrentHashMap<>();
+ //本地按其他键值缓存的对象
+ protected Map> mapMapLocal = new ConcurrentHashMap<>();
+
+ /*注册要按list缓存的信息,key=list的类别,按什么字段来缓存。IGetBeanKey为根据bean获取此bean的key
+ 如资金科目明细项,需按资金科目缓存List。key=sc,value=class_id
+ */
+ protected Map> mapListReg = new HashMap<>();
+ protected Map> mapMapReg = new HashMap<>();
+
+ public AbstractCache() {
+ pTypeClass = CommUtil.getParameterizedType(getClass());
+ }
+
+ //注册
+ protected void install(ScheduledExecutorService executorService) {
+ SwCache swCache = this.getClass().getAnnotation(SwCache.class);
+ if (swCache != null) {
+ ident = swCache.ident();
+ title = swCache.title();
+ lazy = swCache.lazy();
+ depends = StringUtils.split(swCache.depends(), ",");
+ }
+ final @NonNull Caffeine