【两万字图文详解】 运动会管理系统-前后端分离-项目开发:【后端】SpringBoot, SpringMVC, MyBatis【前端】Vue.js,ElementUI

发布时间:2023-05-20 19:00

\"【两万字图文详解】

项目名称:运动会管理系统
 技术栈:
     后端:SpringBoot,SpringMVC,MyBatis,tkmapper,Maven聚合工程等
     前端:Vue.js,Element-ui等
     前后端接口文档:Swagger,Swagger-ui

文章目录

  • 【_运动会管理系统_】
    • 0.功能展示
      • 0.1 用户注册
      • 0.2 用户登录
      • 0.3 学生用户报名
      • 0.4 运动员报名查询
      • 0.5 运动员个人单项赛查询
      • 0.6 团体赛成绩查询
      • 0.7 裁判员报名
      • 0.8 赛事公布
      • 0.9 赛事查询
      • 0.10 成绩公布
      • 0.11 用户个人信息的显示
      • 0.12 用户个人信息的更改
      • 0.13 赛事项目管理
      • 0.14 成绩管理
      • 7.15 分数统计
    • 1 问题描述
    • 2 需求分析
      • 2.1 图示需求
      • 2.2 功能分析
    • 3 软件设计
      • 3.1 项目架构
      • 3.2 技术栈
        • 3.2.1 前端
        • 3.2.2 后端
        • 3.2.3 前后端接口
      • 3.3 数据库设计
        • 3.3.1 概念结构
          • 3.3.1.1 实体-属性图
          • 3.3.1.2 实体-联系图(总E-R图)
      • 3.4 前端设计
        • 0、网站logo设计
        • 1、`注册页面`
        • 2、`登录页面`
        • 3、`主页页面`
        • 4、`报名页面`
        • 5、`查询页面`
        • 6、`赛事公布页面`
        • 7、`成绩公布页面`
        • 8、`用户个人信息页`
        • 9、`登录页面`
        • 10、`管理页面`
      • 3.5 后端设计
    • 4 数据库测试数据
      • 4.1 测试数据的构建思路
      • 4.2 录入测试数据
    • 5 后端搭建
      • 5.1 搭建聚合工程并添加依赖
        • 5.1.1 构建父工程
        • 5.1.2 构建common子工程
          • 1、操作方式
          • 2、添加依赖
        • 5.1.3 构建bean子工程
          • 1、操作方式
          • 2、添加依赖
        • 5.1.4 构建mapper子工程
          • 1、操作方式
          • 2、添加依赖
        • 5.1.5 构建service子工程
          • 1、操作方式
          • 2、添加依赖
        • 5.1.6 构建api子工程
          • 1、操作方式
          • 2、添加依赖
        • 5.1.7 更新父工程的pom.xml
        • 5.1.8 初步启动项目
      • 5.2 子工程的初步构建
        • 5.2.1 common层的初步构建
        • 5.2.2 bean层的初步构建
        • 5.2.1 mapper层的初步构建
        • 5.2.3 service层的初步构建
        • 5.2.4 api层的初步构建
    • 6 前端搭建
      • 6.1 用户-前端
      • 6.2 管理员-前端
    • 7 前后端分离用户认证JWT
      • 7.1 关于Sessin与JWT
      • 7.2 后端-token的签发
      • 7.3 前端-保存token
      • 7.4 前端-携带token
      • 7.5 后端-拦截器
    • 8 开发:注册页及其功能
      • 8.1 前端-UI实现
      • 9.2 业务逻辑-分析
      • 9.3 后端-接口实现
      • 9.4 前端-回显测试
    • 项目后续

运动会管理系统

0.功能展示

0.1 用户注册

用户注册界面

\"【两万字图文详解】

身份选择,不同身份对应各自的个性化注册方案
\"【两万字图文详解】

学生用户注册
\"【两万字图文详解】

通过用户数据校验后,则注册成功

裁判员用户注册,则需输入其工号进行认证
\"【两万字图文详解】

其他用户注册,因数据库表中没有记录其信息的数据表,因此需将个人信息收录完整

注册成功
\"【两万字图文详解】

输入校验
\"【两万字图文详解】

0.2 用户登录

\"【两万字图文详解】

邮箱或密码错误
\"【两万字图文详解】

未登录的情况下,无法访问除注册页和登录页外的其他页面
\"【两万字图文详解】

邮箱和密码正确
\"【两万字图文详解】

0.3 学生用户报名

选择已开放的项目
\"【两万字图文详解】

时间已过,则不可再报(此处本人设计不合理,因为此处的逻辑是只要比赛开始前,都可以报)

\"【两万字图文详解】

若系统检测到当前用户为男生,则他不可以报名女子项目,反之也是如此
\"【两万字图文详解】

若已报名此项目,则不可重复报名
\"【两万字图文详解】

当没有其他拒绝因素时,报名成功
\"【两万字图文详解】

0.4 运动员报名查询

运动员报名成功后,可进行报名查询
\"【两万字图文详解】

输入身份证号即可查询自己的报名情况
\"【两万字图文详解】

查询结果显示如下
\"【两万字图文详解】

0.5 运动员个人单项赛查询

由于此用户刚注册并报名,其比赛还未进行,也没有结果,因此我们登录另一个所报比赛已结束的用户进行测试
\"【两万字图文详解】

输入运动员编号即可进行查询
\"【两万字图文详解】

此运动员的查询结果有多项,都在右侧弹窗中显示
\"【两万字图文详解】

0.6 团体赛成绩查询

输入团体编号
\"【两万字图文详解】

查询得到团体成员信息和比赛结果信息
\"【两万字图文详解】

0.7 裁判员报名

登录裁判员用户
\"【两万字图文详解】

男子跳远项目暂时无裁判
\"【两万字图文详解】

裁判员报名成功
\"【两万字图文详解】

赛事安排表中对应的此项目的元组安排成功
\"【两万字图文详解】

0.8 赛事公布

在赛事公布页可看到此届运动会的相关赛事安排
\"【两万字图文详解】
\"【两万字图文详解】

0.9 赛事查询

赛事可按三种方式进行查询,分别是根据编号查询,根据项目名查询(模糊查询),根据赛事类别查询
\"【两万字图文详解】

首先测试根据赛事编号查询
\"【两万字图文详解】

查询成功
\"【两万字图文详解】

接下来测试根据赛事名查询
\"【两万字图文详解】

成功查询到有关“赛跑”关键字的项目
\"【两万字图文详解】

最后是根据类别查询
\"【两万字图文详解】

0.10 成绩公布

成绩公布页面

\"【两万字图文详解】
\"【两万字图文详解】

0.11 用户个人信息的显示

在用户个人页
\"【两万字图文详解】

0.12 用户个人信息的更改

此处,不再一一演示,具体可更改的条目如下
\"【两万字图文详解】

0.13 赛事项目管理

包括对赛事项目的编辑,添加和删除(或者说取消)操作
\"【两万字图文详解】

首先测试对赛事的编辑更改
\"【两万字图文详解】

提交后,更改成功
\"【两万字图文详解】

接下来测试删除

点击后,项目被删除
\"【两万字图文详解】

\"【两万字图文详解】

同时,我们也可以在赛事项目恢复页恢复项目
\"【两万字图文详解】

之后测试添加项目
\"【两万字图文详解】

添加成功
\"【两万字图文详解】

0.14 成绩管理

此功能类似上个功能的效果,当时时间有限,此处并未开发
\"【两万字图文详解】

7.15 分数统计

对各班得分情况进行统计
\"【两万字图文详解】

1 问题描述

题目要求:登录比赛项目,提出报名的限制要求(包括运动员所报项目,班级运动员人数),各个班级运动员报名后,登录报名情况,检查是否符合要求,为符合要求的运动员自动编号,并为比赛安排裁判员。比赛时先进行检录(运动员报到),检查实际与报名是否相符,为符合要求的运动员安排比赛,比赛后,录入成绩,并计算单项名次,取前若干名,登记领取奖品,为班级累计总分,全部比赛结束后,公布全体总分,并取前若干名。在比赛过程中和比赛结束后,可查询报名和比赛情况,并可进行打印。

2 需求分析

2.1 图示需求

\"【两万字图文详解】

2.2 功能分析

用户端—主要功能页面

  • 注册页面:学生提供基本信息——>注册——>成为用户——>跳转:登录页面
  • 登录页面:输入账号、密码——>登录成功——>跳转:首页页面
  • 主页页面
    • 导航(赛事公布,申请报名,信息查询(报名查询,成绩查询(单项成绩查询,团体成绩查询),班级总分查询,学院总分查询),成绩公布,投诉与检举)
    • 展示运动会资讯(如进展与最终比赛结果)
  • 报名页面:输入基本信息——>符合要求——>报名成功——>提示:可去报名查询页面再次核对
  • 查询页面:报名查询,成绩查询,单项名次查询,团体总分查询,班级累计总分查询
  • 赛事公布页面:类别、具体项目信息,赛事查询
  • 成绩公布页面:单项名次公布,团体总分公布,班级累计总分公布
  • 用户个人信息页面:用户基本信息

管理员端—主要功能页面

  • 登录页面:输入账号、密码——>登录成功——>跳转:管理页面
  • 管理页面(单页应用)
    • 报名管理:运动员报名信息的增删改查,也用于检录
    • 奖品管理:奖品信息的增删改查,也用于颁奖(一键自动根据成绩颁奖)
    • 成绩管理:个人、团体成绩的增删改查,并记录日志
    • 比赛管理:比赛项目信息的增删改查
    • 资讯管理:首页资讯信息的增删改查
    • 日志记录:用户登录情况,管理员登录情况,用户操作情况,管理页操作情况

3 软件设计

3.1 项目架构

  • 前后端分离
  • 前端采用数据-视图分离开发
  • 后端采用Maven聚合工程开发

3.2 技术栈

3.2.1 前端

  • HTML + CSS + JavaScript
  • Vue.js
  • Element-UI

3.2.2 后端

  • SpringBoot
  • Maven聚合工程
  • Mybatis
  • Tkmapper

3.2.3 前后端接口

  • Swagger + Swagger-ui

3.3 数据库设计

3.3.1 概念结构

3.3.1.1 实体-属性图

1、用户

\"【两万字图文详解】

2、学生

\"【两万字图文详解】

3、班级

\"【两万字图文详解】

4、学院
\"【两万字图文详解】

5、运动员

\"【两万字图文详解】

6、团体

\"在这里插入图片描述\"

7、裁判员
\"【两万字图文详解】

8、项目

\"【两万字图文详解】

9、安排
\"【两万字图文详解】

10、安排信息单元

\"【两万字图文详解】

11、比赛记录

\"【两万字图文详解】

12、奖品

\"【两万字图文详解】

13、获奖情况

\"【两万字图文详解】

14、管理员
\"【两万字图文详解】

15、登录日志

\"【两万字图文详解】

3.3.1.2 实体-联系图(总E-R图)

\"【两万字图文详解】

3.4 前端设计

用户端—主要功能页面

0、网站logo设计

\"【两万字图文详解】

1、注册页面

  • 注册页面:学生提供基本信息——>注册——>成为用户——>跳转:登录页面

\"【两万字图文详解】

2、登录页面

  • 登录页面:输入账号、密码——>登录成功——>跳转:首页页面

\"【两万字图文详解】

3、主页页面

  • 主页页面

    • 导航(赛事公布,申请报名,信息查询(报名查询,成绩查询(单项成绩查询,团体成绩查询),班级总分查询,学院总分查询),成绩公布,投诉与检举)
    • 展示运动会资讯(如进展与最终比赛结果)

\"【两万字图文详解】

4、报名页面

  • 报名页面:输入基本信息——>符合要求——>报名成功——>提示:可去报名查询页面再次核对

\"【两万字图文详解】

5、查询页面

  • 查询页面:报名查询,成绩查询(单项成绩查询,团体成绩查询),班级总分查询,学院总分查询

\"【两万字图文详解】

6、赛事公布页面

  • 赛事公布页面:类别、具体项目信息,赛事查询

\"【两万字图文详解】

7、成绩公布页面

  • 成绩公布页面:单项成绩公布,团体成绩公布,班级成绩公布

\"【两万字图文详解】

8、用户个人信息页

  • 用户个人信息页:用户个人基本信息

\"【两万字图文详解】

管理员端—主要功能页面

9、登录页面

  • 登录页面:输入账号、密码——>登录成功——>跳转:管理页面

\"【两万字图文详解】

10、管理页面

  • 管理页面(单页应用)

    • 报名管理:运动员报名信息的增删改查,也用于检录
    • 奖品管理:奖品信息的增删改查,也用于颁奖
    • 成绩管理:个人、团体成绩的增删改查,并记录日志
    • 比赛管理:比赛项目信息的增删改查
    • 资讯管理:首页资讯信息的增删改查(可无)
    • 日志记录:用户登录情况,管理员登录情况,用户操作情况,管理页操作情况

\"【两万字图文详解】

\"【两万字图文详解】

3.5 后端设计

后端采用Maven聚合工程来搭建项目,从而并将项目模块化,模块之间建立相应的依赖关系

Maven聚合工程概念图

\"【两万字图文详解】

4 数据库测试数据

4.1 测试数据的构建思路

因本项目的数据库种所涉及的数据表就有15张,因此需要进行相关联的测试数据的导入。

关于测试数据的思路:

(1)首先录入一条管理员的记录,以便在项目进行过程种需要进行某种管理员功能测试时可以拿来即用

(2)再分别录入学院,班级,学院则为信息科学与工程学院和政法学院,班级为计数19H2和政法1901

(3)再录入学生表,学生则为7条测试记录数据,其中前6人参与之后比赛等其他关系表中关联数据的录入,最后1人留出,用于测试学生报名运动会的功能,因此,前6人的运动员标识需要设为1,而第7人的为0,同时应有两学院的学生中中应有各有一名女生,用于进行女子项目的报名,从而在测试报名功能中报名制定项目比赛的时候可以进行性别的测试

(4)之后也应在用户表中录入对应学生表中的前6人的信息

(5)录入裁判员表

(6)录入项目表,项目有男子100米赛跑,女子100米赛跑,男子2*200米接力赛(用于进行团体型比赛项目的测试)

(7)录入运动员表,参照学生表来写

(8)录入安排信息单元表,给男子100米赛跑,女子100米赛跑,男子2*200米接力赛安排指定时间、地点

(9)录入队伍表,可将计数19H2中两名男生用来录入到一个队伍中,例如,将周龙超与机器人2放入一个队伍

(10)录入安排表,计数19H2一男vs政法1901一 男,计数19H2一女vs政法1901一 女,计数19H2两男以团体名义安排,其中第5条记录的裁判员id为Null,因为,根据项目分析,裁判员也应该通过报名来参与到赛事安排表中,因此,此条记录用于测试裁判员的报名

(11)录入比赛记录表,计数19H2一男vs政法1901一 男 比赛成绩录入(机器人2,机器人4)

补充说明:

男子100米赛跑:机器人2 vs 机器人4 ----------结束

女子100米赛跑:机器人3 vs 机器人5 --------未开始

男子2x200米接力赛:(周龙超+机器人2)vs ? --------结束

男子跳远:机器人2

4.2 录入测试数据

4.2.1 admin表

(管理员表)
\"在这里插入图片描述\"

4.2.2 college表

(学院表)

\"【两万字图文详解】

4.2.3 class表

(班级表)
\"在这里插入图片描述\"

4.2.4 student表

(学生表)

\"【两万字图文详解】

4.2.5 user表

(用户表)
\"在这里插入图片描述\"

4.2.6 referee表

(裁判员表)

\"在这里插入图片描述\"

4.2.7 project表

(项目表)
\"【两万字图文详解】

4.2.8 athlete表

(运动员表)
\"【两万字图文详解】

4.2.9 arrange_info表

(安排信息单元表)

\"【两万字图文详解】

4.2.10 team表

(队伍表)
\"【两万字图文详解】

4.2.11 arrangement表

(安排表)

\"【两万字图文详解】

4.2.12 competition表

(比赛记录表)

\"【两万字图文详解】

5 后端搭建

5.1 搭建聚合工程并添加依赖

5.1.1 构建父工程

首先构建Maven父工程sports-metting-server

本项目采用Maven聚合工程的方式进行创建,首先创建总父Maven工程,并删除不必要文件

\"【两万字图文详解】

首先对父工程的pom.xml文件进行如下配置:

  • packing设置为 pom

  • 父工程继承继承spring-boot-starter-parent

(注:其实一开始也可以将父工程建成SpringBoot项目)

pom.xml进行上述操作后,内容如下:


<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.0modelVersion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.4.4version>
        <relativePath/> 
    parent>

    <groupId>com.zlcgroupId>
    <artifactId>sports-metting-serverartifactId>
    <version>2.0version>
    
    <packaging>pompackaging>

    <properties>
        <java.version>1.8java.version>
    properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

project>

5.1.2 构建common子工程

1、操作方式

选择sports-metting-server,右键—New—Module (Maven工程)


<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\">
    <parent>
        <artifactId>sports-metting-serverartifactId>
        <groupId>com.zlcgroupId>
        <version>2.0version>
    parent>
    <modelVersion>4.0.0modelVersion>

    <artifactId>commonartifactId>

project>
2、添加依赖
  • lombok:用于生成实体类的基本方法,如构造方法,Getter/Setter,toString等方法
  • springfox-swagger2:用于生成前后端接口文档,定义common子工程中ResultVO对象的Api说明信息
<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
dependency>
<dependency>
    <groupId>io.springfoxgroupId>
    <artifactId>springfox-swagger2artifactId>
    <version>2.9.2version>
dependency>

5.1.3 构建bean子工程

1、操作方式

选择sports-metting-server,右键—New—Module (Maven工程)

2、添加依赖
  • lombok:(同上)

  • springfox-swagger2:(同上)

  • mapper-spring-boot-starter:tkmapper的starter依赖,提供现成的单表查询方法,与数据库表逆向转为JavaBean并自动配置好Mapper文件的字段映射

<dependency>
    <groupId>tk.mybatisgroupId>
    <artifactId>mapper-spring-boot-starterartifactId>
    <version>2.1.5version>
dependency>

<dependency>
    <groupId>org.projectlombokgroupId>
    <artifactId>lombokartifactId>
dependency>

<dependency>
    <groupId>io.springfoxgroupId>
    <artifactId>springfox-swagger2artifactId>
    <version>2.9.2version>
dependency>

5.1.4 构建mapper子工程

1、操作方式

选择sports-metting-server,右键—New—Module (Maven工程)

2、添加依赖
  • 添加bean子工程依赖
  • mysql-connector-java:mysql的JDBC驱动包
  • spring-boot-starter:springboot starter依赖
  • mybatis-spring-boot-starter:mybatis starter依赖,用于springboot整合mybatis
  • druid-spring-boot-starter:德鲁伊 starter依赖,Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。

<dependency>
    <groupId>com.qfedugroupId>
    <artifactId>beanartifactId>
    <version>2.0.1version>
dependency>


<dependency>
    <groupId>mysqlgroupId>
    <artifactId>mysql-connector-javaartifactId>
    <version>5.1.47version>
dependency>


<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starterartifactId>
    <version>2.4.4version>
dependency>


<dependency>
    <groupId>org.mybatis.spring.bootgroupId>
    <artifactId>mybatis-spring-boot-starterartifactId>
    <version>2.1.4version>
dependency>

<dependency>
    <groupId>com.alibabagroupId>
    <artifactId>druid-spring-boot-starterartifactId>
    <version>1.1.22version>
dependency>

5.1.5 构建service子工程

1、操作方式

选择sports-metting-server,右键—New—Module (Maven工程)

在service子工程的pom.xml,依赖common子工程和mapper子工程

2、添加依赖
  • 添加common子工程依赖
  • 添加mapper子工程依赖
  • java-jwtjjwt:前后端分离项目中解决用户认证问题
<dependency>
    <groupId>com.zlcgroupId>
    <artifactId>commonartifactId>
    <version>2.0version>
dependency>

<dependency>
    <groupId>com.zlcgroupId>
    <artifactId>mapperartifactId>
    <version>2.0version>
dependency>

<dependency>
    <groupId>com.auth0groupId>
    <artifactId>java-jwtartifactId>
    <version>3.10.3version>
dependency>

<dependency>
    <groupId>io.jsonwebtokengroupId>
    <artifactId>jjwtartifactId>
    <version>0.9.1version>
dependency>

5.1.6 构建api子工程

1、操作方式

选择sports-metting-server,右键—New—Module (Maven工程)

在api子工程的pom.xml,依赖service子工程

2、添加依赖
  • 添加service子工程依赖
  • springfox-swagger-ui:前后端接口文档swagger的可视化页面
  • swagger-bootstrap-ui:swagger的可视化页面的增强版管理页面
  • spring-boot-starter-web:spring web的 starter依赖
  • spring-boot-starter-test:spring test的 starter依赖
  • junit:Java单元测试框架依赖
<dependency>
    <groupId>com.zlcgroupId>
    <artifactId>serviceartifactId>
    <version>2.0.1version>
dependency>
<dependency>
    <groupId>io.springfoxgroupId>
    <artifactId>springfox-swagger-uiartifactId>
    <version>2.9.2version>
dependency>
<dependency>
    <groupId>com.github.xiaoymingroupId>
    <artifactId>swagger-bootstrap-uiartifactId>
    <version>1.9.6version>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
    <groupId>org.springframework.bootgroupId>
    <artifactId>spring-boot-starter-testartifactId>
dependency>
<dependency>
    <groupId>junitgroupId>
    <artifactId>junitartifactId>
    <scope>testscope>
dependency>

5.1.7 更新父工程的pom.xml

注册各个子模块


<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.0modelVersion>

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.4.4version>
        <relativePath/> 
    parent>

    <groupId>com.zlcgroupId>
    <artifactId>sports-metting-serverartifactId>
    <version>2.0version>
    <modules>
        <module>commonmodule>
        <module>beanmodule>
        <module>mappermodule>
        <module>servicemodule>
        <module>apimodule>
    modules>
    <packaging>pompackaging>

    <properties>
        <java.version>1.8java.version>
    properties>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.bootgroupId>
                <artifactId>spring-boot-maven-pluginartifactId>
            plugin>
        plugins>
    build>

    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starterartifactId>
        dependency>

        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-testartifactId>
            <scope>testscope>
        dependency>
    dependencies>

project>

5.1.8 初步启动项目

1、首先配置mapper子工程中的数据库和mybatis的配置

application.yml

spring:
  datasource:
    druid:
      driver-class-name: com.mysql.cj.jdbc.Driver
      url: jdbc:mysql://localhost:3306/sports?characterEncoding=utf-8
      username: root
      password: 123456



mybatis:
  mapper-locations: classpath:mappers/*Mapper.xml
  type-aliases-package: com.zlc.sports.entity

2、在api子工程中创建SpringBoot启动类,同时指定MapperScan扫描的具体包

@SpringBootApplication
@MapperScan(\"com.zlc.sports.dao\")
public class ApiApplication {

    public static void main(String[] args) {
        SpringApplication.run(ApiApplication.class, args);
    }

}

3、启动ApiApplication

运行正常,则说明之前的配置并无较大问题,可进行下阶段的编码

5.2 子工程的初步构建

5.2.1 common层的初步构建

建立软件包

  • util包:工具类
  • vo包:用于响应前端的信息类(说明:携带状态码,响应标语,响应的具体内容),也将存放用于处理前端分页的类

\"【两万字图文详解】

在vo包中:

  • ResStatus:状态码封装类

    public class ResStatus {
        public static final int OK = 10000;
        public static final int NO = 10001;
    
        public static final int LOGIN_SUCCESS = 2000; //认证成功
        public static final int LOGIN_FAIL_NOT = 20001; //用户未登录
        public static final int LOGIN_FAIL_OVERDUE = 20002; //用户登录失效
    }
    
  • ResultVO:后端传给前端的信息单元类

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @ApiModel(value = \"响应的VO对象\", description = \"封装接口返回给前端的数据\")
    public class ResultVO {
        //传递给前端的状态码
        @ApiModelProperty(value = \"响应状态码\", dataType = \"int\")
        private int code;
    
        //响应给前端的信息
        @ApiModelProperty(value = \"响应提示信息\", dataType = \"string\")
        private String msg;
    
        //响应给前端的数据
        @ApiModelProperty(value = \"响应数据\", dataType = \"obj\")
        private Object data;
    }
    

5.2.2 bean层的初步构建

建立软件包

  • entity包:JavaBean类
  • vo包:由JavaBean衍生出的View Object类(说明:若响应前端的某个请求需要返回多表查询的结果,而某个实体又只有自己的属性,因此需要定义自定义化的View Object类)

\"【两万字图文详解】

5.2.1 mapper层的初步构建

建立软件包

  • dao包:数据库交互接口
  • general包:tkmapper的自定义公共接口类
  • generator目录:tkmapper的配置文件
  • mappers目录:mybatis的Mapper配置文件

\"【两万字图文详解】

利用tkmapper的逆向工程来初步构建Dao层,将数据库中的表映射为JavaBean并配置相关mybatis的Mapper映射配置的主要内容

使用逆向工程的方法,需进行如下步骤的配置:

  • (1)在mapper子工程中添加tkmapper依赖:已添加,因在bean子工程中已经引入tkmapper依赖—mapper-spring-boot-starter,而mapper子工程又引入了bean子工程依赖

  • (2)在mapper子工程的general包中创建一个继承Mapper和MySqlMapper的泛型类,这样就可以使之后在dao包中自动生成的Mapper类只需对接这一个接口即可

    public interface GeneralDAO<T> extends Mapper<T>, MySqlMapper<T> {
    }
    
  • (3)在mapper子工程的resources/generator目录下创建generatorConfig.xml
    \"【两万字图文详解】

  • (4)配置mapper子工程的pom.xml

    \"【两万字图文详解】

  • (5)执行逆向生成插件

\"在这里插入图片描述\"

执行完成后,即可在各个预先指定的包和目录中得到JavaBean实体类,Mapper类以及Mapper.xml配置,之后还需将entity包中的类移动到bean子工程下,并删除mapper子工程下的entity包即可

5.2.3 service层的初步构建

建立软件包

  • sports包:业务层接口
  • impl:业务层接口的实现类

\"【两万字图文详解】

首先建立好各个JavaBean的接口与实现类(也可以边写边建立,看个人习惯)

\"【两万字图文详解】

5.2.4 api层的初步构建

建立软件包

  • config包:配置类,如之后拦截器配置和前后端接口文档Swagger的配置类
  • controller包:控制器类,处理并响应前端发来的请求
  • interceptor包:用户身份认证的拦截器
  • 测试包:用于单元测试(暂时先建一个Dao层的测试包)

\"【两万字图文详解】

编写Swagger配置类

\"【两万字图文详解】

6 前端搭建

6.1 用户-前端

本项目欲将管理员的前端页面开发为多页浏览的方式,因此,只需建立一个空文件夹,并用IDEA打开,在其中新建前端文件,并创建必要目录,进行开发即可。

\"在这里插入图片描述\"
\"【两万字图文详解】

6.2 管理员-前端

本项目欲将管理员的前端页面开发为单页浏览的方式,因此可用Vue.js的脚手架进行前端的搭建(但也可以自己去写单页应用)。

7 前后端分离用户认证JWT

7.1 关于Sessin与JWT

由于在前后端分离项目开发中,前后端之间是通过异步交互完成数据访问的,请求是无状态的,因此不能基于session实现用户的认证。

关于session和jwt详细介绍的一篇优秀文章

基于Session的用户认证:

  1. 用户输入其登录信息
  2. 服务器验证信息是否正确,并创建一个session,然后将其存储在数据库中
  3. 服务器为用户生成一个sessionId,将具有sesssionId的Cookie将放置在用户浏览器中
  4. 在后续请求中,会根据数据库验证sessionID,如果有效,则接受请求
  5. 一旦用户注销应用程序,会话将在客户端和服务器端都被销毁

基于token(令牌)的用户认证:

  1. 用户输入其登录信息

  2. 服务器验证信息是否正确,并返回已签名的token

  3. token储在客户端,例如存在local storage或cookie中

  4. 之后的HTTP请求都将token添加到请求头里

  5. 服务器解码JWT,并且如果令牌有效,则接受请求

  6. 一旦用户注销,令牌将在客户端被销毁,不需要与服务器进行交互一个关键是,令牌是无状态的。后端服务器不需要保存令牌或当前session的记录。

7.2 后端-token的签发

在进行登录验证的时候,若登录成功,则进行token的签发
\"在这里插入图片描述\"

7.3 前端-保存token

前端将服务器签发的token保存到cookie中。

\"【两万字图文详解】

7.4 前端-携带token

当前端请求访问受限资源的时候,若想成功访问,则请求头中需要携带服务器端签发的token。

\"【两万字图文详解】

7.5 后端-拦截器

当前端请求访问受限资源的时候,则根据请求路径和拦截器配置类中的预先设置进行拦截,若请求头中携带了token,则需拦截器类进行校验,校验成功才可以放行,从而进行受限资源的访问。

拦截器配置类
\"【两万字图文详解】
拦截器类
\"【两万字图文详解】

8 开发:注册页及其功能

8.1 前端-UI实现

\"【两万字图文详解】

\"【两万字图文详解】

9.2 业务逻辑-分析

\"【两万字图文详解】

9.3 后端-接口实现

UserService

/**
 * 用户注册,可能是学生,裁判,或另外身份,分别处理
 *
 * @param info
 * @return
 */
public ResultVO addUserToRegister(Map<String, String> info);

UserServiceImpl

/**
 * 用户注册,可能是学生,裁判,或另外身份,分别处理
 *
 * @param info
 * @return
 */
@Override
public ResultVO addUserToRegister(Map<String, String> info) {
    String type = info.get(\"type\");
    //System.out.println(type);
    //若是学生注册
    if (type.equals(\"0\")) {
        //首先根据学号得到学生在学生表中的主键id,从而插入用户表中的type_id字段
        String studentNumber = info.get(\"studentNumber\");

        Example example = new Example(Student.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo(\"studentNumber\", studentNumber);
        List<Student> students = studentMapper.selectByExample(example);
        //System.out.println(\"students = \" + students);
        //如果学号正确
        if (students.size() > 0) {
            Student student = students.get(0);
            //则构建此学生用户,并插入用户表
            User user = new User();
            user.setType(\"0\");
            user.setTypeId(student.getStudentId());
            user.setUsername(info.get(\"username\"));
            user.setPassword(info.get(\"password\"));
            user.setEmail(info.get(\"email\"));
            user.setImg(\"default.png\");
            user.setCreateTime(new Date());
            user.setUpdateTime(new Date());

            int i = userMapper.insert(user);
            if (i > 0) {
                return new ResultVO(ResStatus.OK, \"success\", null);
            } else {
                return new ResultVO(ResStatus.NO, \"fail\", null);
            }
        }
    } else {
        // 如果不是学生
        //则构建此非学生用户,并插入用户表
        User user = new User();
        user.setType(info.get(\"type\"));
        user.setUsername(info.get(\"username\"));
        user.setPassword(info.get(\"password\"));
        user.setEmail(info.get(\"email\"));
        user.setRealname(info.get(\"realname\"));
        user.setGender(info.get(\"gender\"));
        user.setIdnumber(info.get(\"idnumber\"));
        user.setPhoneNumber(info.get(\"phoneNumber\"));
        user.setImg(\"default.png\");
        String birthday = info.get(\"birthday\");

        birthday = birthday.substring(0, 10);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(\"yyyy-MM-dd\");
        Date dateTime = null;
        try {
            dateTime = simpleDateFormat.parse(birthday);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        user.setBirthday(dateTime);

        user.setCreateTime(new Date());
        user.setUpdateTime(new Date());

        int i = userMapper.insert(user);
        if (i > 0) {
            return new ResultVO(ResStatus.OK, \"success\", null);
        } else {
            return new ResultVO(ResStatus.NO, \"fail\", null);
        }
    }
    return new ResultVO(ResStatus.NO, \"fail\", null);
}

UserController

@PostMapping(\"/register\")
@ApiOperation(\"用户注册\")
public ResultVO register(@RequestBody Map<String, String> info) {
    return userService.addUserToRegister(info);
}

9.4 前端-回显测试

register.html

<el-form ref=\"form\" :model=\"formInfo\" label-width=\"80px\">
    <el-form-item label=\"身份选择\">
        <el-select v-model=\"formInfo.identity\" placeholder=\"请首先声明您的身份\" @change=\"changeIdentity\">
            <el-option label=\"学生\" value=\"0\">el-option>
            <el-option label=\"教师\" value=\"1\">el-option>
            <el-option label=\"裁判员\" value=\"2\">el-option>
            <el-option label=\"校内其他工作人员\" value=\"3\">el-option>
            <el-option label=\"非本校人员\" value=\"4\">el-option>
        el-select>
    el-form-item>

    <el-form-item label=\"用户名\">
        <el-input v-model=\"formInfo.username\">el-input>
    el-form-item>

    <el-form-item label=\"密码\">
        <el-input v-model=\"formInfo.password\">el-input>
    el-form-item>

    <el-form-item label=\"确认密码\">
        <el-input v-model=\"formInfo.rePassword\">el-input>
    el-form-item>


    <el-form-item label=\"邮箱\">
        <el-input v-model=\"formInfo.email\">el-input>
    el-form-item>

    <template v-if=\"isStudent\">
        <el-form-item label=\"学号\">
            <el-input v-model=\"formInfo.studentNumber\">el-input>
        el-form-item>
    template>

    <template v-if=\"!isStudent\">
        
        <el-form-item label=\"真实姓名\">
            <el-input v-model=\"formInfo.realname\">el-input>
        el-form-item>

        <el-form-item label=\"性别\">
            <el-radio-group v-model=\"formInfo.gender\">
                <el-radio label=\"1\">el-radio>
                <el-radio label=\"0\">el-radio>
            el-radio-group>
        el-form-item>

        <el-form-item label=\"身份证号\">
            <el-input v-model=\"formInfo.idnumber\">el-input>
        el-form-item>

        <el-form-item label=\"出生日期\">
            <el-col :span=\"11\">
                <el-date-picker type=\"date\" placeholder=\"选择日期\" v-model=\"formInfo.birthday\"
                                style=\"width: 100%;\">el-date-picker>
            el-col>
        el-form-item>

        <el-form-item label=\"联系电话\">
            <el-input v-model=\"formInfo.phoneNumber\">el-input>
        el-form-item>
    template>


    <el-form-item>
        <el-button type=\"primary\" @click=\"onSubmit\" class=\"move-right-mid\">注册el-button>
        <el-button @click=\"reWrite\" class=\"move-right-large\">重置el-button>
    el-form-item>
el-form>

<script>
    var baseUrl = \"http://localhost:8080\";
    var vm = new Vue({
        el: \'#container\',
        data: {
            formInfo: {
                identity: \'\',
                username: \'\',
                password: \'\',
                rePassword: \'\',
                email: \'\',

                studentNumber: \'\',

                realname: \'\',
                gender: \'\',
                idnumber: \'\',
                birthday: \'\',
                phoneNumber: \'\'
            },

            isStudent: false
        },

        created: function () {

        },

        watch: {},

        methods: {
            onSubmit() {
                // console.log(\'submit!\');
                console.log(this.formInfo);

                //进行输入校验
                //校验密码


                // 发送 POST 请求
                axios({
                    method: \'post\',
                    url: baseUrl + \'/register\',
                    data: {
                        studentNumber: this.formInfo.studentNumber,
                        type: this.formInfo.identity,
                        username: this.formInfo.username,
                        password: this.formInfo.password,
                        email: this.formInfo.email,

                        realname: this.formInfo.realname,
                        gender: this.formInfo.gender,
                        idnumber: this.formInfo.idnumber,
                        birthday: this.formInfo.birthday,
                        phoneNumber: this.formInfo.phoneNumber
                    }
                }).then((res)=>{
                    var vo = res.data;
                    console.log(vo);
                    if (vo.code == 10000) {
                        // console.log(vo);
                        window.location.href = \"login.html\";
                    }
                });
            },
            reWrite() {
                this.formInfo.identity = \'\';
                this.formInfo.username = \'\';
                this.formInfo.password = \'\';
                this.formInfo.rePassword = \'\';
                this.formInfo.email = \'\';
                this.formInfo.studentNumber = \'\';
                this.formInfo.realname = \'\';
                this.formInfo.gender = \'\';
                this.formInfo.idnumber = \'\';
                this.formInfo.birthday = \'\';
                this.formInfo.phoneNumber = \'\';
                // console.log(this.form);
            },
            changeIdentity() {
                console.log(this.formInfo.identity);
                //如果是学生身份
                if (this.formInfo.identity == \'0\') {
                    // console.log(this.formInfo.identity);
                    this.isStudent = true;
                } else {
                    this.isStudent = false;
                }
            }
        }

    });
script>

项目后续

关于此项目剩余功能的开发教程、思路、代码文档,本人在开发的同时已整理成详细md格式文档

\"【两万字图文详解】
此项目附带文件如下
\"【两万字图文详解】
因此项目的开发以及文档的编写耗费了本人大量的精力和时间,因此决定将此项目的源码和剩余文档设为付费内容,有意向的小伙伴可以前往链接下载,感谢小伙伴们的支持。

附下载地址:
https://download.csdn.net/download/m0_46360532/19853247?spm=1001.2014.3001.5501

(可加 wx:zlc777687,wx 支付优惠 5 元)

ItVuer - 免责声明 - 关于我们 - 联系我们

本网站信息来源于互联网,如有侵权请联系:561261067@qq.com

桂ICP备16001015号