Commit bcd1715b by tangyi

调整结构

parent 5e3df5c7
Version v3.1.0 (2019-7-18)
--------------------------
改进:
* 调整项目结构
* 调整版本号
* 去掉热部署部分内容,修复读取缓存报ClassCastException问题
* 完善登录日志,增加登录IP、耗时等信息
Version v3.0.0 (2019-7-15)
--------------------------
改进:
......
......@@ -30,9 +30,9 @@ QQ群号:996208878
### 部署文档
- [在线考试系统部署文档](docs/在线考试系统V2.0_部署文档.md)
- [在线考试系统部署文档](docs/在线考试系统V3.0_部署文档.md)
- [基于docker-compose部署](docs/在线考试系统V2.0_部署文档(docker版).md)
- [基于docker-compose部署](docs/在线考试系统V3.0_部署文档(docker版).md)
### 源码地址
......@@ -52,7 +52,7 @@ QQ群号:996208878
- 分布式配置中心:`Spring Cloud Config`
- 分布式调用链监控:`Spring Cloud Sleuth` + `Zipkin`
- 数据库:`MySQL 5.7`
- 部署:`Docker`
- 部署:`Docker` + `docker-compose`
- 构建工具:`Maven`
- 后台 API 文档:`Swagger`
- 消息队列:`RabbitMQ`
......@@ -79,9 +79,9 @@ QQ群号:996208878
后台管理分为:系统管理、系统监控、考务管理、附件管理、个人管理
![image](docs/产品设计/功能概述.png)
![image](docs/产品设计/系统功能.jpg)
- [在线考试系统V2.0功能概述](docs/在线考试系统V2.0_功能概述.md)
- [在线考试系统V3.0功能概述](docs/在线考试系统V3.0_功能概述.md)
## 功能演示
......@@ -128,7 +128,7 @@ QQ群号:996208878
- [ ] 作业、考试、知识点管理、考试成绩排名、图表展示
- [ ] 学生签到、请假
- [ ] 短信验证码,第三方登录
- [x] 短信验证码,第三方登录
- [ ] 简答题,题库完善,智能组卷,在线学习,成绩排名
## 问题反馈
......@@ -139,17 +139,21 @@ QQ群号:996208878
## 参考资料
- [在线考试系统V2.0设计文档-数据库设计](docs/在线考试系统V2.0_数据库设计.md)
- [在线考试系统V3.0系统架构图](https://www.processon.com/view/link/5cf88937e4b0a64c88aaa3e4)
- [在线考试系统V2.0部署文档](docs/在线考试系统V2.0_部署文档.md)
- [在线考试系统V3.0使用文档](docs/在线考试系统V3.0_使用文档.md)
- [在线考试系统V2.0部署文档(docker版)](docs/在线考试系统V2.0_部署文档(docker版).md)
- [在线考试系统V3.0设计文档-数据库设计](docs/在线考试系统V3.0_数据库设计.md)
- [在线考试系统V2.0项目结构说明文档](docs/在线考试系统V2.0_项目结构说明.md)
- [在线考试系统V3.0部署文档](docs/在线考试系统V3.0_部署文档.md)
- [在线考试系统V3.0部署文档(docker版)](docs/在线考试系统V3.0_部署文档(docker版).md)
- [在线考试系统V3.0项目结构说明文档](docs/在线考试系统V3.0_项目结构说明.md)
- [微服务架构下的安全设计方案](http://ehedgehog.net/2019/03/23/%E5%BE%AE%E6%9C%8D%E5%8A%A1%E6%9E%B6%E6%9E%84%E4%B8%8B%E7%9A%84%E5%AE%89%E5%85%A8%E8%AE%BE%E8%AE%A1%E6%96%B9%E6%A1%88/)
- [在线考试系统V2.0镜像构建、推送、部署](http://ehedgehog.net/2019/04/22/%E5%9C%A8%E7%BA%BF%E8%80%83%E8%AF%95%E7%B3%BB%E7%BB%9FV2.0%E9%95%9C%E5%83%8F%E6%9E%84%E5%BB%BA%E3%80%81%E6%8E%A8%E9%80%81%E3%80%81%E9%83%A8%E7%BD%B2/)
- [在线考试系统V3.0镜像构建、推送、部署](http://ehedgehog.net/2019/04/22/%E5%9C%A8%E7%BA%BF%E8%80%83%E8%AF%95%E7%B3%BB%E7%BB%9FV2.0%E9%95%9C%E5%83%8F%E6%9E%84%E5%BB%BA%E3%80%81%E6%8E%A8%E9%80%81%E3%80%81%E9%83%A8%E7%BD%B2/)
***
......
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<artifactId>common-core</artifactId>
<name>${project.artifactId}</name>
......
......@@ -28,5 +28,6 @@ public class AppStartupRunner implements CommandLineRunner {
// 设置系统属性
if (StringUtils.isNotBlank(sysProperties.getCacheExpire()))
System.setProperty(CommonConstant.CACHE_EXPIRE, sysProperties.getCacheExpire());
log.info("end command line...");
}
}
......@@ -16,22 +16,22 @@ public enum LoginType {
/**
* 账号密码登录
*/
PWD("PWD", "账号密码登录"),
PWD("PWD", "账号密码登录", "/oauth/token"),
/**
* 验证码登录
*/
SMS("SMS", "验证码登录"),
SMS("SMS", "验证码登录", "/mobile/token"),
/**
* QQ登录
*/
QQ("QQ", "QQ登录"),
QQ("QQ", "QQ登录", "/mobile/token"),
/**
* 微信登录
*/
WECHAT("WX", "微信登录");
WECHAT("WX", "微信登录", "/wx/token");
/**
* 类型
......@@ -42,4 +42,9 @@ public enum LoginType {
* 描述
*/
private String description;
/**
* 接口uri
*/
private String uri;
}
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<artifactId>common-feign</artifactId>
<name>${project.artifactId}</name>
......
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<artifactId>common-log</artifactId>
<name>${project.artifactId}</name>
......@@ -27,7 +28,7 @@
<!-- user-api -->
<dependency>
<groupId>com.github.tangyi</groupId>
<artifactId>user-api</artifactId>
<artifactId>user-service-api</artifactId>
</dependency>
</dependencies>
......
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>common</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<artifactId>common-security</artifactId>
<name>${project.artifactId}</name>
......
......@@ -5,7 +5,7 @@
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<artifactId>common</artifactId>
<packaging>pom</packaging>
......
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<artifactId>config-service</artifactId>
<name>${project.artifactId}</name>
......
......@@ -60,6 +60,10 @@ sys:
# feign相关配置
feign:
httpclient:
enabled: false
okhttp:
enabled: true
hystrix:
enabled: true
......
......@@ -70,7 +70,7 @@ services:
# 配置中心
# ---------------------------
config-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/config-service:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/config-service:3.1.0
container_name: config-service
env_file: docker-compose.env # 从文件中获取配置
restart: always
......
......@@ -4,7 +4,7 @@ services:
# 前台
# ---------------------------
spring-microservice-exam-web:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/spring-microservice-exam-web:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/spring-microservice-exam-web:3.1.0
volumes:
# 挂载nginx的配置文件
- ./nginx.conf:/etc/nginx/nginx.conf
......@@ -20,7 +20,7 @@ services:
# 后台
# ---------------------------
spring-microservice-exam-ui:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/spring-microservice-exam-ui:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/spring-microservice-exam-ui:3.1.0
volumes:
# 挂载nginx的配置文件
- ./nginx.conf:/etc/nginx/nginx.conf
......
......@@ -4,7 +4,7 @@ services:
# api网关
# ---------------------------
gateway-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/gateway-service:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/gateway-service:3.1.0
container_name: gateway-service
env_file: docker-compose.env # 从文件中获取配置
restart: always
......@@ -17,7 +17,7 @@ services:
# 授权服务
# ---------------------------
auth-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/auth-service:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/auth-service:3.1.0
container_name: auth-service
env_file: docker-compose.env # 从文件中获取配置
restart: always
......@@ -30,7 +30,7 @@ services:
# 用户服务
# ---------------------------
user-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/user-service:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/user-service:3.1.0
container_name: user-service
env_file: docker-compose.env # 从文件中获取配置
restart: always
......@@ -43,7 +43,7 @@ services:
# 考试服务
# ---------------------------
exam-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/exam-service:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/exam-service:3.1.0
container_name: exam-service
env_file: docker-compose.env # 从文件中获取配置
restart: always
......@@ -56,7 +56,7 @@ services:
# 消息服务
# ---------------------------
msc-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/msc-service:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/msc-service:3.1.0
container_name: msc-service
env_file: docker-compose.env # 从文件中获取配置
restart: always
......@@ -69,7 +69,7 @@ services:
# 监控服务
# ---------------------------
monitor-service:
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/monitor-service:3.0.0
image: registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam/monitor-service:3.1.0
container_name: monitor-service
env_file: docker-compose.env # 从文件中获取配置
restart: always
......
......@@ -11,7 +11,7 @@
Target Server Version : 50617
File Encoding : 65001
Date: 15/07/2019 21:39:26
Date: 18/07/2019 23:06:58
*/
SET NAMES utf8mb4;
......
......@@ -11,7 +11,7 @@
Target Server Version : 50617
File Encoding : 65001
Date: 15/07/2019 22:56:05
Date: 18/07/2019 23:06:48
*/
SET NAMES utf8mb4;
......@@ -120,11 +120,6 @@ CREATE TABLE `sys_log` (
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Compact;
-- ----------------------------
-- Records of sys_log
-- ----------------------------
INSERT INTO `sys_log` VALUES ('600442842367791104', NULL, '用户登录', NULL, NULL, NULL, NULL, NULL, NULL, 'auth-service', NULL, 'admin', '2019-07-15 21:45:29', 'admin', '2019-07-15 21:45:29', '0', 'EXAM', 'gitee');
-- ----------------------------
-- Table structure for sys_menu
-- ----------------------------
DROP TABLE IF EXISTS `sys_menu`;
......@@ -648,7 +643,7 @@ CREATE TABLE `sys_user` (
INSERT INTO `sys_user` VALUES ('596078038307966976', '管理员', '15521089185', '596094244884713472', '1633736729@qq.com', '2019-07-01', 0, 0, '571347099191480320', '管理员', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'admin', '2019-07-04 13:51:34', 'admin', '2019-07-04 13:51:35', 0, 'EXAM', 'gitee');
INSERT INTO `sys_user` VALUES ('596307222997372928', '梁同学', '15521089185', NULL, '1633736729@qq.com', '2019-07-01', 0, 1, NULL, '梁同学', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'admin', '2019-07-05 21:53:16', 'admin', '2019-07-05 21:53:17', 0, 'EXAM', 'gitee');
INSERT INTO `sys_user` VALUES ('596332387600830464', '林老师', '15521089185', NULL, '1633736729@qq.com', '2019-07-03', 0, 1, NULL, '林老师', NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 'admin', '2019-07-04 13:34:28', 'admin', '2019-07-04 13:38:06', 0, 'EXAM', 'gitee');
INSERT INTO `sys_user` VALUES ('597110984758398976', '白炽灯', NULL, '597110984758398977', NULL, NULL, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2019-07-06 17:05:52', NULL, NULL, 'ovLl45InRn4Hz_jrpEk-gF-kEFf8', '2019-07-06 17:05:53', 'ovLl45InRn4Hz_jrpEk-gF-kEFf8', '2019-07-06 17:05:53', 0, 'EXAM', 'gitee');
INSERT INTO `sys_user` VALUES ('597110984758398976', '测试', '15521089182', '597110984758398977', NULL, NULL, 0, 1, NULL, NULL, NULL, NULL, NULL, NULL, NULL, '2019-07-06 17:05:52', NULL, NULL, 'ovLl45InRn4Hz_jrpEk-gF-kEFf8', '2019-07-18 23:06:24', 'admin', '2019-07-18 23:06:25', 0, 'EXAM', 'gitee');
-- ----------------------------
-- Table structure for sys_user_auths
......@@ -696,7 +691,7 @@ CREATE TABLE `sys_user_role` (
INSERT INTO `sys_user_role` VALUES ('596307898116739072', '596078038307966976', '596117256346406912');
INSERT INTO `sys_user_role` VALUES ('596333922548322304', '596332387600830464', '596330074307956736');
INSERT INTO `sys_user_role` VALUES ('596820924016234496', '596307222997372928', '596116511031169024');
INSERT INTO `sys_user_role` VALUES ('597110985244938240', '597110984758398976', '596116511031169024');
INSERT INTO `sys_user_role` VALUES ('601550371109867520', '597110984758398976', '596116511031169024');
-- ----------------------------
-- Table structure for sys_user_student
......
......@@ -5,7 +5,7 @@ DOCKERHOME=/spring-microservice-exam
# 镜像名称前缀、标签
BASE_IMAGE_NAME=registry.cn-hangzhou.aliyuncs.com/spring-microservice-exam
BSEE_IMAGE_TAG=3.0.0
BSEE_IMAGE_TAG=3.1.0
# 各服务的镜像名称
CONFIG_SERVICE=$BASE_IMAGE_NAME/config-service:$BSEE_IMAGE_TAG
......
docs/images/deploy/config.png

88 KB | W: | H:

docs/images/deploy/config.png

248 KB | W: | H:

docs/images/deploy/config.png
docs/images/deploy/config.png
docs/images/deploy/config.png
docs/images/deploy/config.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/deploy/config_fdfs.png

127 KB | W: | H:

docs/images/deploy/config_fdfs.png

223 KB | W: | H:

docs/images/deploy/config_fdfs.png
docs/images/deploy/config_fdfs.png
docs/images/deploy/config_fdfs.png
docs/images/deploy/config_fdfs.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/deploy/config_redis.png

88.2 KB | W: | H:

docs/images/deploy/config_redis.png

303 KB | W: | H:

docs/images/deploy/config_redis.png
docs/images/deploy/config_redis.png
docs/images/deploy/config_redis.png
docs/images/deploy/config_redis.png
  • 2-up
  • Swipe
  • Onion skin
docs/images/deploy/config_xms.png

89.9 KB | W: | H:

docs/images/deploy/config_xms.png

162 KB | W: | H:

docs/images/deploy/config_xms.png
docs/images/deploy/config_xms.png
docs/images/deploy/config_xms.png
docs/images/deploy/config_xms.png
  • 2-up
  • Swipe
  • Onion skin
### 在线考试系统V3.0使用文档
完整项目地址:
- 前台ui:[spring-microservice-exam-web](https://gitee.com/wells2333/spring-microservice-exam-web.git)
- 后台ui:[spring-microservice-exam-ui](https://gitee.com/wells2333/spring-microservice-exam-ui.git)
- 后端:[spring-microservice-exam](https://gitee.com/wells2333/spring-microservice-exam.git)
### 系列文章
- [登录]()
- [系统管理]()
- [考务管理]()
- [系统监控]()
- [附件管理]()
- [个人资料]()
主要介绍如何基于docker、docker-compose部署后端项目、前端项目,主要的步骤是本地构建镜像,推送的远程仓库,远程服务器从远程仓库拉去镜像运行
主要介绍如何基于docker、docker-compose部署后端项目、前端项目,主要的步骤是本地构建镜像,推送的远程仓库,远程服务器从远程仓库拉去镜像运行
......@@ -10,11 +10,13 @@
MySQL需要单独安装,创建数据库和执行初始化脚本:
`/docs/deploy/mysql/microservice-user.sql`
`/docs/deploy/mysql/init/microservice-user.sql`
`/docs/deploy/mysql/microservice-exam.sql`
`/docs/deploy/mysql/init/microservice-exam.sql`
`/docs/deploy/mysql/microservice-auth.sql`
`/docs/deploy/mysql/init/microservice-auth.sql`
`/docs/deploy/mysql/init/microservice-gateway.sql`
## 安装docker、docker-compose
......@@ -77,4 +79,4 @@ $ docker login --username=你的阿里云账号 registry.cn-hangzhou.aliyuncs.co
- [安装docker-compose](https://www.jianshu.com/p/94760f35c98c)
- [在线考试系统V2.0镜像构建、推送、部署](http://ehedgehog.net/2019/04/22/%E5%9C%A8%E7%BA%BF%E8%80%83%E8%AF%95%E7%B3%BB%E7%BB%9FV2.0%E9%95%9C%E5%83%8F%E6%9E%84%E5%BB%BA%E3%80%81%E6%8E%A8%E9%80%81%E3%80%81%E9%83%A8%E7%BD%B2/)
\ No newline at end of file
- [在线考试系统V3.0镜像构建、推送、部署](http://ehedgehog.net/2019/04/22/%E5%9C%A8%E7%BA%BF%E8%80%83%E8%AF%95%E7%B3%BB%E7%BB%9FV2.0%E9%95%9C%E5%83%8F%E6%9E%84%E5%BB%BA%E3%80%81%E6%8E%A8%E9%80%81%E3%80%81%E9%83%A8%E7%BD%B2/)
\ No newline at end of file
......@@ -47,6 +47,8 @@ fastDfs的IP和端口号:
`/docs/deploy/mysql/microservice-auth.sql`
`/docs/deploy/mysql/microservice-gateway.sql`
#### 启动后端项目
启动项目前要**先确认consul、MySQL、redis、rabbitMq是否已经启动**
......@@ -62,6 +64,7 @@ fastDfs的IP和端口号:
需要监控功能再启动:
6. monitor-service
7. msc-service
内存不足的可以限制每个服务的内存:`config-service`可以分配64M(-Xmx64m -Xms64m)、其它服务分配128M(-Xmx128m -Xms128m)
......
......@@ -9,13 +9,20 @@ common -- 系统公共模块
├── common-feign -- 系统公共feign模块
├── common-log -- 系统公共日志模块
└── common-security -- 系统公共安全模块,包括资源服务器配置
service-api -- 服务api公共模块
├── user-api -- 用户服务api
└── exam-api -- 考试服务api
service-api-impl -- 服务api模块实现
├── auth-service -- 授权服务(OAuth2.0)
├── user-service -- 用户服务
└── exam-service -- 考试服务
modules -- 业务模块
|-- auth-service-parent -- 认证授权服务
|-- auth-service-api -- 认证授权服务api
|-- auth-service -- 认证授权服务具体实现
|-- user-service-parent -- 用户服务
|-- user-service-api -- 用户服务api
|-- user-service -- 用户服务具体实现
|── exam-service-parent -- 考试服务
|-- exam-service-api -- 考试服务api
|-- exam-service -- 考试服务具体实现
└── msc-service-parent -- 消息中心
|-- msc-service-api -- 消息中心api
|-- msc-service -- 消息中心具体实现
config-service -- 配置中心(本地仓库)
gateway-service -- 网关(动态路由)
monitor-service -- spring boot amdin 监控服务
......
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId>
<version>3.0.0</version>
<version>3.1.0</version>
</parent>
<artifactId>gateway-service</artifactId>
<name>${project.artifactId}</name>
......
package com.github.tangyi.gateway.config;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.gateway.module.Route;
import com.github.tangyi.common.core.utils.JsonMapper;
import com.github.tangyi.gateway.module.Route;
import com.github.tangyi.gateway.service.RouteService;
import com.github.tangyi.gateway.vo.RoutePredicateVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
......@@ -40,6 +41,8 @@ public class RegistrySwaggerResourcesProvider implements SwaggerResourcesProvide
private final RedisTemplate redisTemplate;
private final RouteService routeService;
@Override
public List<SwaggerResource> get() {
List<SwaggerResource> resources = new ArrayList<>();
......@@ -50,11 +53,8 @@ public class RegistrySwaggerResourcesProvider implements SwaggerResourcesProvide
if (swaggerProviderConfig.getProviders().contains(route.getId()))
routes.add(route.getId());
});
// 结合配置的route-路径(Path),和route过滤,只获取有效的route节点
Object object = redisTemplate.opsForValue().get(CommonConstant.ROUTE_KEY);
if (object != null) {
List<Route> routeList = JsonMapper.getInstance().fromJson(object.toString(), JsonMapper.getInstance().createCollectionType(ArrayList.class, Route.class));
List<Route> routeList = this.routeList();
if (CollectionUtils.isNotEmpty(routeList)) {
for (Route route : routeList) {
if (routes.contains(route.getRouteId())) {
......@@ -74,11 +74,30 @@ public class RegistrySwaggerResourcesProvider implements SwaggerResourcesProvide
}
}
}
}
return resources;
}
/**
* 获取路由列表
*
* @return List<Route>
*/
private List<Route> routeList() {
List<Route> routeList;
// 结合配置的route-路径(Path),和route过滤,只获取有效的route节点
Object object = redisTemplate.opsForValue().get(CommonConstant.ROUTE_KEY);
if (object == null) {
// 放入缓存
routeList = routeService.findList(new Route());
if (CollectionUtils.isNotEmpty(routeList))
redisTemplate.opsForValue().set(CommonConstant.ROUTE_KEY, JsonMapper.getInstance().toJson(routeList));
} else {
routeList = JsonMapper.getInstance().fromJson(object.toString(), JsonMapper.getInstance().createCollectionType(ArrayList.class, Route.class));
}
return routeList;
}
/**
* 服务信息
*
* @param name name
......
......@@ -17,6 +17,7 @@ import javax.validation.Valid;
/**
* 路由controller
* TODO:增加security认证
*
* @author tangyi
* @date 2019/4/2 15:03
......
......@@ -2,6 +2,7 @@ package com.github.tangyi.gateway.service;
import com.fasterxml.jackson.databind.JavaType;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.exceptions.CommonException;
import com.github.tangyi.common.core.service.CrudService;
import com.github.tangyi.common.core.utils.JsonMapper;
import com.github.tangyi.gateway.constants.GatewayConstant;
......@@ -9,7 +10,6 @@ import com.github.tangyi.gateway.mapper.RouteMapper;
import com.github.tangyi.gateway.module.Route;
import com.github.tangyi.gateway.vo.RouteFilterVo;
import com.github.tangyi.gateway.vo.RoutePredicateVo;
import com.github.tangyi.gateway.vo.RouteVo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
......@@ -18,10 +18,8 @@ import org.springframework.cloud.gateway.filter.FilterDefinition;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.core.publisher.Mono;
import java.net.URI;
import java.util.ArrayList;
......@@ -51,6 +49,14 @@ public class RouteService extends CrudService<RouteMapper, Route> {
@Override
public int insert(Route route) {
int update;
if (StringUtils.isBlank(route.getRouteId()))
throw new CommonException("服务ID不能为空!");
// 校验服务路由是否存在
Route condition = new Route();
condition.setRouteId(route.getRouteId());
List<Route> routes = this.findList(condition);
if (CollectionUtils.isNotEmpty(routes))
throw new CommonException("该服务的路由已存在!");
route.setCommonValue("", GatewayConstant.SYS_CODE, GatewayConstant.DEFAULT_TENANT_CODE);
if ((update = this.dao.insert(route)) > 0) {
dynamicRouteService.add(routeDefinition(route));
......@@ -67,6 +73,8 @@ public class RouteService extends CrudService<RouteMapper, Route> {
@Override
public int update(Route route) {
int update;
if (StringUtils.isBlank(route.getRouteId()))
throw new CommonException("服务ID不能为空!");
route.setNewRecord(false);
route.setCommonValue("", GatewayConstant.SYS_CODE, GatewayConstant.DEFAULT_TENANT_CODE);
if ((update = this.dao.update(route)) > 0) {
......
......@@ -2,12 +2,13 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>service-api</artifactId>
<version>3.0.0</version>
<artifactId>auth-service-parent</artifactId>
<version>3.1.0</version>
</parent>
<artifactId>auth-api</artifactId>
<artifactId>auth-service-api</artifactId>
<name>${project.artifactId}</name>
<description>授权服务api</description>
......
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>service-api-impl</artifactId>
<version>3.0.0</version>
<artifactId>auth-service-parent</artifactId>
<version>3.1.0</version>
</parent>
<artifactId>auth-service</artifactId>
<name>${project.artifactId}</name>
......@@ -30,22 +31,22 @@
<artifactId>common-log</artifactId>
</dependency>
<!-- user-api -->
<!-- user-service-api -->
<dependency>
<groupId>com.github.tangyi</groupId>
<artifactId>user-api</artifactId>
<artifactId>user-service-api</artifactId>
</dependency>
<!-- auth-api -->
<!-- auth-service-api -->
<dependency>
<groupId>com.github.tangyi</groupId>
<artifactId>auth-api</artifactId>
<artifactId>auth-service-api</artifactId>
</dependency>
<!-- exam-api -->
<!-- exam-service-api -->
<dependency>
<groupId>com.github.tangyi</groupId>
<artifactId>exam-api</artifactId>
<artifactId>exam-service-api</artifactId>
</dependency>
<!-- web 服务 -->
......
package com.github.tangyi.auth.model;
import com.github.tangyi.common.core.enums.LoginType;
import lombok.Data;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
......@@ -17,9 +18,22 @@ public class CustomUserDetails extends User {
private static final long serialVersionUID = 1L;
/**
* 租户标识
*/
private String tenantCode;
/**
* 开始授权时间
*/
private long start;
/**
* 登录类型
*/
private LoginType loginType;
/**
* 构造方法
*
* @param username username
......@@ -27,9 +41,13 @@ public class CustomUserDetails extends User {
* @param enabled enabled
* @param authorities authorities
* @param tenantCode tenantCode
* @param start start
* @param loginType loginType
*/
public CustomUserDetails(String username, String password, boolean enabled, Collection<? extends GrantedAuthority> authorities, String tenantCode) {
public CustomUserDetails(String username, String password, boolean enabled, Collection<? extends GrantedAuthority> authorities, String tenantCode, long start, LoginType loginType) {
super(username, password, enabled, true, true, true, authorities);
this.tenantCode = tenantCode;
this.start = start;
this.loginType = loginType;
}
}
......@@ -5,10 +5,12 @@ import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.constant.ServiceConstant;
import com.github.tangyi.common.core.model.Log;
import com.github.tangyi.common.core.utils.SysUtil;
import com.github.tangyi.common.security.utils.SecurityUtil;
import com.github.tangyi.user.api.feign.UserServiceClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.event.EventListener;
import org.springframework.http.HttpMethod;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.event.AbstractAuthenticationEvent;
......@@ -39,6 +41,8 @@ public class CustomAuthenticationSuccessHandler {
@EventListener({AuthenticationSuccessEvent.class, InteractiveAuthenticationSuccessEvent.class})
public void processAuthenticationSuccessEvent(AbstractAuthenticationEvent event) {
// 注意:登录包括oauth2客户端、用户名密码登录都会触发AuthenticationSuccessEvent,这里只记录用户名密码登录的日志
if (event.getSource() instanceof OAuth2Authentication)
return;
if (event.getAuthentication().getPrincipal() instanceof CustomUserDetails) {
CustomUserDetails userDetails = (CustomUserDetails) event.getAuthentication().getPrincipal();
String tenantCode = userDetails.getTenantCode();
......@@ -48,7 +52,10 @@ public class CustomAuthenticationSuccessHandler {
Log logInfo = new Log();
logInfo.setCommonValue(username, SysUtil.getSysCode(), tenantCode);
logInfo.setTitle("用户登录");
//logInfo.setType(CommonConstant.STATUS_NORMAL);
logInfo.setType(CommonConstant.STATUS_NORMAL);
logInfo.setMethod(HttpMethod.POST.name());
logInfo.setTime(String.valueOf(System.currentTimeMillis() - userDetails.getStart()));
logInfo.setRequestUri(userDetails.getLoginType().getUri());
// 获取ip、浏览器信息
this.initLogInfo(logInfo, event.getSource());
logInfo.setServiceId(ServiceConstant.AUTH_SERVICE);
......@@ -65,22 +72,17 @@ public class CustomAuthenticationSuccessHandler {
* @param source source
*/
private void initLogInfo(Log logInfo, Object source) {
if (source instanceof OAuth2Authentication) {
OAuth2Authentication auth2Authentication = (OAuth2Authentication) source;
Object details = auth2Authentication.getDetails();
if (details instanceof OAuth2AuthenticationDetails) {
OAuth2AuthenticationDetails oAuth2AuthenticationDetails = (OAuth2AuthenticationDetails) details;
logInfo.setIp(oAuth2AuthenticationDetails.getRemoteAddress());
}
} else if (source instanceof UsernamePasswordAuthenticationToken) {
UsernamePasswordAuthenticationToken token = (UsernamePasswordAuthenticationToken) source;
Object details = token.getDetails();
if (details instanceof WebAuthenticationDetails) {
WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) details;
if (source instanceof UsernamePasswordAuthenticationToken) {
Object currentAuthentication = SecurityUtil.getCurrentAuthentication();
if (currentAuthentication instanceof UsernamePasswordAuthenticationToken) {
Object currentDetails = ((UsernamePasswordAuthenticationToken) currentAuthentication).getDetails();
if (currentDetails instanceof WebAuthenticationDetails) {
WebAuthenticationDetails webAuthenticationDetails = (WebAuthenticationDetails) currentDetails;
logInfo.setIp(webAuthenticationDetails.getRemoteAddress());
}
}
}
}
/**
* 获取用户名
......
......@@ -4,6 +4,7 @@ import com.github.tangyi.auth.api.module.WxSession;
import com.github.tangyi.auth.model.CustomUserDetails;
import com.github.tangyi.auth.service.WxSessionService;
import com.github.tangyi.common.core.constant.CommonConstant;
import com.github.tangyi.common.core.enums.LoginType;
import com.github.tangyi.common.core.exceptions.CommonException;
import com.github.tangyi.common.core.exceptions.TenantNotFoundException;
import com.github.tangyi.common.core.model.ResponseBean;
......@@ -61,11 +62,12 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
*/
@Override
public UserDetails loadUserByIdentifierAndTenantCode(String username, String tenantCode) throws UsernameNotFoundException, TenantNotFoundException {
long start = System.currentTimeMillis();
Tenant tenant = this.validateTenantCode(tenantCode);
UserVo userVo = userServiceClient.findUserByIdentifier(username, tenantCode);
if (userVo == null)
throw new UsernameNotFoundException("用户名不存在.");
return new CustomUserDetails(username, userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode());
return new CustomUserDetails(username, userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.PWD);
}
/**
......@@ -79,11 +81,12 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
*/
@Override
public UserDetails loadUserBySocialAndTenantCode(String social, String tenantCode) throws UsernameNotFoundException {
long start = System.currentTimeMillis();
Tenant tenant = this.validateTenantCode(tenantCode);
UserVo userVo = userServiceClient.findUserBySocial(social, tenantCode);
if (userVo == null)
throw new UsernameNotFoundException("用户手机号未注册.");
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode());
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.SMS);
}
/**
......@@ -99,6 +102,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
*/
@Override
public UserDetails loadUserByWxCodeAndTenantCode(String code, String tenantCode, WxUser wxUser) throws UsernameNotFoundException {
long start = System.currentTimeMillis();
Tenant tenant = this.validateTenantCode(tenantCode);
// 根据code获取openId和sessionKey
WxSession wxSession = wxService.code2Session(code);
......@@ -130,7 +134,7 @@ public class CustomUserDetailsServiceImpl implements CustomUserDetailsService {
userDto.setLoginTime(DateUtils.asDate(LocalDateTime.now()));
//userServiceClient.updateUser(userDto);
}
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode());
return new CustomUserDetails(userVo.getIdentifier(), userVo.getCredential(), CommonConstant.STATUS_NORMAL.equals(userVo.getStatus()), getAuthority(userVo), userVo.getTenantCode(), start, LoginType.WECHAT);
}
/**
......
......@@ -2,20 +2,17 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>spring-microservice-exam</artifactId>
<version>3.0.0</version>
</parent>
<artifactId>service-api-impl</artifactId>
<packaging>pom</packaging>
<name>${project.artifactId}</name>
<description>api实现</description>
<modules>
<module>auth-service-api</module>
<module>auth-service</module>
<module>user-service</module>
<module>exam-service</module>
<module>msc-service</module>
</modules>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>modules</artifactId>
<version>3.1.0</version>
</parent>
<artifactId>auth-service-parent</artifactId>
<name>${project.artifactId}</name>
<description>认证授权服务</description>
</project>
......@@ -2,12 +2,13 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>service-api</artifactId>
<version>3.0.0</version>
<artifactId>exam-service-parent</artifactId>
<version>3.1.0</version>
</parent>
<artifactId>exam-api</artifactId>
<artifactId>exam-service-api</artifactId>
<name>${project.artifactId}</name>
<description>考试服务api</description>
......
package com.github.tangyi.exam.api.module;
import com.github.tangyi.common.core.persistence.BaseEntity;
import lombok.Data;
/**
* 考试权限
*
* @author tangyi
* @date 2019-07-16 14:01
*/
@Data
public class ExaminationAuth extends BaseEntity<ExaminationAuth> {
/**
* 学生ID
*/
private String userId;
/**
* 考试ID
*/
private String examinationId;
}
......@@ -28,7 +28,7 @@ public class ExaminationSubject extends BaseEntity<ExaminationSubject> {
private Integer serialNumber;
/**
* 题目类型,0:选择题,1:简答题
* 题目类型,0:选择题,1:简答题,2:判断题,3:多选题
*/
private Integer type;
}
package com.github.tangyi.exam.api.module;
import com.github.tangyi.common.core.persistence.BaseEntity;
import lombok.Data;
import javax.validation.constraints.NotBlank;
/**
* 判断题
*
* @author tangyi
* @date 2019-07-16 12:57
*/
@Data
public class SubjectJudgement extends BaseEntity<SubjectJudgement> {
/**
* 题目分类ID
*/
private String categoryId;
/**
* 题目序号
*/
@NotBlank(message = "题目序号不能为空")
private Integer serialNumber;
/**
* 题目名称
*/
@NotBlank(message = "题目名称不能为空")
private String subjectName;
/**
* 参考答案
*/
private String answer;
/**
* 分值
*/
@NotBlank(message = "题目分值不能为空")
private Integer score;
/**
* 解析
*/
private String analysis;
/**
* 难度等级
*/
private Integer level;
}
......@@ -2,10 +2,11 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<packaging>jar</packaging>
<parent>
<groupId>com.github.tangyi</groupId>
<artifactId>service-api-impl</artifactId>
<version>3.0.0</version>
<artifactId>exam-service-parent</artifactId>
<version>3.1.0</version>
</parent>
<artifactId>exam-service</artifactId>
<name>${project.artifactId}</name>
......@@ -36,16 +37,16 @@
<artifactId>common-feign</artifactId>
</dependency>
<!-- user-api -->
<!-- user-service-api -->
<dependency>
<groupId>com.github.tangyi</groupId>
<artifactId>user-api</artifactId>
<artifactId>user-service-api</artifactId>
</dependency>
<!-- exam-api -->
<!-- exam-service-api -->
<dependency>
<groupId>com.github.tangyi</groupId>
<artifactId>exam-api</artifactId>
<artifactId>exam-service-api</artifactId>
</dependency>
<!-- web 服务 -->
......
......@@ -33,10 +33,10 @@ public class ExaminationInitConfig {
log.info("开始加载考试信息.");
// 查询已发布的考试
Examination examination = new Examination();
//examination.setStatus(CommonConstant.STATUS_NORMAL);
examination.setStatus(CommonConstant.STATUS_NORMAL.toString());
Stream<Examination> examinationStream = examinationService.findList(examination).stream();
if (Optional.ofNullable(examinationStream).isPresent())
examinationStream.forEach(tempExamination -> redisTemplate.opsForValue().set("examination::" + tempExamination.getId(), tempExamination));
examinationStream.forEach(tempExamination -> redisTemplate.opsForValue().set(tempExamination.getTenantCode() + ":examination:" + tempExamination.getId(), tempExamination));
log.info("考试信息加载完成.");
}
}
This diff is collapsed. Click to expand it.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment