# Vhr-Server **Repository Path**: project_skeleton/Vhr-Server ## Basic Information - **Project Name**: Vhr-Server - **Description**: VHR-服务端 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-03-26 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## 项目介绍 微人事是一个前后端分离的人力资源管理系统,项目采用 SpringBoot+Vue 开发,项目加入常见的企业级应用所涉及到的技术点,例如 Redis、RabbitMQ 等。 - 项目地址:[https://github.com/lenve/vhr](https://github.com/lenve/vhr) - [项目部署视频教程(旧版)](https://mp.weixin.qq.com/s/qN01Le434FWom0c3jqiQmA) - [项目部署视频教程(新版)](https://mp.weixin.qq.com/s/dcJv6BIVFPnokI8nBf4IrQ) - [项目其他相关资料](./README_zh.md) ### 项目技术栈 #### 后端技术栈 1. Spring Boot 2. Spring Security 3. MyBatis 4. MySQL 5. Redis 6. RabbitMQ 7. Spring Cache 8. WebSocket 9. ... #### 前端技术栈 1. Vue 2. ElementUI 3. axios 4. vue-router 5. Vuex 6. WebSocket 7. vue-cli4 8. ... ### 项目效果图 首先,不同的用户在登录成功之后,根据不同的角色,会看到不同的系统菜单,完整菜单如下: ![p278](https://raw.githubusercontent.com/wiki/lenve/vhr/doc/p278.png) 不同用户登录上来之后,可能看到的会有差异,如下: ![p279](https://raw.githubusercontent.com/wiki/lenve/vhr/doc/p279.png) 每个用户的角色是由系统管理员进行分配的,系统管理员给用户分配角色的页面如下: ![p280](https://raw.githubusercontent.com/wiki/lenve/vhr/doc/p280.png) 系统管理员也可以管理不同角色可以操作的资源,页面如下: ![p281](https://raw.githubusercontent.com/wiki/lenve/vhr/doc/p281.png) ## 快速部署 1. clone 项目到本地 `git@github.com:lenve/vhr.git` 2. 数据库脚本使用 Flyway 管理,**不需要手动导入数据库脚本**,只需要提前在本地 MySQL 中创建一个空的数据库 vhr,并修改项目中关于数据的配置(resources 目录下的 application.properties 文件中)即可 3. 提前准备好 Redis,在 项目的 application.properties 文件中,将 Redis 配置改为自己的 4. 提前准备好 RabbitMQ,在项目的 application.properties 文件中将 RabbitMQ 的配置改为自己的(**注意,RabbitMQ 需要分别修改 mailserver 和 vhrserver 的配置文件**) 5. 在 IntelliJ IDEA 中打开 vhr 项目,启动 mailserver 模块 6. 运行 vhrserver 中的 vhr-web 模块 7、打包时在最外围打包; **OK,至此,服务端就启动成功了,此时我们直接在地址栏输入 `http://localhost:8081/index.html` 即可访问我们的项目,如果要做二次开发,请继续看第七、八步。** 7. 进入到vuehr目录中,在命令行依次输入如下命令: ``` # 安装依赖 npm install # 在 localhost:8080 启动项目 npm run serve ``` 由于我在 vuehr 项目中已经配置了端口转发,将数据转发到 Spring Boot 上,因此项目启动之后,在浏览器中输入 `http://localhost:8080` 就可以访问我们的前端项目了,所有的请求通过端口转发将数据传到 Spring Boot 中(注意此时不要关闭 Sprin gBoot 项目)。 8. 最后可以用 WebStorm 等工具打开 vuehr 项目,继续开发,开发完成后,当项目要上线时,依然进入到 vuehr 目录,然后执行如下命令: ``` npm run build ``` 该命令执行成功之后,vuehr 目录下生成一个 dist 文件夹,将该文件夹中的两个文件 static 和 index.html 拷贝到 Spring Boot 项目中 resources/static/ 目录下,然后就可以像第 6 步那样直接访问了(关于前后端分离部署,大家也可以参考这个[使用 Nginx 部署前后端分离项目,解决跨域问题](https://mp.weixin.qq.com/s/C7PIck3SIPPTcA3NX3ELoQ))。 [SpringBoot + Vue之分页操作](https://www.icode9.com/content-4-176118.html) >分页不生效问题 > [SpringBoot 使用 @Transactional无效](https://www.cnblogs.com/wochenjun/p/10840233.html) >分析:确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚。 于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致。 **步骤 7 中需要大家对 NodeJS、NPM 等有一定的使用经验,不熟悉的小伙伴可以先自行搜索学习下,推荐 [Vue 官方教程](https://cn.vuejs.org/v2/guide/)。** ## 文档 文档是对项目开发过程中遇到的一些问题的详细记录,主要是为了帮助没有基础的小伙伴快速理解这个项目。 1. [权限数据库设计](https://github.com/lenve/vhr/wiki/1.%E6%9D%83%E9%99%90%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AE%BE%E8%AE%A1) 2. [服务端环境搭建](https://github.com/lenve/vhr/wiki/2.%E6%9C%8D%E5%8A%A1%E7%AB%AF%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA) 3. [动态处理角色和资源的关系](https://github.com/lenve/vhr/wiki/3.%E5%8A%A8%E6%80%81%E5%A4%84%E7%90%86%E8%A7%92%E8%89%B2%E5%92%8C%E8%B5%84%E6%BA%90%E7%9A%84%E5%85%B3%E7%B3%BB) 4. [密码加密并加盐](https://github.com/lenve/vhr/wiki/4.%E5%AF%86%E7%A0%81%E5%8A%A0%E5%AF%86%E5%B9%B6%E5%8A%A0%E7%9B%90) 5. [服务端异常的统一处理](https://github.com/lenve/vhr/wiki/5.%E6%9C%8D%E5%8A%A1%E7%AB%AF%E5%BC%82%E5%B8%B8%E7%9A%84%E7%BB%9F%E4%B8%80%E5%A4%84%E7%90%86) 6. [axios 请求封装,请求异常统一处理](https://github.com/lenve/vhr/wiki/6.axios%E8%AF%B7%E6%B1%82%E5%B0%81%E8%A3%85,%E8%AF%B7%E6%B1%82%E5%BC%82%E5%B8%B8%E7%BB%9F%E4%B8%80%E5%A4%84%E7%90%86) 7. [将请求方法挂到Vue上](https://github.com/lenve/vhr/wiki/7.%E5%B0%86%E8%AF%B7%E6%B1%82%E6%96%B9%E6%B3%95%E6%8C%82%E5%88%B0Vue%E4%B8%8A) 8. [登录状态的保存](https://github.com/lenve/vhr/wiki/8.%E7%99%BB%E5%BD%95%E7%8A%B6%E6%80%81%E7%9A%84%E4%BF%9D%E5%AD%98) 9. [登录成功后动态加载组件](https://github.com/lenve/vhr/wiki/9.%E7%99%BB%E5%BD%95%E6%88%90%E5%8A%9F%E5%90%8E%E5%8A%A8%E6%80%81%E5%8A%A0%E8%BD%BD%E7%BB%84%E4%BB%B6) 10. [角色资源关系管理](https://github.com/lenve/vhr/wiki/10.%E8%A7%92%E8%89%B2%E8%B5%84%E6%BA%90%E5%85%B3%E7%B3%BB%E7%AE%A1%E7%90%86) 11. [用户角色关系管理](https://github.com/lenve/vhr/wiki/11.%E7%94%A8%E6%88%B7%E8%A7%92%E8%89%B2%E5%85%B3%E7%B3%BB%E7%AE%A1%E7%90%86) #### 相关文档: 12. [部门数据库设计与存储过程编写](https://github.com/lenve/vhr/wiki/12.%E9%83%A8%E9%97%A8%E6%95%B0%E6%8D%AE%E5%BA%93%E8%AE%BE%E8%AE%A1%E4%B8%8E%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B%E7%BC%96%E5%86%99) 13. [递归查询与存储过程调用](https://github.com/lenve/vhr/wiki/13.%E9%80%92%E5%BD%92%E6%9F%A5%E8%AF%A2%E4%B8%8E%E5%AD%98%E5%82%A8%E8%BF%87%E7%A8%8B%E8%B0%83%E7%94%A8) 14. [Tree 树形控件使用要点](https://github.com/lenve/vhr/wiki/14.Tree%E6%A0%91%E5%BD%A2%E6%8E%A7%E4%BB%B6%E4%BD%BF%E7%94%A8%E8%A6%81%E7%82%B9) 15. [职位管理和职称管理功能介绍](https://github.com/lenve/vhr/wiki/15.%E8%81%8C%E4%BD%8D%E7%AE%A1%E7%90%86%E5%92%8C%E8%81%8C%E7%A7%B0%E7%AE%A1%E7%90%86%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D) 16. [组件复用](https://github.com/lenve/vhr/wiki/16.%E7%BB%84%E4%BB%B6%E5%A4%8D%E7%94%A8) 17. [[题外话]利用 git 标签回退至任意版本](https://github.com/lenve/vhr/wiki/17.%5B%E9%A2%98%E5%A4%96%E8%AF%9D%5D%E5%88%A9%E7%94%A8git%E6%A0%87%E7%AD%BE%E5%9B%9E%E9%80%80%E8%87%B3%E4%BB%BB%E6%84%8F%E7%89%88%E6%9C%AC) 18. [员工基本信息管理功能介绍](https://github.com/lenve/vhr/wiki/18.%E5%91%98%E5%B7%A5%E5%9F%BA%E6%9C%AC%E4%BF%A1%E6%81%AF%E7%AE%A1%E7%90%86%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D) 19. [Spring Boot 中自定义参数绑定](https://github.com/lenve/vhr/wiki/19.SpringBoot%E4%B8%AD%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%82%E6%95%B0%E7%BB%91%E5%AE%9A) 20. [高级搜索功能介绍](https://github.com/lenve/vhr/wiki/20.%E9%AB%98%E7%BA%A7%E6%90%9C%E7%B4%A2%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D) 21. [Excel 导入导出效果图](https://github.com/lenve/vhr/wiki/21.Excel%E5%AF%BC%E5%85%A5%E5%AF%BC%E5%87%BA%E6%95%88%E6%9E%9C%E5%9B%BE) 22. [SpringMVC 文件下载的两种方式](https://github.com/lenve/vhr/wiki/22.SpringMVC%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E7%9A%84%E4%B8%A4%E7%A7%8D%E6%96%B9%E5%BC%8F) 23. [POI 生成 Excel](https://github.com/lenve/vhr/wiki/23.POI%E7%94%9F%E6%88%90Excel) 24. [axios 下载文件](https://github.com/lenve/vhr/wiki/24.axios%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6) 25. [使用 POI 实现 Excel 导入](https://github.com/lenve/vhr/wiki/25.%E4%BD%BF%E7%94%A8POI%E5%AE%9E%E7%8E%B0Excel%E5%AF%BC%E5%85%A5) 26. [Spring Boot 中使用 Freemarker 邮件模板生成邮件](https://github.com/lenve/vhr/wiki/26.SpringBoot%E4%B8%AD%E4%BD%BF%E7%94%A8Freemarker%E9%82%AE%E4%BB%B6%E6%A8%A1%E6%9D%BF%E7%94%9F%E6%88%90%E9%82%AE%E4%BB%B6) 27. [Java 中邮件的发送](https://github.com/lenve/vhr/wiki/27.Java%E4%B8%AD%E9%82%AE%E4%BB%B6%E7%9A%84%E5%8F%91%E9%80%81) 28. [Spring Boot 中使用新线程发送邮件](https://github.com/lenve/vhr/wiki/28.SpringBoot%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%96%B0%E7%BA%BF%E7%A8%8B%E5%8F%91%E9%80%81%E9%82%AE%E4%BB%B6) 29. [工资账套管理功能介绍](https://github.com/lenve/vhr/wiki/29.%E5%B7%A5%E8%B5%84%E8%B4%A6%E5%A5%97%E7%AE%A1%E7%90%86%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D) 30. [员工账套设置功能介绍](https://github.com/lenve/vhr/wiki/30.%E5%91%98%E5%B7%A5%E8%B4%A6%E5%A5%97%E8%AE%BE%E7%BD%AE%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D) 31. [在线聊天功能介绍](https://github.com/lenve/vhr/wiki/31.%E5%9C%A8%E7%BA%BF%E8%81%8A%E5%A4%A9%E5%8A%9F%E8%83%BD%E4%BB%8B%E7%BB%8D) 32. [在线聊天功能实现](https://github.com/lenve/vhr/wiki/32.%E5%9C%A8%E7%BA%BF%E8%81%8A%E5%A4%A9%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0) 33. [系统通知功能实现](https://github.com/lenve/vhr/wiki/33.%E7%B3%BB%E7%BB%9F%E9%80%9A%E7%9F%A5%E5%8A%9F%E8%83%BD%E5%AE%9E%E7%8E%B0) 34. [两年了,微人事项目迎来了一次重大更新](https://mp.weixin.qq.com/s/Eo2RRB6zKQuPDMWlnCHDrw) ## 参考 - [vue-chat](https://github.com/microzz/vue-chat) ## Docker方式部署 1. 配置POM.xml ``` com.spotify dockerfile-maven-plugin 1.4.13 default build push ${docker.image.prefix}/${project.artifactId} true latest target/${project.build.finalName}.jar 注意:最终打的包名要与保持一致; ``` 2.配置settings.xml ``` com.spotify 远程仓库空间名称 远程仓库登录名 远程仓库密码 邮箱 ``` 3.编写env文件 ``` .env 文件包含了一些变量,这些变量可以在 docker-compose.yml 文件中通过 ${variable_name} 来引用。 . │ .env │ docker-compose.yml │ .................... └───────── 注意,EVN文件要与引用文件放置同一个目录,方便使用,否则会因目录问题不生效; ``` 3.配置DockerFile ``` FROM openjdk:8-jdk-alpine #引入一个父镜像,在此基础上进行添加只读层,FORM下面的命令,可以理解就是在已有的只读层,添加只读层 #设置编译镜像时加入的参数。 这里的JAR_FILE就是maven插件中的target/${project.build.finalName}.jar ARG JAR_FILE #(只支持将本地文件复制到容器 ,还有个ADD更强大但复杂点。)把app.jar放在docker image的根目录下 COPY ${JAR_FILE} /opt/app.jar #EXPOSE 指定于外界交互的端口 EXPOSE 8081 #解决验证码空指针问题,原因是 Alpine 太过精简,导致里面没有字体,只需要安装字体即可 RUN echo -e "https://mirror.tuna.tsinghua.edu.cn/alpine/v3.4/main\n\ https://mirror.tuna.tsinghua.edu.cn/alpine/v3.4/community" > /etc/apk/repositories RUN apk --update add curl bash ttf-dejavu && \ rm -rf /var/cache/apk/* #设置时区(定义了该镜像的时间格式及时区) #RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -Duser.timezone=Asia/Shanghai -Dfile.encoding=UTF-8 -jar /opt/app.jar ``` 4.编写docker-compose.yml文件 ``` version: '3' services: # --------------------------- # 前台 # --------------------------- hrserver-ui: image: registry.cn-beijing.aliyuncs.com/hrserver/hrserver-ui:latest volumes: # 挂载nginx的配置文件 - ./nginx.conf:/etc/nginx/nginx.conf container_name: web-service restart: always ports: - "80:80" networks: - net # --------------------------- # 邮件服务 # --------------------------- mailserver: image: registry.cn-beijing.aliyuncs.com/hrserver/mailserver:latest container_name: mailserver restart: always ports: - "8082:8082" networks: - net # --------------------------- # 后台服务 # --------------------------- vhr-web: image: registry.cn-beijing.aliyuncs.com/hrserver/vhr-web:latest container_name: vhr-web env_file: docker-compose.env # 从文件中获取配置 restart: always ports: - "8081:8081" networks: - net # --------------------------- # Redis # --------------------------- redis: image: redis:latest container_name: redis restart: always env_file: docker-compose.env # 从文件中获取配置 command: redis-server /usr/local/etc/redis/redis.conf ports: - "6379:6379" volumes: - ./redis-data:/data - ./redis.conf:/usr/local/etc/redis/redis.conf networks: - net # --------------------------- # rabbitMq # --------------------------- rabbit: image: rabbitmq:3.6.6-management-alpine container_name: rabbit-mq restart: always env_file: docker-compose.env # 从文件中获取配置 ports: - "5672:5672" - "15672:15672" environment: - RABBITMQ_DEFAULT_USER=guest - RABBITMQ_DEFAULT_PASS=guest networks: - net networks: net: driver: bridge volumes: data: driver: local Docker Compose是一个用来定义和运行复杂应用的Docker工具,一个使用Docker容器的应用,通常由多个容器组成。 注意:使用同一个docker-compose构建及服务编排文件,会将所有的container构建在同一网络下,涉及到负载均衡,分发请求至container时, 只需通过docker-compose里面的 service name 即可找到,而不是需要通过IP; ``` 5.编写Shell脚本 ``` #!/bin/sh # 配置文件根目录,固定是hrserver DOCKERHOME=/web/hnserver # 镜像名称前缀、标签 BASE_IMAGE_NAME=registry.cn-beijing.aliyuncs.com/hrserver BSEE_IMAGE_TAG=latest # 各服务的镜像名称 UI_SERVICE=$BASE_IMAGE_NAME/hrserver-ui:$BSEE_IMAGE_TAG MAIL_SERVICE=$BASE_IMAGE_NAME/mailserver:$BSEE_IMAGE_TAG WEB_SERVICE=$BASE_IMAGE_NAME/vhr-web:$BSEE_IMAGE_TAG case "$1" in # 删除容器 removeAll) echo "* 正在删除容器..." time docker rm $(docker ps -aq) -f echo "* 删除容器成功..." ;; # 拉取镜像 pull) echo "* 正在拉取后端镜像..." time docker pull $MAIL_SERVICE time docker pull $WEB_SERVICE echo "* 开始拉取前端镜像..." time docker pull $UI_SERVICE echo "* 拉取镜像成功..." ;; # 运行镜像 run) echo "* 开始运行后端服务镜像..." time docker-compose -f -p $DOCKERHOME/docker-compose-services.yml up -d echo "* 等待10s..." echo "* 运行成功..." ;; # 拉取镜像并运行 pullrun) echo "* 正在拉取后端镜像..." time docker pull $MAIL_SERVICE time docker pull $WEB_SERVICE echo "* 开始拉取前端镜像..." time docker pull $UI_SERVICE echo "* 拉取镜像成功..." echo "* 开始运行前端与后端服务镜像..." time docker-compose -f $DOCKERHOME/docker-compose-services.yml up -d echo "* 等待10s..." echo "* 运行成功..." ;; # 停止容器 stop) echo "* 正在停止容器..." time docker-compose -f $DOCKERHOME/docker-compose-services.yml stop echo "* 停止容器成功..." ;; # 重启容器 restart) echo "* 正在停止镜像..." time docker-compose -f $DOCKERHOME/docker-compose-services.yml restart ;; # 其它 *) echo "* ..." ;; esac exit 0 诠释: 该脚本主要用于从远程仓库拉取镜像、然后批量实现脚本的运行、删除、停止,执行的是对应的docker-compose.yml ``` 6.使用命令将镜像推送至远程仓库 ``` 将镜像推送到Registry $ sudo docker login --username=x心j静r如s水 registry.cn-beijing.aliyuncs.com $ sudo docker tag [ImageId] registry.cn-beijing.aliyuncs.com/hrserver/vhr-web:[镜像版本号] $ sudo docker push registry.cn-beijing.aliyuncs.com/vhr-web:[镜像版本号] 请根据实际镜像信息替换示例中的[ImageId]和[镜像版本号]参数。 $ sudo docker tag 6c69561208d2 registry.cn-beijing.aliyuncs.com/hrserver/vhr-web:latest $ sudo docker tag 8aed8174e20f registry.cn-beijing.aliyuncs.com/hrserver/mailserver:latest $ sudo docker tag 0d7826d3943c registry.cn-beijing.aliyuncs.com/hrserver/hrserver-ui:latest $ docker push registry.cn-beijing.aliyuncs.com/hrserver/vhr-web:latest $ docker push registry.cn-beijing.aliyuncs.com/hrserver/mailserver:latest $ docker push registry.cn-beijing.aliyuncs.com/hrserver/hrserver-ui:latest ``` 7.部署方式 ``` 将源码docs/deploy目录下的docker-compose.env、docker-compose-base.yml、 docker-compose-services.yml、nginx.conf、docker-compose.evn、 start.sh文件上传到服务器的自己创建的/web/hnserver目录下 (一)、批量执行脚本:通过脚本启动镜像、并生成容器 sed -i "s/\r//" start.sh ./start.sh run ./start.sh stop (二)、单个执行 docker-compose -f docker-compose-services.yml up -d (三)、实时查看docker容器日志 $ sudo docker logs -f -t --tail 行数 容器名 docker logs -f -t --tail 100 vhr-web docker logs -f -t --tail 100 web-service (四)、容器管理命令 列出所有处于停止状态的容器列表: docker ps -a -f status=exited 删除所有处于停止状态的容器 docker rm $(docker ps -a -f status=exited -q) 批量删除其他状态的容器方法同理。删除所有容器首先需要停止所有容器 docker stop $(docker ps -a -q) 删除所有容器: docker rm $(docker ps -a -q) docker查看容器IP地址:docker inspect 容器名称或 id ```