diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/.gitignore" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/.gitignore" new file mode 100644 index 0000000000000000000000000000000000000000..9ac53673cbfcb8ac953665716cb63a60804df2de --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/.gitignore" @@ -0,0 +1,7 @@ +target/ +logs/ +.classpath +.project +.settings +.factorypath +upload/ \ No newline at end of file diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/Dockerfile" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/Dockerfile" new file mode 100644 index 0000000000000000000000000000000000000000..1c493477a0c6548b84acce328b4d947851baac57 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/Dockerfile" @@ -0,0 +1,15 @@ +#基础镜像 +FROM adoptopenjdk/openjdk8-openj9:alpine-slim + +RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone + +#拷贝发布包 +COPY target/*.jar /root/app.jar + +#指定交互端口 +EXPOSE 8080 + +CMD ["--server.port=8080"] + +#项目的启动方式 +ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom", "-Xshareclasses", "-Xquickstart", "-jar", "/root/app.jar"] diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/README.md" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/README.md" new file mode 100644 index 0000000000000000000000000000000000000000..e8ceeba4283f5f2646970f1cf107f9fe93190ded --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/README.md" @@ -0,0 +1,96 @@ +# springboot-git + +springboot工程操作git + +![输入图片说明](images/image.png) + + +最新版本已支持docker镜像部署,完整的编排文件以及启动脚本见docker目录。 + +# 一、docker部署过程 + +## 1. 上传docker目录到安装了docker环境的服务器 + +目录结构 + +```shell +├── docker-compose.yml +├── restart.sh +├── restart-simple.sh +└── stop.sh + +``` + +## 2. 运行命令启动容器 + +```shell +sh restart.sh +``` + +输出结果如下: + +```sh +[root@00fly docker-git]# sh restart.sh +[+] Running 9/9 + ✔ git-web 7 layers [⣿⣿⣿⣿⣿⣿⣿] 0B/0B Pulled 21.6s + ✔ 97518928ae5f Already exists 0.0s + ✔ b109695f6e59 Already exists 0.0s + ✔ 3ac0199bf17e Already exists 0.0s + ✔ 14cce039e329 Already exists 0.0s + ✔ 1bc1e3a5cc47 Already exists 0.0s + ✔ afe7d63db613 Pull complete 0.2s + ✔ 18a218fb6784 Pull complete 20.3s + ✔ git-simple Pulled 21.6s +[+] Running 2/3 + ⠴ Network docker-git_default Created 0.5s + ✔ Container git-web Started 0.4s + ✔ Container git-simple Started +``` + +输入`docker ps`查看,可以看到启动了2个服务,如**8082**端口被占用,请自行修改`docker-compose.yml` + +![docker-ps](images/docker-ps.png) + +为什么启动2个服务? +- git-web是我们通过接口配置git参数,一旦参数配置完成后,便可以关了他。 +- git-simple是日常后台执行git推送,无需开放端口。 + +# 二、操作指南 + +配置地址:http://{ip}:8082/doc.html + +## 1. 设置请求token +如提示:禁止访问,token信息不合法,按下述步骤操作: + +- 查看后台日志 +![查看后台日志](images/log.png) + +- 请求头设置token +![请求头设置token](images/token.png) + +- 刷新页面 + + +## 2. 设置git仓库参数,支持设置多个仓库 +![设置git仓库参数](images/git-setup.png) + +注意: **git项目根目录下一定要创建 README.md文件,此程序会自动替换最后一行内容为提交时间戳。** + +## 3. 设置运行时间 +![设置运行时间](images/times-setup.png) + +## 4. 测试一次远程提交 +![测试一次远程提交](images/remote-test.png) + +## 5. 查看运行时间 +![查看运行时间](images/times-show.png) + + +# 三.主要涉及技术点 + 1. jgit + 2. swagger使用 + 3. 定时任务cron + 4. 文件读写 + 5. 统一异常处理 + 6. log4j2日志 + diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/docker-compose.yml" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/docker-compose.yml" new file mode 100644 index 0000000000000000000000000000000000000000..20f0cfa4d8353fab802eaf4c13cd0c4f338e49bb --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/docker-compose.yml" @@ -0,0 +1,46 @@ +version: '3.7' +services: + git-web: + image: registry.cn-shanghai.aliyuncs.com/00fly/springboot-git:1.0.0 + container_name: git-web + deploy: + resources: + limits: + cpus: '1.0' + memory: 200M + reservations: + cpus: '0.05' + memory: 200M + ports: + - 8080:8080 + environment: + - white.list=127.0.0.1,101.224.211.68 + restart: on-failure + volumes: + - ./data/:/root/data/ + logging: + driver: json-file + options: + max-size: '5m' + max-file: '1' + + git-simple: + image: registry.cn-shanghai.aliyuncs.com/00fly/springboot-git:1.0.0 + container_name: git-simple + command: '--noweb' + deploy: + resources: + limits: + cpus: '2' + memory: 200M + reservations: + cpus: '0.05' + memory: 150M + restart: on-failure + volumes: + - ./data/:/root/data/ + logging: + driver: json-file + options: + max-size: '5m' + max-file: '1' diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/restart-simple.sh" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/restart-simple.sh" new file mode 100644 index 0000000000000000000000000000000000000000..f920e15141efa5e07d97397285b1f36c02d60f79 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/restart-simple.sh" @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down && docker-compose up -d git-simple && docker logs -f git-simple diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/restart.sh" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/restart.sh" new file mode 100644 index 0000000000000000000000000000000000000000..02d836d39a2187f90c97450a182730c8c6f3e101 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/restart.sh" @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down && docker-compose up -d diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/stop.sh" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/stop.sh" new file mode 100644 index 0000000000000000000000000000000000000000..86699d3f1759fb6ae75e8a3ca5e793407ad5ca3e --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/docker/stop.sh" @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose down diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/docker-ps.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/docker-ps.png" new file mode 100644 index 0000000000000000000000000000000000000000..143b4770ec23c1c9c80f2249b07cb2065fb47e37 Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/docker-ps.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/git-setup.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/git-setup.png" new file mode 100644 index 0000000000000000000000000000000000000000..237f00a961e8d0e2e648d3c527f03fd59d868370 Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/git-setup.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/image.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/image.png" new file mode 100644 index 0000000000000000000000000000000000000000..ba5567832894ebb3e837650f0e9e022587183a86 Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/image.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/log.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/log.png" new file mode 100644 index 0000000000000000000000000000000000000000..4668e568c57ff4823ca98db5a45f97c368b344c1 Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/log.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/remote-test.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/remote-test.png" new file mode 100644 index 0000000000000000000000000000000000000000..0257e883cb78bc1c2ebd63854e63f42066565ba6 Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/remote-test.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/times-setup.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/times-setup.png" new file mode 100644 index 0000000000000000000000000000000000000000..8814e4a5fdd0a262ce827ae603e799f335d7cf1f Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/times-setup.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/times-show.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/times-show.png" new file mode 100644 index 0000000000000000000000000000000000000000..6229f46de6ce2cceb01f9e308f976f79f552f7ff Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/times-show.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/token.png" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/token.png" new file mode 100644 index 0000000000000000000000000000000000000000..592116643e55ee4d904c3439c30ac7e8d1e17345 Binary files /dev/null and "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/images/token.png" differ diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/pom.xml" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/pom.xml" new file mode 100644 index 0000000000000000000000000000000000000000..2f661faf741d9040b231f96a0c32533501559abb --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/pom.xml" @@ -0,0 +1,175 @@ + + + 4.0.0 + com.fly + springboot-git + 1.0.0 + jar + + + org.springframework.boot + spring-boot-starter-parent + 2.2.3.RELEASE + + + + + UTF-8 + yyyyMMdd-HH + 1.8 + true + registry.cn-shanghai.aliyuncs.com + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + com.github.xiaoymin + knife4j-spring-boot-starter + 2.0.8 + + + org.springframework.boot + spring-boot-devtools + true + + + org.aspectj + aspectjweaver + + + org.eclipse.jgit + org.eclipse.jgit + 5.13.1.202206130422-r + + + + + com.lmax + disruptor + 3.4.2 + + + + org.projectlombok + lombok + provided + + + + org.springframework.boot + spring-boot-starter-test + test + + + org.junit.vintage + junit-vintage-engine + + + + + + org.apache.commons + commons-lang3 + + + commons-io + commons-io + 2.8.0 + + + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + + + + public + aliyun nexus + https://maven.aliyun.com/repository/public/ + + true + + + false + + + + + + ${project.artifactId}-${project.version} + + + org.springframework.boot + spring-boot-maven-plugin + + + + + io.fabric8 + docker-maven-plugin + 0.40.3 + + + package + + build + push + remove + + + + + + + + + ${docker.hub} + + + ${docker.hub}/00fly/${project.artifactId}:${project.version}-UTC-${maven.build.timestamp} + + ${project.basedir} + + + + ${docker.hub}/00fly/${project.artifactId}:${project.version} + + ${project.basedir} + + + + ${docker.hub}/00fly/${project.artifactId} + + ${project.basedir} + + + + + + + + diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/GitApplication.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/GitApplication.java" new file mode 100644 index 0000000000000000000000000000000000000000..2bdcbee15cee1dd6a7741e1dddf6fa04a8ec0781 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/GitApplication.java" @@ -0,0 +1,47 @@ +package com.fly; + +import java.net.InetAddress; + +import org.apache.commons.lang3.ArrayUtils; +import org.apache.commons.lang3.SystemUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.CommandLineRunner; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.scheduling.annotation.EnableScheduling; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +@EnableScheduling +@SpringBootApplication +public class GitApplication +{ + @Value("${server.port}") + Integer port; + + public static void main(String[] args) + { + boolean web = !ArrayUtils.contains(args, "--noweb"); + log.info("############### with Web Configuration: {} #############", web); + new SpringApplicationBuilder(GitApplication.class).web(web ? WebApplicationType.SERVLET : WebApplicationType.NONE).run(args); + } + + @Bean + @ConditionalOnWebApplication + CommandLineRunner openBrowser() + { + return args -> { + if (SystemUtils.IS_OS_WINDOWS && port > 0) + { + log.info("★★★★★★★★ now open Browser ★★★★★★★★ "); + String ip = InetAddress.getLocalHost().getHostAddress(); + String url = "http://" + ip + ":" + port; + Runtime.getRuntime().exec("cmd /c start /min " + url); + } + }; + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/aspect/AuthAspect.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/aspect/AuthAspect.java" new file mode 100644 index 0000000000000000000000000000000000000000..0b28f0b528a6d2e8bd23e4a7866f3bf0615b65da --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/aspect/AuthAspect.java" @@ -0,0 +1,89 @@ +package com.fly.core.aspect; + +import java.util.Date; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.time.DateUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import com.fly.core.entity.JsonResult; +import com.fly.core.utils.HttpRequestUtils; + +import lombok.extern.slf4j.Slf4j; + +/** + * + * aop处理鉴权 + * + * @author 00fly + * @version [版本号, 2022年11月29日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +@Slf4j +@Aspect +@Component +public class AuthAspect +{ + private String token = null; + + /** + * token有效时间(60分钟) + */ + private Date tokenTime; + + @Value("${white.list:127.0.0.1}") + private String whiteList; + + /** + * 切入点com.fly.git.web包及子包和使用PostMapping注解标注的类 + */ + @Pointcut("within(com.fly.git.web..*) && @annotation(org.springframework.web.bind.annotation.PostMapping)") + public void point() + { + } + + @Around("point()") + public Object around(ProceedingJoinPoint joinPoint) + throws Throwable + { + HttpServletRequest request = HttpRequestUtils.getHttpServletRequest(); + if (request != null) + { + String ip = request.getRemoteAddr(); + String token = request.getHeader("token"); + log.info("★★★★★★★★ request ip: {}, head token : {}", ip, token); + if (!StringUtils.contains(whiteList, ip) && !StringUtils.equals(token, getToken())) + { + return JsonResult.error("禁止访问,请添加白名单IP:" + ip + "或设置合法token"); + } + } + return joinPoint.proceed(); + } + + /** + * 获取token + * + * @return + * @see [类、类#方法、类#成员] + */ + private synchronized String getToken() + { + Date now = new Date(); + if (tokenTime == null || now.after(tokenTime)) + { + token = UUID.randomUUID().toString().replace("-", ""); + tokenTime = DateUtils.addMinutes(now, 60); + } + log.info("------ now valid token is: {}", token); + return token; + } +} \ No newline at end of file diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/DisableWebAutoConfig.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/DisableWebAutoConfig.java" new file mode 100644 index 0000000000000000000000000000000000000000..e8023378e1d918454e6d72d558f373c19b25504b --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/DisableWebAutoConfig.java" @@ -0,0 +1,24 @@ +package com.fly.core.config; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication; +import org.springframework.context.annotation.Configuration; + +import com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration; + +/** + * + * 非web环境下禁用AutoConfiguration + * + * @author 00fly + * @version [版本号, 2023年4月4日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +@Configuration +@ConditionalOnNotWebApplication +@EnableAutoConfiguration(exclude = Knife4jAutoConfiguration.class) +public class DisableWebAutoConfig +{ + +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/Knife4jConfig.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/Knife4jConfig.java" new file mode 100644 index 0000000000000000000000000000000000000000..e173faef2f60beb8f4ede003491c0a11e79c9512 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/Knife4jConfig.java" @@ -0,0 +1,59 @@ +package com.fly.core.config; + +import java.util.Collections; +import java.util.List; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import com.github.xiaoymin.knife4j.spring.annotations.EnableKnife4j; + +import io.swagger.annotations.ApiOperation; +import springfox.bean.validators.configuration.BeanValidatorPluginsConfiguration; +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiKey; +import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc; + +/** + * knife4j + * + * @author jack + */ +@Configuration +@EnableKnife4j +@EnableSwagger2WebMvc +@ConditionalOnWebApplication +@Import(BeanValidatorPluginsConfiguration.class) +public class Knife4jConfig +{ + + @Value("${knife4j.enable: true}") + private boolean enable; + + @Bean(value = "defaultApi2") + public Docket defaultApi2() + { + return new Docket(DocumentationType.SWAGGER_2).enable(enable) + .apiInfo(new ApiInfoBuilder().title("接口API").description("接口文档").termsOfServiceUrl("http://00fly.online/").contact(new Contact("xx", "xx", "xx")).version("1.0").build()) + // 分组名称 + .groupName("0.1版") + .select() + .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class)) + .paths(PathSelectors.any()) + .build() + .securitySchemes(security()); + } + + private List security() + { + return Collections.singletonList(new ApiKey("token", "token", "header")); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/ScheduledExecutorConfig.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/ScheduledExecutorConfig.java" new file mode 100644 index 0000000000000000000000000000000000000000..689336c16f3f167202df09cc0161ae877ee363e3 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/ScheduledExecutorConfig.java" @@ -0,0 +1,25 @@ +package com.fly.core.config; + +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledThreadPoolExecutor; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.concurrent.CustomizableThreadFactory; + +@Configuration +public class ScheduledExecutorConfig +{ + /** + * 默认线程池的大小为1,配置线程池支持多个线程并发执行 + * + * @return + * @see [类、类#方法、类#成员] + */ + @Bean + public ScheduledExecutorService scheduledExecutorService() + { + // return Executors.newScheduledThreadPool(5); + return new ScheduledThreadPoolExecutor(5, new CustomizableThreadFactory("schedule-pool-")); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/WebMvcConfig.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/WebMvcConfig.java" new file mode 100644 index 0000000000000000000000000000000000000000..0f9c29c0110148050e6e9f6be1d49f5f608f5e85 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/config/WebMvcConfig.java" @@ -0,0 +1,85 @@ +package com.fly.core.config; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * + * mvc配置 + * + * @author 00fly + * @version [版本号, 2021年4月23日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +@Configuration +@ConditionalOnWebApplication +public class WebMvcConfig implements WebMvcConfigurer +{ + @Override + public void configureMessageConverters(final List> converters) + { + converters.add(stringHttpMessageConverter()); + converters.add(mappingJackson2HttpMessageConverter()); + } + + @Override + public void configureContentNegotiation(final ContentNegotiationConfigurer configurer) + { + configurer.defaultContentType(MediaType.APPLICATION_JSON); + configurer.ignoreUnknownPathExtensions(false); + configurer.favorPathExtension(true); + configurer.favorParameter(false); + final Map mediaTypes = new ConcurrentHashMap<>(3); + mediaTypes.put("atom", MediaType.APPLICATION_ATOM_XML); + mediaTypes.put("html", MediaType.TEXT_HTML); + mediaTypes.put("json", MediaType.APPLICATION_JSON); + configurer.mediaTypes(mediaTypes); + } + + @Bean + StringHttpMessageConverter stringHttpMessageConverter() + { + return new StringHttpMessageConverter(); + } + + @Bean + MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() + { + final MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter(); + final List list = new ArrayList<>(); + list.add(MediaType.APPLICATION_JSON); + list.add(MediaType.APPLICATION_XML); + list.add(MediaType.TEXT_PLAIN); + list.add(MediaType.TEXT_HTML); + list.add(MediaType.TEXT_XML); + messageConverter.setSupportedMediaTypes(list); + return messageConverter; + } + + /** + * 等价于mvc中
+ * 等价于mvc中 + * + * @param registry + */ + @Override + public void addViewControllers(final ViewControllerRegistry registry) + { + registry.addViewController("/").setViewName("redirect:doc.html"); + registry.addViewController("/index").setViewName("index.html"); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/entity/JsonResult.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/entity/JsonResult.java" new file mode 100644 index 0000000000000000000000000000000000000000..9542c9a990cd324476c5af4f79ef7fe623bdc221 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/entity/JsonResult.java" @@ -0,0 +1,65 @@ +package com.fly.core.entity; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * + * 结果对象 + * + * @author 00fly + * @version [版本号, 2021年5月2日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +@Data +@ApiModel(description = "Json格式消息体") +public class JsonResult +{ + @ApiModelProperty(value = "数据对象") + private T data; + + @ApiModelProperty(value = "是否成功", required = true, example = "true") + private boolean success; + + @ApiModelProperty(value = "错误码") + private String errorCode; + + @ApiModelProperty(value = "提示信息") + private String message; + + public JsonResult() + { + super(); + } + + public static JsonResult success(T data) + { + JsonResult r = new JsonResult<>(); + r.setData(data); + r.setSuccess(true); + return r; + } + + public static JsonResult success() + { + JsonResult r = new JsonResult<>(); + r.setSuccess(true); + return r; + } + + public static JsonResult error(String code, String msg) + { + JsonResult r = new JsonResult<>(); + r.setSuccess(false); + r.setErrorCode(code); + r.setMessage(msg); + return r; + } + + public static JsonResult error(String msg) + { + return error("500", msg); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/exception/GlobalExceptionHandler.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/exception/GlobalExceptionHandler.java" new file mode 100644 index 0000000000000000000000000000000000000000..ad2c4c5131ee7ba5166253edf9be500278ebd083 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/exception/GlobalExceptionHandler.java" @@ -0,0 +1,64 @@ +package com.fly.core.exception; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.lang3.StringUtils; +import org.springframework.validation.BindException; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +import com.fly.core.entity.JsonResult; + +import lombok.extern.slf4j.Slf4j; + +/** + * 统一异常处理器 + * + * @author 00fly + * @version [版本号, 2018-09-11] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +@Slf4j +@RestControllerAdvice +public class GlobalExceptionHandler +{ + @ExceptionHandler(value = Exception.class) + public JsonResult handleBadRequest(Exception exception) + { + // JSR303参数校验异常 + if (exception instanceof BindException) + { + BindingResult bindingResult = ((BindException)exception).getBindingResult(); + if (null != bindingResult && bindingResult.hasErrors()) + { + List errMsg = new ArrayList<>(); + bindingResult.getFieldErrors().stream().forEach(fieldError -> { + errMsg.add(fieldError.getDefaultMessage()); + }); + Collections.sort(errMsg); + return JsonResult.error(StringUtils.join(Arrays.asList(errMsg), ",")); + } + } + + // 手动抛出的ValidateException + if (exception instanceof ValidateException) + { + return JsonResult.error(exception.getMessage()); + } + + // Assert异常 + if (exception instanceof IllegalArgumentException) + { + return JsonResult.error(exception.getMessage()); + } + + // 其余情况 + log.error("Error: handleBadRequest StackTrace : {}", exception); + return JsonResult.error(StringUtils.defaultString(exception.getMessage(), "系统异常,请联系管理员")); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/exception/ValidateException.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/exception/ValidateException.java" new file mode 100644 index 0000000000000000000000000000000000000000..9d6c15f35c8be0da277eb45db22d4e0313946a2c --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/exception/ValidateException.java" @@ -0,0 +1,16 @@ +package com.fly.core.exception; + +public class ValidateException extends RuntimeException +{ + private static final long serialVersionUID = -939208231165751812L; + + public ValidateException() + { + super(); + } + + public ValidateException(String message) + { + super(message); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/BeanUtils.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/BeanUtils.java" new file mode 100644 index 0000000000000000000000000000000000000000..8974fcf1b29a81ea30dfff5ea206400471760d8c --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/BeanUtils.java" @@ -0,0 +1,55 @@ +package com.fly.core.utils; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.springframework.cglib.beans.BeanMap; + +public class BeanUtils +{ + /** + * 将map装换为javabean对象 + * + * @param map + * @param bean + * @return + */ + public static T mapToBean(Map map, T bean) + { + BeanMap beanMap = BeanMap.create(bean); + for (String key : map.keySet()) + { + beanMap.put(key.toLowerCase(), map.get(key)); // 转换成小写处理,否则无法设置属性 + } + return bean; + } + + /** + * 将List>转换为List + * + * @param maps + * @param clazz + * @return + * @throws InstantiationException + * @throws IllegalAccessException + */ + public static List mapsToObjects(List> maps, Class clazz) + throws InstantiationException, IllegalAccessException + { + List list = new ArrayList(); + if (maps != null && maps.size() > 0) + { + Map map = null; + T bean = null; + for (int i = 0, size = maps.size(); i < size; i++) + { + map = maps.get(i); + bean = clazz.newInstance(); + mapToBean(map, bean); + list.add(bean); + } + } + return list; + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/HttpRequestUtils.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/HttpRequestUtils.java" new file mode 100644 index 0000000000000000000000000000000000000000..018dab1e30b7c396a394eaf44bcdfc3c4b8df934 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/HttpRequestUtils.java" @@ -0,0 +1,19 @@ +package com.fly.core.utils; + +import javax.servlet.http.HttpServletRequest; + +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +public class HttpRequestUtils +{ + public static HttpServletRequest getHttpServletRequest() + { + ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes)RequestContextHolder.getRequestAttributes(); + if (servletRequestAttributes != null) + { + return servletRequestAttributes.getRequest(); + } + return null; + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/MD5Utils.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/MD5Utils.java" new file mode 100644 index 0000000000000000000000000000000000000000..c2f3813f7eff39a7a499e5806ef87f4b8cdc19d5 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/MD5Utils.java" @@ -0,0 +1,41 @@ +package com.fly.core.utils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + +import org.springframework.util.DigestUtils; + +public class MD5Utils +{ + /** + * MD5加密 + * + * @explain spring实现 + * @param str 待加密字符串 + * @return 16进制加密字符串 + */ + public static String encryptToMD5(String str) + { + return DigestUtils.md5DigestAsHex(str.getBytes(StandardCharsets.UTF_8)); + } + + /** + * MD5加密 + * + * @explain spring实现 + * @param file 待加密文件 + * @return 16进制加密字符串 + * @throws IOException + */ + public static String encryptToMD5(File file) + throws IOException + { + try (InputStream fis = new FileInputStream(file)) + { + return DigestUtils.md5DigestAsHex(fis); + } + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/SpringContextUtils.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/SpringContextUtils.java" new file mode 100644 index 0000000000000000000000000000000000000000..e135ad53302eebde128f9d92bea28dbc1367c82f --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/core/utils/SpringContextUtils.java" @@ -0,0 +1,52 @@ +package com.fly.core.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * Spring Context 工具类 + */ +@Component +public class SpringContextUtils implements ApplicationContextAware +{ + public static ApplicationContext applicationContext; + + public static boolean containsBean(String name) + { + return applicationContext.containsBean(name); + } + + public synchronized static T getBean(Class clazz) + { + return applicationContext.getBean(clazz); + } + + public static Object getBean(String name) + { + return applicationContext.getBean(name); + } + + public static T getBean(String name, Class requiredType) + { + return applicationContext.getBean(name, requiredType); + } + + public static Class getType(String name) + { + return applicationContext.getType(name); + } + + public static boolean isSingleton(String name) + { + return applicationContext.isSingleton(name); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException + { + SpringContextUtils.applicationContext = applicationContext; + } +} \ No newline at end of file diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/model/GitInfo.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/model/GitInfo.java" new file mode 100644 index 0000000000000000000000000000000000000000..ad519cc6d06be9c5c237f24918fe3358f81c765c --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/model/GitInfo.java" @@ -0,0 +1,34 @@ +package com.fly.git.model; + +import java.io.Serializable; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(description = "git参数信息") +public class GitInfo implements Serializable +{ + private static final long serialVersionUID = -4864847400188602713L; + + @NotBlank(message = "用户名不能为空") + @ApiModelProperty(value = "用户名", required = true) + private String username; + + @NotBlank(message = "密码或个人令牌不能为空") + @ApiModelProperty(value = "密码或个人令牌", required = true) + private String password; + + @NotBlank(message = "注册邮箱不能为空") + @Email(message = "注册邮箱不合法") + @ApiModelProperty(value = "注册邮箱", required = true) + private String email; + + @NotBlank(message = "git项目地址不能为空") + @ApiModelProperty(value = "git项目地址", example = "https://gitee.com/00fly/git-test.git", required = true) + private String remoteGit; +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/model/GitRunInfo.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/model/GitRunInfo.java" new file mode 100644 index 0000000000000000000000000000000000000000..b8350d93a0f83c92cdf47681082b487dc257d466 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/model/GitRunInfo.java" @@ -0,0 +1,86 @@ +package com.fly.git.model; + +import java.io.File; +import java.io.IOException; +import java.util.Calendar; +import java.util.Set; +import java.util.concurrent.ConcurrentSkipListSet; +import java.util.stream.IntStream; + +import org.apache.commons.lang3.RandomUtils; +import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider; + +import com.fly.core.utils.MD5Utils; + +import lombok.Data; +import lombok.extern.slf4j.Slf4j; + +/** + * git运行信息 + * + * @author 00fly + * + */ +@Data +@Slf4j +public class GitRunInfo +{ + /** + * git参数信息 + */ + private GitInfo gitInfo; + + /** + * 代码本地目录 + */ + private String localPath; + + /** + * 鉴权信息 + */ + private UsernamePasswordCredentialsProvider credentialsProvider; + + /** + * 定时任务运行时间 + */ + private Set runHours = new ConcurrentSkipListSet<>(); + + /** + * 上次运行时间 + */ + private Long lastRunTime; + + /** + * 上次提交的内容 + */ + String commitText; + + public GitRunInfo(GitInfo gitInfo) + { + super(); + try + { + this.gitInfo = gitInfo; + this.credentialsProvider = new UsernamePasswordCredentialsProvider(gitInfo.getUsername(), gitInfo.getPassword()); + this.localPath = new File("project/" + MD5Utils.encryptToMD5(gitInfo.getRemoteGit())).getCanonicalPath(); + registerHours(); + } + catch (IOException e) + { + log.error("###### GitRunInfo init failure!", e.getMessage()); + } + } + + /** + * registerRunHours + * + * @see [类、类#方法、类#成员] + */ + public void registerHours() + { + runHours.clear(); + int curHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); + IntStream.range(curHour + 1, 24).filter(n -> RandomUtils.nextInt(0, 10) > 6).forEach(runHours::add); + log.info("---- runHours init success: {} ----", runHours); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/service/GitClientService.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/service/GitClientService.java" new file mode 100644 index 0000000000000000000000000000000000000000..cea196c87ba8091b7e082f72a47aea5cc0aaf0fc --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/service/GitClientService.java" @@ -0,0 +1,374 @@ +package com.fly.git.service; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FilenameFilter; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import javax.annotation.PostConstruct; + +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.RandomUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.SystemUtils; +import org.apache.commons.lang3.time.DateFormatUtils; +import org.eclipse.jgit.api.AddCommand; +import org.eclipse.jgit.api.CloneCommand; +import org.eclipse.jgit.api.CommitCommand; +import org.eclipse.jgit.api.Git; +import org.eclipse.jgit.api.PushCommand; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.InvalidRemoteException; +import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.api.errors.TransportException; +import org.eclipse.jgit.diff.DiffEntry; +import org.eclipse.jgit.diff.DiffEntry.ChangeType; +import org.eclipse.jgit.internal.storage.file.FileRepository; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.util.Assert; + +import com.fly.core.exception.ValidateException; +import com.fly.core.utils.HttpRequestUtils; +import com.fly.git.model.GitInfo; +import com.fly.git.model.GitRunInfo; + +import lombok.extern.slf4j.Slf4j; + +/** + * + * GitClientService + * + * @author 00fly + * @version [版本号, 2021年6月27日] + * @see [相关类/方法] + * @since [产品/模块版本] + */ +@Slf4j +@Service +public class GitClientService +{ + private List gitRunInfos = new ArrayList<>(); + + public List getGitRunInfos() + { + return gitRunInfos; + } + + /** + * 初始化 + * + * @see [类、类#方法、类#成员] + */ + @PostConstruct + public void init() + { + // 遍历data目录 + File data = new File("data"); + if (!data.exists()) + { + data.mkdirs(); + log.error("####### data directory is empty!"); + return; + } + Collection files = FileUtils.listFiles(data, new String[] {"ser"}, false); + if (files.isEmpty()) + { + log.error("####### not find any file in data directory!"); + return; + } + gitRunInfos.clear(); + for (File file : files) + { + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) + { + GitInfo gitInfo = (GitInfo)ois.readObject(); + Assert.notNull(gitInfo, "gitInfo is null"); + Assert.isTrue(StringUtils.isNoneEmpty(gitInfo.getUsername(), gitInfo.getPassword(), gitInfo.getEmail(), gitInfo.getRemoteGit()), "git params is empty"); + GitRunInfo gitRunInfo = new GitRunInfo(gitInfo); + gitRunInfos.add(gitRunInfo); + log.info("****** init from file [{}] success!", file.getAbsolutePath()); + } + catch (IOException | ClassNotFoundException e) + { + log.error("###### init failure! {}", e.getMessage()); + } + } + } + + /** + * 克隆远程库 + * + * @throws InvalidRemoteException + * @throws TransportException + * @throws GitAPIException + * @see [类、类#方法、类#成员] + */ + public void gitClone(GitRunInfo gitRunInfo) + throws InvalidRemoteException, TransportException, GitAPIException + { + GitInfo gitInfo = gitRunInfo.getGitInfo(); + Assert.notNull(gitInfo, "gitInfo is null"); + CloneCommand cloneCommand = Git.cloneRepository(); + cloneCommand.setURI(gitInfo.getRemoteGit()).setBranch("master").setCredentialsProvider(gitRunInfo.getCredentialsProvider()); + cloneCommand.setDirectory(new File(gitRunInfo.getLocalPath())); + try (Git git = cloneCommand.call()) + { + log.info("★★★★ gitClone success! tag: {}", git.tag()); + } + } + + /** + * 本地提交代码 + */ + public void localCommit(GitRunInfo gitRunInfo) + throws IOException, GitAPIException, JGitInternalException + { + GitInfo gitInfo = gitRunInfo.getGitInfo(); + Assert.notNull(gitInfo, "gitInfo is null"); + try (Git git = new Git(new FileRepository(gitRunInfo.getLocalPath() + "/.git"))) + { + String remark = DateFormatUtils.format(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss") + " auto commit."; + git.commit().setAmend(true).setAuthor(gitInfo.getUsername(), gitInfo.getEmail()).setMessage(remark).call(); + } + } + + /** + * 拉取远程仓库内容到本地 + */ + public void remotePull(GitRunInfo gitRunInfo) + throws IOException, GitAPIException + { + GitInfo gitInfo = gitRunInfo.getGitInfo(); + Assert.notNull(gitInfo, "gitInfo is null"); + try (Git git = new Git(new FileRepository(gitRunInfo.getLocalPath() + "/.git"))) + { + git.pull().setRemote("origin").setRemoteBranchName("master").setCredentialsProvider(gitRunInfo.getCredentialsProvider()).call(); + } + } + + /** + * push本地代码到远程仓库地址 + */ + public void remotePush(GitRunInfo gitRunInfo) + throws IOException, JGitInternalException, GitAPIException + { + GitInfo gitInfo = gitRunInfo.getGitInfo(); + Assert.notNull(gitInfo, "gitInfo is null"); + try (Git git = new Git(new FileRepository(gitRunInfo.getLocalPath() + "/.git"))) + { + git.push().setRemote("origin").setCredentialsProvider(gitRunInfo.getCredentialsProvider()).call(); + } + } + + /** + * 定时任务调度逻辑 + * + * @see [类、类#方法、类#成员] + */ + @Scheduled(cron = "0 0 0/1 * * ?") + public void schedule() + { + for (GitRunInfo gitRunInfo : gitRunInfos) + { + int curHour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY); + Set runHours = gitRunInfo.getRunHours(); + if (runHours.isEmpty() || curHour == 0) + { + gitRunInfo.registerHours(); + } + log.info("---- runHours is {} ----", runHours); + + // 到达设定时间点或当天未提交过 + String date = DateFormatUtils.format(System.currentTimeMillis(), "yyyy-MM-dd"); + String commitText = gitRunInfo.getCommitText(); + if (runHours.contains(curHour) || !StringUtils.startsWith(commitText, date)) + { + try + { + // 删除project目录 + if (SystemUtils.IS_OS_UNIX) + { + Runtime.getRuntime().exec(new String[] {"/bin/sh", "-c", "rm -rf " + gitRunInfo.getLocalPath()}); + } + else if (SystemUtils.IS_OS_WINDOWS) + { + Runtime.getRuntime().exec("cmd /c start " + gitRunInfo.getLocalPath()); + TimeUnit.SECONDS.sleep(1); + Runtime.getRuntime().exec("cmd /c rd /s/q " + gitRunInfo.getLocalPath()); + } + long seconds = RandomUtils.nextLong(10, 100L); + log.info("★★★★ thread will sleep seconds: {}", seconds); + TimeUnit.SECONDS.sleep(seconds); + runGitAll(); + } + catch (InterruptedException | IOException | GitAPIException e) + { + log.error("schedule error", e.getCause()); + } + } + } + } + + /** + * 全流程 + * + * @throws IOException + * @throws GitAPIException + * @throws InterruptedException + * + * @see [类、类#方法、类#成员] + */ + public void runGitAll() + throws IOException, GitAPIException + { + for (GitRunInfo gitRunInfo : gitRunInfos) + { + GitInfo gitInfo = gitRunInfo.getGitInfo(); + Assert.notNull(gitInfo, "gitInfo is null"); + + // 仅限制http接口请求,不影响定时任务 + if (HttpRequestUtils.getHttpServletRequest() != null) + { + Long lastRunTime = gitRunInfo.getLastRunTime(); + if (lastRunTime != null && System.currentTimeMillis() < lastRunTime + 600000) + { + String msg = String.format("您请求过于频繁,请%s后再试", DateFormatUtils.format(lastRunTime + 600000, "HH:mm:ss")); + throw new ValidateException(msg); + } + gitRunInfo.setLastRunTime(System.currentTimeMillis()); + } + log.info("★★★★ it is time to ready run ......"); + if (!new File(gitRunInfo.getLocalPath()).exists()) + { + gitClone(gitRunInfo); + } + + // 替换最后一行内容 + File readMe = new File(gitRunInfo.getLocalPath() + "/README.md"); + List lines = FileUtils.readLines(readMe, StandardCharsets.UTF_8); + if (lines.size() > 1) + { + lines.remove(lines.size() - 1); + } + String commitText = DateFormatUtils.format(System.currentTimeMillis(), "yyyy-MM-dd HH:mm:ss"); + lines.add(commitText); + FileUtils.writeLines(readMe, StandardCharsets.UTF_8.name(), lines); + gitRunInfo.setCommitText(commitText); + + File rootDir = new File(gitRunInfo.getLocalPath()); + try (Git git = Git.open(rootDir)) + { + List files = Arrays.asList(rootDir.list(new FilenameFilter() + { + @Override + public boolean accept(File dir, String name) + { + return !name.endsWith(".git"); + } + })); + List diffEntries = git.diff().setPathFilter(PathFilterGroup.createFromStrings(files)).setShowNameAndStatusOnly(true).call(); + if (diffEntries == null || diffEntries.isEmpty()) + { + return; + } + // 被修改过的文件 + List updateFiles = new ArrayList(); + ChangeType changeType; + for (DiffEntry entry : diffEntries) + { + changeType = entry.getChangeType(); + switch (changeType) + { + case ADD: + case COPY: + case RENAME: + case MODIFY: + updateFiles.add(entry.getNewPath()); + break; + case DELETE: + updateFiles.add(entry.getOldPath()); + break; + } + } + + // 将文件提交到git仓库中,并返回本次提交的版本号 + // 1、将工作区的内容更新到暂存区 + AddCommand addCmd = git.add(); + for (String file : updateFiles) + { + addCmd.addFilepattern(file); + } + addCmd.call(); + + // 2、commit + CommitCommand commitCmd = git.commit(); + for (String file : updateFiles) + { + commitCmd.setOnly(file); + } + RevCommit revCommit = commitCmd.setCommitter(gitInfo.getUsername(), gitInfo.getEmail()).setMessage(commitText + " auto commit.").call(); + log.info("★★★★ local commit successful:{}", revCommit.getName()); + + // swagger测试忽略远程提交 + if (HttpRequestUtils.getHttpServletRequest() != null) + { + log.info("★★★★ Swagger HttpServletRequest Test, not call remote git push ★★★★ "); + continue; + } + + // 3、git push + log.info("★★★★ now call remote git push ★★★★"); + PushCommand push = git.push(); + push.setRemote("origin").setCredentialsProvider(gitRunInfo.getCredentialsProvider()).call(); + log.info("★★★★ remote git push successful ★★★★\n"); + } + } + } + + /** + * autoCommitPull + * + * @return + * @see [类、类#方法、类#成员] + */ + // @Scheduled(cron = "0 0 9-17 * * ?") + public void autoCommitPullAll() + { + for (GitRunInfo gitRunInfo : gitRunInfos) + { + autoCommitPull(gitRunInfo); + } + } + + private boolean autoCommitPull(GitRunInfo gitRunInfo) + { + try + { + log.info("★★★★ autoCommitPull ★★★★"); + if (!new File(gitRunInfo.getLocalPath()).exists()) + { + gitClone(gitRunInfo); + } + localCommit(gitRunInfo); + remotePush(gitRunInfo); + return true; + } + catch (JGitInternalException | GitAPIException | IOException e) + { + log.error("autoCommitPull error", e.getCause()); + return false; + } + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/web/IndexController.java" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/web/IndexController.java" new file mode 100644 index 0000000000000000000000000000000000000000..c686437227c87551a9f3680a3b848c8fec52c43b --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/java/com/fly/git/web/IndexController.java" @@ -0,0 +1,107 @@ +package com.fly.git.web; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.validation.Valid; + +import org.eclipse.jgit.api.errors.GitAPIException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.fly.core.entity.JsonResult; +import com.fly.core.utils.MD5Utils; +import com.fly.git.model.GitInfo; +import com.fly.git.model.GitRunInfo; +import com.fly.git.service.GitClientService; +import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +@Api(tags = "api接口") +@RestController +@RequestMapping("/git") +public class IndexController +{ + @Autowired + private GitClientService gitClient; + + @ApiOperationSupport(order = 10) + @ApiOperation("设置git参数") + @PostMapping("init") + public JsonResult init(@Valid GitInfo gitInfo) + throws FileNotFoundException, IOException + { + String project = MD5Utils.encryptToMD5(gitInfo.getRemoteGit()); + File file = new File("data/" + project + ".ser"); + file.getParentFile().mkdirs(); + try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))) + { + oos.writeObject(gitInfo); + } + gitClient.init(); + return JsonResult.success(); + } + + @ApiOperationSupport(order = 20) + @ApiOperation("设置运行时间") + @PostMapping("configHours") + public JsonResult configHours() + { + List gitRunInfos = gitClient.getGitRunInfos(); + if (gitRunInfos.isEmpty()) + { + return JsonResult.error("请先设置git参数"); + } + for (GitRunInfo gitRunInfo : gitRunInfos) + { + gitRunInfo.registerHours(); + } + return JsonResult.success("设置运行时间成功"); + } + + @ApiOperationSupport(order = 30) + @ApiOperation("测试远程提交") + @PostMapping("remote-commit") + public JsonResult commit() + throws IOException, GitAPIException + { + List gitRunInfos = gitClient.getGitRunInfos(); + if (gitRunInfos.isEmpty()) + { + return JsonResult.error("请先设置git参数"); + } + gitClient.runGitAll(); + return JsonResult.success(); + } + + @ApiOperationSupport(order = 40) + @ApiOperation("查询运行时间") + @GetMapping("queryHours") + public JsonResult queryHours() + { + List gitRunInfos = gitClient.getGitRunInfos(); + if (gitRunInfos.isEmpty()) + { + return JsonResult.error("请先设置git参数"); + } + Integer index = 1; + Map> runHoursAll = new HashMap<>(); + for (GitRunInfo gitRunInfo : gitRunInfos) + { + runHoursAll.put(index++, gitRunInfo.getRunHours()); + } + return JsonResult.success(runHoursAll); + } +} diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/resources/application.yml" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/resources/application.yml" new file mode 100644 index 0000000000000000000000000000000000000000..7faa8089f1b3f4caa60bde4f7212c09c5920852d --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/resources/application.yml" @@ -0,0 +1,8 @@ +server: + port: 8080 + servlet: + context-path: / + session: + timeout: 1800 +knife4j: + enable: true \ No newline at end of file diff --git "a/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/resources/log4j2.xml" "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/resources/log4j2.xml" new file mode 100644 index 0000000000000000000000000000000000000000..5ab6b66c7fe071cc0996427b82d580af814dc768 --- /dev/null +++ "b/Git\344\273\243\347\240\201\346\221\270\351\261\274-\347\250\213\345\272\217\347\214\277Git\351\241\271\347\233\256\344\273\243\347\240\201\350\207\252\345\212\250\346\217\220\344\272\244\347\245\236\345\231\250/src/main/resources/log4j2.xml" @@ -0,0 +1,59 @@ + + + + + ../logs/git + ../logs/git/7z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file