项目展示

登录及角色控制

首页展示

业务模块展示

智慧校园系统简介

项目简介

智慧校园管理系统:主要是以年级、班级为单位,进行老师和学生信息记录和统计功能。项目采用前后端分离架构思想,前端采用HTML+CSS+VUE来实现页面效果展示,后端采用SpringBoot+MybatisPlus框架实现数据存储等服务。存储层使用高性能的MySQL,服务器使用SpringBoot内置的Tomcat9.x,项目构建工具使用Maven来管理jar包和项目构建。

项目模块

技术栈

VUE
是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。 前后端分离是目前一种非常流行的开发模式,它使项目的分工更加明确:后端:负责处理、存储数据。前端:负责显示数据。前端和后端开发人员通过接口进行数据的交换。

Spring
 Spring就像是整个项目中装配bean的大工厂,在配置文件中可以指定使用特定的参数去调用实体类的构造方法来实例化对象,也可以称之为项目中的粘合剂。
 Spring的核心思想是IoC(控制反转),即不再需要程序员去显式地 new 一个对象,而是让Spring框架帮你来完成这一切。

SpringMVC
 SpringMVC在项目中拦截用户请求,它的核心Servlet,即DispatcherServlet承担中介或是前台这样的职责,将用户请求通过HandlerMapping去匹配Controller,Controller就是具体对应请求所执行的操作。SpringMVC相当于SSH框架中struts。

mybatis-plus
 mybatis是对jdbc的封装,它让数据库底层操作变的透明。mybatis的操作都是围绕一个sqlSessionFactory实例展开的。mybatis通过配置文件关联到各实体类的Mapper文件,Mapper文件中配置了每个类对数据库所需进行的sql语句映射。在每次与数据库交互时,通过sqlSessionFactory拿到一个sqlSession,再执行sql命令。MyBatis-plus就是在MyBatis的基础上,为Mapper接口Service层提供一些比较全面的CURD的业务逻辑功能,使程序员可以减少在Mapper和Service层的代码编写。

MVC项目架构

页面发送请求给控制器,控制器调用业务层处理逻辑,逻辑层向持久层发送请求,持久层与数据库交互,后将结果返回给业务层,业务层将处理逻辑发送给控制器,控制器再调用视图展现数据。

软件环境

安装数据库

  • 优点
  1. 开放源代码:MySQL最强大的优势之一在于它是一个开放源代码的数据库管理系统。开源的特点是给予了用户根据自己需要修改DBMS的自由。MySQL采用了General Public License,这意味着授予用户阅读、修改和优化源代码的权利,这样即使是免费版的MySQL的功能也足够强大,这也是为什么MySQL越来越受欢迎的主要原因。
  2. 跨平台:MySQL可在不同的操作系统下运行,简单地说,MySQL可以支持Windows系统、UNIX系统、Linux系统等多种操作系统平台。这意味着在一个操作系统中实现的应用程序可很方便移植到其他操作系统下。
  3. 轻量级:MySQL的核心程序完全采用多线程编程,这些线程都是轻量级的进程,它在灵活地为用户提供服务的同时,又不会占用过多的系统资源。因此MySQL能够更快速、高效的处理数据。
  4. 成本低:MySQL分为社区版和企业版,社区版是完全免费的,而企业版是收费的。即使在开发中需要用到一些付费的附加功能,价格相对于昂贵的Oracle、DB2等也是有很大优势的。其实免费的社区版也支持多种数据类型和正规的SQL查询语言,能够对数据进行各种查询、增加、删除、修改等操作,所以一般情况下社区版就可以满足开发需求了,而对数据库可靠性要求比较高的企业可以选择企业版。

安装数据库客户端工具

Navicat是一套快速、可靠并价格相当便宜的数据库管理工具,专为简化数据库的管理及降低系统管理成本而设。它的设计符合数据库管理员、开发人员及中小企业的需要。Navicat 是以直觉化的图形用户界面而建的,让你可以以安全并且简单的方式创建、组织、访问并共用信息。Navicat Premium 是一套数据库开发工具,让你从单一应用程序中同时连接 MySQL、MariaDB、MongoDB、SQL Server、Oracle、PostgreSQL 和 SQLite 数据库。它与 Amazon RDS、Amazon Aurora、Amazon Redshift、Microsoft Azure、Oracle Cloud、MongoDB Atlas、阿里云、腾讯云和华为云等云数据库兼容。你可以快速轻松地创建、管理和维护数据库。

安装JDK

安装IDEA

安装Maven

Maven是Apache软件基金会组织维护的一款专门为Java项目提供构建和依赖管理支持的工具。

Maven本地仓库

​ Maven的核心程序并不包含具体功能,仅负责宏观调度。具体功能由插件来完成。Maven核心程序会到本地仓库中查找插件。如果本地仓库中没有就会从远程中央仓库下载。此时如果不能上网则无法执行Maven的具体功能。为了解决这个问题,我们可以将Maven的本地仓库指向一个在联网情况下下载好的目录。Maven默认的本地仓库:.m2\repository目录(表示当前用户的家目录)。

优化Maven的Runner参数

优化配置:-DarchetypeCatalog=internal 每次创建项目时,IDEA要使用插件进行创建,这些插件当创建新项目时,它每次都会去中央仓库下载,这样使得创建比较慢。应该在创建时让它找本地仓库中插件进行创建项目。(-D代表属性,后面是key=value的形式配置参数)

安装Tomcat

目前使用SpringBoot内置Tomcat即可。

智慧校园系统功能开发

项目搭建

SpringBoot脚手架创建Maven项目

创建新项目,选择Spring Initializr

填写 group 和 artiface,选择JAVA version

添加组件和选择SpringBoot版本,暂时使用默认即可,后面我们自己添加项目依赖和修改SpringBoot版本

创建完毕后,检查项目的Maven配置,安装Lombok插件,启动注解处理,然后重启idea

  1. Lombok插件
  1. 开启注解处理
  1. 检查maven配置

导入相关依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<!-- 继承方式使用SpringBoot -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.5.RELEASE</version>
<relativePath/>
</parent>

<groupId>com.exercise</groupId>
<artifactId>Zhxy</artifactId>
<version>0.0.1-SNAPSHOT</version>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--单元测试启动器-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- thymeleaf支持-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.0</version>
</dependency>
<!-- 简化POJO实体类开发 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
<!--swagger-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger ui-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--swagger2 增强版接口文档-->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>2.0.4</version>
</dependency>
<!--开发者工具-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.33</version>
</dependency>
<!-- JWT生成Token-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
</dependencies>

<build>
<plugins>
<!--spring boot maven插件 , 可以将项目运行依赖的jar包打到我们的项目中-->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

</project>

项目结构

  • java目录下

    • config:项目的配置类
    • controller:控制层
    • mapper:持久层接口
    • pojo:实体类
    • service:服务层
    • util:工具类包
    • ZhxyApplication:启动类
  • resources目录下

    • mapper:持久层映射文件
    • public/upload:文件上传目录
    • static:静态资源目录
    • application.yml:SpringBoot核心配置文件

application.yml配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
server:
port: 9001
spring:
#解决SpringBoot2.6.0与swagger冲突问题【原因是在springboot2.6.0中将SpringMVC 默认路径匹配策略从AntPathMatcher 更改为PathPatternParser,导致出错,解决办法是切换回原先的AntPathMatcher】
mvc:
pathmatch:
matching-strategy: ant_path_matcher
#配置数据源
datasource:
#配置数据源类型
type: com.zaxxer.hikari.HikariDataSource
#配置数据库连接属性
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/sgg_zhxy_db?characterEncoding=utf-8&serverTimezone=GMT%2B8&userSSL=false
username: root
password: root
#url: jdbc:mysql://r2czkq1vewxat78mnyg60oisurj5h4dp.mysql.qingcloud.link:3306/ssg_zhxy_db?characterEncoding=utf-8&serverTimezone=GMT%2B8&userSSL=false
#username: shangguigu
#password: shangguigu@QY123
#mybatis-plus内置连接池
hikari:
connection-test-query: SELECT 1
connection-timeout: 60000
idle-timeout: 500000
max-lifetime: 540000
maximum-pool-size: 12
minimum-idle: 10
pool-name: GuliHikariPool
thymeleaf:
#模板的模式,支持 HTML, XML TEXT JAVASCRIPT
mode: HTML5
#编码 可不用配置
encoding: UTF-8
#开发配置为false,避免修改模板还要重启服务器
cache: false
#配置模板路径,默认是templates,可以不用配置
prefix: classpath:/static/
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
servlet:
#设置文件上传上限
multipart:
max-file-size: 10MB
max-request-size: 100MB
mybatis-plus:
configuration:
#添加日志支持
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
mapper-locations: classpath*:/mapper/**/*.xml

分页插件的配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package com.exercise.zhxy.config;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.exercise.zhxy.mapper")
public class MyConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
// paginationInterceptor.setLimit(你的最大单页限制数量,默认 500 条,小于 0 如 -1 不受限制);
return paginationInterceptor;
}
}

Swagger2的配置类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.exercise.zhxy.config;

import com.google.common.base.Predicates;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.util.ArrayList;
import java.util.List;

/**
* Swagger2配置信息
*/
@Configuration
@EnableSwagger2
public class Swagger2Config {

@Bean
public Docket webApiConfig(){
//添加head参数start
List<Parameter> pars = new ArrayList<>();
ParameterBuilder tokenPar = new ParameterBuilder();
tokenPar.name("userId")
.description("用户ID")
.defaultValue("1")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build();
pars.add(tokenPar.build());

ParameterBuilder tmpPar = new ParameterBuilder();
tmpPar.name("userTempId")
.description("临时用户ID")
.defaultValue("1")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build();
pars.add(tmpPar.build());
//添加head参数end
return new Docket(DocumentationType.SWAGGER_2)
.groupName("webApi")
.apiInfo(webApiInfo())
.select()
//可以测试请求头中:输入token
.apis(RequestHandlerSelectors.withClassAnnotation(ApiOperation.class))
//过滤掉admin路径下的所有页面
//.paths(Predicates.and(PathSelectors.regex("/sms/.*")))
//过滤掉所有error或error.*页面
//.paths(Predicates.not(PathSelectors.regex("/error.*")))
.build()
.globalOperationParameters(pars);
}

private ApiInfo webApiInfo(){
return new ApiInfoBuilder()
.title("网站-API文档")
.description("本文档描述了网站微服务接口定义")
.version("1.0")
.contact(new Contact("Zhxy", "https://liuwqtech.github.io/", "1096463510@qq.com"))
.build();
}

private ApiInfo adminApiInfo(){
return new ApiInfoBuilder()
.title("后台管理系统-API文档")
.description("本文档描述了后台管理系统微服务接口定义")
.version("1.0")
.contact(new Contact("Zhxy", "https://liuwqtech.github.io/", "1096463510@qq.com"))
.build();
}
}

util下的工具类

验证码图片工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package com.exercise.zhxy.util;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.Random;

/**
* @project: ssm_sms
* @description: 绘制验证码图片
*/
public class CreateVerifiCodeImage {

private static int WIDTH = 90;
private static int HEIGHT = 35;
private static int FONT_SIZE = 20; //字符大小
private static char[] verifiCode; //验证码
private static BufferedImage verifiCodeImage; //验证码图片

/**
* @description: 获取验证码图片
* @param: no
* @return: java.awt.image.BufferedImage
*/
public static BufferedImage getVerifiCodeImage() {
verifiCodeImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_BGR);// create a image
Graphics graphics = verifiCodeImage.getGraphics();

verifiCode = generateCheckCode();
drawBackground(graphics);
drawRands(graphics, verifiCode);

graphics.dispose();

return verifiCodeImage;
}

/**
* @description: 获取验证码
* @param: no
* @return: char[]
*/
public static char[] getVerifiCode() {
return verifiCode;
}

/**
* @description: 随机生成验证码
* @param: no
* @return: char[]
*/
private static char[] generateCheckCode() {
String chars = "0123456789abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char[] rands = new char[4];
for (int i = 0; i < 4; i++) {
int rand = (int) (Math.random() * (10 + 26 * 2));
rands[i] = chars.charAt(rand);
}
return rands;
}

/**
* @description: 绘制验证码
* @param: g
* @param: rands
* @return: void
*/
private static void drawRands(Graphics g, char[] rands) {
g.setFont(new Font("Console", Font.BOLD, FONT_SIZE));

for (int i = 0; i < rands.length; i++) {
g.setColor(getRandomColor());
g.drawString("" + rands[i], i * FONT_SIZE + 10, 25);
}
}

/**
* @description: 绘制验证码图片背景
* @param: g
* @return: void
*/
private static void drawBackground(Graphics g) {

g.setColor(Color.white);
g.fillRect(0, 0, WIDTH, HEIGHT);

// 绘制验证码干扰点
for (int i = 0; i < 200; i++) {
int x = (int) (Math.random() * WIDTH);
int y = (int) (Math.random() * HEIGHT);
g.setColor(getRandomColor());
g.drawOval(x, y, 1, 1);
}
}

/**
* @description: 获取随机颜色
* @param: no
* @return: java.awt.Color
*/
private static Color getRandomColor() {
Random ran = new Random();
return new Color(ran.nextInt(220), ran.nextInt(220), ran.nextInt(220));
}
}

token口令生成工具 JwtHelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package com.exercise.zhxy.util;

import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;

import java.util.Date;

public class JwtHelper {
private static long tokenExpiration = 24*60*60*1000;
private static String tokenSignKey = "123456";

//生成token字符串
public static String createToken(Long userId, Integer userType) {
String token = Jwts.builder()
.setSubject("YYGH-USER")
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.claim("userId", userId)
// .claim("userName", userName)
.claim("userType", userType)
.signWith(SignatureAlgorithm.HS512, tokenSignKey)
.compressWith(CompressionCodecs.GZIP)
.compact();
return token;
}

//从token字符串获取userid
public static Long getUserId(String token) {
if(StringUtils.isEmpty(token)) return null;
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
Integer userId = (Integer)claims.get("userId");
return userId.longValue();
}

//从token字符串获取userType
public static Integer getUserType(String token) {
if(StringUtils.isEmpty(token)) return null;
Jws<Claims> claimsJws
= Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
return (Integer)(claims.get("userType"));
}

//从token字符串获取userName
public static String getUserName(String token) {
if(StringUtils.isEmpty(token)) return "";
Jws<Claims> claimsJws
= Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
return (String)claims.get("userName");
}

//判断token是否有效
public static boolean isExpiration(String token){
try {
boolean isExpire = Jwts.parser()
.setSigningKey(tokenSignKey)
.parseClaimsJws(token)
.getBody()
.getExpiration().before(new Date());
//没有过期,有效,返回false
return isExpire;
}catch(Exception e) {
//过期出现异常,返回true
return true;
}
}

/**
* 刷新Token
* @param token
* @return
*/
public String refreshToken(String token) {
String refreshedToken;
try {
final Claims claims = Jwts.parser()
.setSigningKey(tokenSignKey)
.parseClaimsJws(token)
.getBody();
refreshedToken = JwtHelper.createToken(getUserId(token), getUserType(token));
} catch (Exception e) {
refreshedToken = null;
}
return refreshedToken;
}

public static void main(String[] args) {
// String token = JwtHelper.createToken(1L, "lucy");
// System.out.println(token);
// System.out.println(JwtHelper.getUserId(token));
// System.out.println(JwtHelper.getUserName(token));
}
}

解析 request 请求中的 token 口令的工具 AuthContextHolder

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.exercise.zhxy.util;

import javax.servlet.http.HttpServletRequest;

public class AuthContextHolder {

//从请求头token获取userid
public static Long getUserIdToken(HttpServletRequest request) {
//从请求头token
String token = request.getHeader("token");
//调用工具类
Long userId = JwtHelper.getUserId(token);
return userId;
}

//从请求头token获取name
public static String getUserName(HttpServletRequest request) {
//从header获取token
String token = request.getHeader("token");
//jwt从token获取username
String userName = JwtHelper.getUserName(token);
return userName;
}
}

MD5加密工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package com.exercise.zhxy.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public final class MD5 {

public static String encrypt(String strSrc) {
try {
char hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8',
'9', 'a', 'b', 'c', 'd', 'e', 'f' };
byte[] bytes = strSrc.getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(bytes);
bytes = md.digest();
int j = bytes.length;
char[] chars = new char[j * 2];
int k = 0;
for (int i = 0; i < bytes.length; i++) {
byte b = bytes[i];
chars[k++] = hexChars[b >>> 4 & 0xf];
chars[k++] = hexChars[b & 0xf];
}
return new String(chars);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
throw new RuntimeException("MD5加密出错!!+" + e);
}
}
}

JSON响应结果格式封装类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
package com.exercise.zhxy.util;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

/**
* 全局统一返回结果类
*
*/
@Data
@ApiModel(value = "全局统一返回结果")
public class Result<T> {

@ApiModelProperty(value = "返回码")
private Integer code;

@ApiModelProperty(value = "返回消息")
private String message;

@ApiModelProperty(value = "返回数据")
private T data;

public Result(){}

// 返回数据
protected static <T> Result<T> build(T data) {
Result<T> result = new Result<T>();
if (data != null)
result.setData(data);
return result;
}

public static <T> Result<T> build(T body, ResultCodeEnum resultCodeEnum) {
Result<T> result = build(body);
result.setCode(resultCodeEnum.getCode());
result.setMessage(resultCodeEnum.getMessage());
return result;
}

public static<T> Result<T> ok(){
return Result.ok(null);
}

/**
* 操作成功
* @param data
* @param <T>
* @return
*/
public static<T> Result<T> ok(T data){
Result<T> result = build(data);
return build(data, ResultCodeEnum.SUCCESS);
}

public static<T> Result<T> fail(){
return Result.fail(null);
}

/**
* 操作失败
* @param data
* @param <T>
* @return
*/
public static<T> Result<T> fail(T data){
Result<T> result = build(data);
return build(data, ResultCodeEnum.FAIL);
}

public Result<T> message(String msg){
this.setMessage(msg);
return this;
}

public Result<T> code(Integer code){
this.setCode(code);
return this;
}

public boolean isOk() {
if(this.getCode().intValue() == ResultCodeEnum.SUCCESS.getCode().intValue()) {
return true;
}
return false;
}
}

响应结果类型码枚举

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.exercise.zhxy.util;

import lombok.Getter;

/**
* 统一返回结果状态信息类
*/
@Getter
public enum ResultCodeEnum {

SUCCESS(200,"成功"),
FAIL(201, "失败"),
SERVICE_ERROR(2012, "服务异常"),
ILLEGAL_REQUEST( 204, "非法请求"),
PAY_RUN(205, "支付中"),
ARGUMENT_VALID_ERROR(206, "参数校验错误"),

LOGIN_ERROR(207, "用户名或密码错误"),
LOGIN_AUTH(208, "未登陆"),
PERMISSION(209, "没有权限"),
SECKILL_NO_START(210, "秒杀还没开始"),
SECKILL_RUN(211, "正在排队中"),
SECKILL_NO_PAY_ORDER(212, "您有未支付的订单"),
SECKILL_FINISH(213, "已售罄"),
SECKILL_END(214, "秒杀已结束"),
SECKILL_SUCCESS(215, "抢单成功"),
SECKILL_FAIL(216, "抢单失败"),
SECKILL_ILLEGAL(217, "请求不合法"),
SECKILL_ORDER_SUCCESS(218, "下单成功"),
COUPON_GET(220, "优惠券已经领取"),
COUPON_LIMIT_GET(221, "优惠券已发放完毕"),
//2022-02-22
LOGIN_CODE(222,"长时间未操作,会话已失效,请刷新页面后重试!"),
CODE_ERROR(223,"验证码错误!"),
TOKEN_ERROR(224,"Token无效!");

private Integer code;

private String message;

private ResultCodeEnum(Integer code, String message) {
this.code = code;
this.message = message;
}
}

文件上传工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
package com.exercise.zhxy.util;

import org.apache.commons.io.filefilter.SuffixFileFilter;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
* @project: zhxy
* @description: 上传文件的工具类
*/
public class UploadFile {

//存储文件上传失败的错误信息
private static Map<String, Object> error_result = new HashMap<>();
//存储头像的上传结果信息
private static Map<String, Object> upload_result = new HashMap<>();

/**
* @description: 效验所上传图片的大小及格式等信息...
* @param: photo
* @param: path
* @return: java.util.Map<java.lang.String, java.lang.Object>
*/
private static Map<String, Object> uploadPhoto(MultipartFile photo, String path) {
//限制头像大小(20M)
int MAX_SIZE = 20971520;
//获取图片的原始名称
String orginalName = photo.getOriginalFilename();
//如果保存文件的路径不存在,则创建该目录
File filePath = new File(path);
if (!filePath.exists()) {
filePath.mkdirs();
}
//限制上传文件的大小
if (photo.getSize() > MAX_SIZE) {
error_result.put("success", false);
error_result.put("msg", "上传的图片大小不能超过20M哟!");
return error_result;
}
// 限制上传的文件类型
String[] suffixs = new String[]{".png", ".PNG", ".jpg", ".JPG", ".jpeg", ".JPEG", ".gif", ".GIF", ".bmp", ".BMP"};
SuffixFileFilter suffixFileFilter = new SuffixFileFilter(suffixs);
if (!suffixFileFilter.accept(new File(path + orginalName))) {
error_result.put("success", false);
error_result.put("msg", "禁止上传此类型文件! 请上传图片哟!");
return error_result;
}
return null;
}

/**
* @description: (提取公共代码 : 提高代码的可重用性)获取头像的上传结果信息
* @param: photo
* @param: dirPaht
* @param: portraitPath
* @return: java.util.Map<java.lang.String, java.lang.Object>
*/
public static Map<String, Object> getUploadResult(MultipartFile photo, String dirPaht, String portraitPath) {

if (!photo.isEmpty() && photo.getSize() > 0) {
//获取图片的原始名称
String orginalName = photo.getOriginalFilename();
//上传图片,error_result:存储头像上传失败的错误信息
Map<String, Object> error_result = UploadFile.uploadPhoto(photo, dirPaht);
if (error_result != null) {
return error_result;
}
//使用UUID重命名图片名称(uuid__原始图片名称)
String newPhotoName = UUID.randomUUID() + "__" + orginalName;
//将上传的文件保存到目标目录下
try {
photo.transferTo(new File(dirPaht + newPhotoName));
upload_result.put("success", true);
upload_result.put("portrait_path", portraitPath + newPhotoName);//将存储头像的项目路径返回给页面
} catch (IOException e) {
e.printStackTrace();
upload_result.put("success", false);
upload_result.put("msg", "上传文件失败! 服务器端发生异常!");
return upload_result;
}
} else {
upload_result.put("success", false);
upload_result.put("msg", "头像上传失败! 未找到指定图片!");
}
return upload_result;
}
}

各层基础代码

pojo

  • Admin
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.exercise.zhxy.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_admin")
public class Admin {
@TableId(value = "id",type = IdType.AUTO)
private Integer id;
private String name;
private Character gender;
private String password;
private String email;
private String telephone;
private String address;
private String portraitPath; //头像的图片路径
}
  • Clazz
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.exercise.zhxy.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_clazz")
public class Clazz {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String name;
private Integer number;
private String introduction;
private String headmaster;
private String email;
private String telephone;
private String gradeName;
}
  • Grade
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
package com.exercise.zhxy.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_grade")
public class Grade {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String name;
private String manager;
private String email;
private String telephone;
private String introduction;
}
  • Student
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
package com.exercise.zhxy.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_student")
public class Student {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String sno;
private String name;
private Character gender;
private String password;
private String email;
private String telephone;
private String address;
private String introduction;
private String portraitPath;
private String clazzName;
}
  • Teacher
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.exercise.zhxy.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("tb_teacher")
public class Teacher {
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String tno;
private String name;
private Character gender;
private String password;
private String email;
private String telephone;
private String address;
private String portraitPath;
private String clazzName;
}
  • LoginParam
1
2
3
4
5
6
7
8
9
10
11
12
package com.exercise.zhxy.pojo;

import lombok.Data;

@Data
public class LoginParam {
private String username;
private String password;
private String verifiCode;
private Integer userType;

}

mapper

  • AdminMapper
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.exercise.zhxy.pojo.Admin;
import org.springframework.stereotype.Repository;

@Repository
public interface AdminMapper extends BaseMapper<Admin> {
}
  • ClazzMapper
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.exercise.zhxy.pojo.Clazz;
import org.springframework.stereotype.Repository;

@Repository
public interface ClazzMapper extends BaseMapper<Clazz> {
}
  • GradeMapper
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.exercise.zhxy.pojo.Grade;
import org.springframework.stereotype.Repository;

@Repository
public interface GradeMapper extends BaseMapper<Grade> {
}
  • StudentMapper
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.exercise.zhxy.pojo.Student;
import org.springframework.stereotype.Repository;

@Repository
public interface StudentMapper extends BaseMapper<Student> {
}
  • TeacherMapper
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.exercise.zhxy.pojo.Teacher;
import org.springframework.stereotype.Repository;

@Repository
public interface TeacherMapper extends BaseMapper<Teacher> {
}

service

  • Admin
1
2
3
4
5
6
7
package com.exercise.zhxy.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.exercise.zhxy.pojo.Admin;

public interface AdminService extends IService<Admin> {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.exercise.zhxy.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exercise.zhxy.mapper.AdminMapper;
import com.exercise.zhxy.pojo.Admin;
import com.exercise.zhxy.service.AdminService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("adminServiceImpl")
@Transactional
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {
}
  • Clazz
1
2
3
4
5
6
7
package com.exercise.zhxy.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.exercise.zhxy.pojo.Clazz;

public interface ClazzService extends IService<Clazz> {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.exercise.zhxy.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exercise.zhxy.mapper.ClazzMapper;
import com.exercise.zhxy.pojo.Clazz;
import com.exercise.zhxy.service.ClazzService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("clazzServiceImpl")
@Transactional
public class ClazzServiceImpl extends ServiceImpl<ClazzMapper, Clazz> implements ClazzService {
}
  • Grade
1
2
3
4
5
6
7
package com.exercise.zhxy.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.exercise.zhxy.pojo.Grade;

public interface GradeService extends IService<Grade> {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.exercise.zhxy.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exercise.zhxy.mapper.GradeMapper;
import com.exercise.zhxy.pojo.Grade;
import com.exercise.zhxy.service.GradeService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("gradeServiceImpl")
@Transactional
public class GradeServiceImpl extends ServiceImpl<GradeMapper, Grade> implements GradeService {
}
  • Student
1
2
3
4
5
6
7
package com.exercise.zhxy.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.exercise.zhxy.pojo.Student;

public interface StudentService extends IService<Student> {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.exercise.zhxy.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exercise.zhxy.mapper.StudentMapper;
import com.exercise.zhxy.pojo.Student;
import com.exercise.zhxy.service.StudentService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("studentServiceImpl")
@Transactional
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {
}
  • Teacher
1
2
3
4
5
6
7
package com.exercise.zhxy.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.exercise.zhxy.pojo.Teacher;

public interface TeacherService extends IService<Teacher> {
}
1
2
3
4
5
6
7
8
9
10
11
12
13
package com.exercise.zhxy.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.exercise.zhxy.mapper.TeacherMapper;
import com.exercise.zhxy.pojo.Teacher;
import com.exercise.zhxy.service.TeacherService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service("teacherServiceImpl")
@Transactional
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {
}

controller

1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sms/adminController")
public class AdminController {
}
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sms/clazzController")
public class ClazzController {
}
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sms/gradeController")
public class GradeController {
}
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sms/studentController")
public class StudentController {
}
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sms/teacherController")
public class TeacherController {
}
1
2
3
4
5
6
7
8
9
package com.exercise.zhxy.controller;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/sms/system")
public class SystemController {
}

登录功能后台

验证码功能

获取验证码图片及向session中存储验证码功能实现

SystemController层代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.exercise.zhxy.controller;

import com.exercise.zhxy.util.CreateVerifiCodeImage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;

@Api(tags = "系统控制器")
@RestController
@RequestMapping("/sms/system")
public class SystemController {

@ApiOperation("获取验证码图片")
@GetMapping("/getVerifiCodeImage")
public void getVerifiCodeImage(HttpServletRequest request, HttpServletResponse response){
//获取图片
BufferedImage verifiCodeImage = CreateVerifiCodeImage.getVerifiCodeImage();
//获取图片上的验证码
String verifiCode = new String(CreateVerifiCodeImage.getVerifiCode());
//将验证码文本放入session域,为下一次验证做准备
HttpSession session = request.getSession();
session.setAttribute("verifiCode",verifiCode);
//将验证码图片相应给浏览器
try {
//将验证码图片通过输出流做出响应
ImageIO.write(verifiCodeImage,"JPEG",response.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
}

swagger2接口文档查阅

登录校验功能

SystemController层代码实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
package com.exercise.zhxy.controller;

import com.exercise.zhxy.pojo.Admin;
import com.exercise.zhxy.pojo.LoginParam;
import com.exercise.zhxy.pojo.Student;
import com.exercise.zhxy.pojo.Teacher;
import com.exercise.zhxy.service.AdminService;
import com.exercise.zhxy.service.StudentService;
import com.exercise.zhxy.service.TeacherService;
import com.exercise.zhxy.util.CreateVerifiCodeImage;
import com.exercise.zhxy.util.JwtHelper;
import com.exercise.zhxy.util.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;

@Api(tags = "系统控制器")
@RestController
@RequestMapping("/sms/system")
public class SystemController {

@Autowired
private AdminService adminService;
@Autowired
private StudentService studentService;
@Autowired
private TeacherService teacherService;

@ApiOperation("登录请求验证")
@PostMapping ("/login")
public Result login(@RequestBody LoginParam loginParam,HttpServletRequest request){
//获取用户提交的验证码和session域中的验证码
HttpSession session = request.getSession();
String sessionVerifiCode = (String) session.getAttribute("verifiCode");
String loginVerifiCode = loginParam.getVerifiCode();
if ("".equals(sessionVerifiCode) || null == sessionVerifiCode){
//session过期,验证码超时
return Result.fail().message("验证码失效,请刷新后重试");
}
if (!sessionVerifiCode.equalsIgnoreCase(loginVerifiCode)){
//验证码有误
return Result.fail().message("验证码有误,请重新输入后重试");
}
//验证码使用完毕,移除当前请求域中的验证码
session.removeAttribute("verifiCode");

//准备一个Map用户存放响应的数据
Map<String,Object> map = new LinkedHashMap<>();
//分用户类型进行校验
switch (loginParam.getUserType()){
case 1:
try {
Admin admin = adminService.login(loginParam);
if (null != admin){
//将用户的类型和用户的id转换成一个密文,以token反馈给客户端
String token = JwtHelper.createToken(admin.getId().longValue(), 1);
map.put("token",token);
}
else {
throw new RuntimeException("用户名或密码有误");
}
return Result.ok(map);
} catch (RuntimeException e) {
e.printStackTrace();
return Result.fail().message(e.getMessage());
}
case 2:
try {
Student student = studentService.login(loginParam);
if (null != student){
//将用户的类型和用户的id转换成一个密文,以token反馈给客户端
String token = JwtHelper.createToken(student.getId().longValue(), 2);
map.put("token",token);
}
else {
throw new RuntimeException("用户名或密码有误");
}
return Result.ok(map);
} catch (RuntimeException e) {
e.printStackTrace();
return Result.fail().message(e.getMessage());
}
case 3:
try {
Teacher teacher = teacherService.login(loginParam);
if (null != teacher){
//将用户的类型和用户的id转换成一个密文,以token反馈给客户端
String token = JwtHelper.createToken(teacher.getId().longValue(), 3);
map.put("token",token);
}
else {
throw new RuntimeException("用户名或密码有误");
}
return Result.ok(map);
} catch (RuntimeException e) {
e.printStackTrace();
return Result.fail().message(e.getMessage());
}
}
return Result.fail().message("查无此用户");
}
}

AdminService中的login方法

1
2
3
4
5
6
7
8
public interface AdminService extends IService<Admin> {
/**
* 登陆
* @param loginParam
* @return
*/
Admin login(LoginParam loginParam);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service("adminServiceImpl")
@Transactional
public class AdminServiceImpl extends ServiceImpl<AdminMapper, Admin> implements AdminService {

@Autowired
private AdminMapper adminMapper;

/**
* 管理员登陆
* @param loginParam
* @return
*/
@Override
public Admin login(LoginParam loginParam) {
QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name",loginParam.getUsername())
.eq("password", MD5.encrypt(loginParam.getPassword()));
Admin admin = adminMapper.selectOne(queryWrapper);
return admin;
}
}

StudentService中的login方法

1
2
3
4
5
6
7
8
public interface StudentService extends IService<Student> {
/**
* 登陆
* @param loginParam
* @return
*/
Student login(LoginParam loginParam);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service("studentServiceImpl")
@Transactional
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

@Autowired
private StudentMapper studentMapper;

/**
* 学生登陆
* @param loginParam
* @return
*/
@Override
public Student login(LoginParam loginParam) {
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name",loginParam.getUsername())
.eq("password", MD5.encrypt(loginParam.getPassword()));
Student student = studentMapper.selectOne(queryWrapper);
return student;
}
}

TeacherService中的login方法

1
2
3
4
5
6
7
8
public interface TeacherService extends IService<Teacher> {
/**
* 登陆
* @param loginParam
* @return
*/
Teacher login(LoginParam loginParam);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
@Service("teacherServiceImpl")
@Transactional
public class TeacherServiceImpl extends ServiceImpl<TeacherMapper, Teacher> implements TeacherService {

@Autowired
private TeacherMapper teacherMapper;

/**
* 教师登陆
* @param loginParam
* @return
*/
@Override
public Teacher login(LoginParam loginParam) {
QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name",loginParam.getUsername())
.eq("password", MD5.encrypt(loginParam.getPassword()));
Teacher teacher = teacherMapper.selectOne(queryWrapper);
return teacher;
}
}

跳转至首页功能

当验证通过后,前端会产生第二个请求,用以获取用户的类型,然后根据用户的类型来展现不同的页面,所以后端要有一个根据token解析用户类型并做出结果响应的控制层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    @GetMapping("/getInfo")
public Result getUserInfoByToken(@RequestHeader("token") String token){
//获取用户中请求的token
//检查token是否过期 20H
boolean expiration = JwtHelper.isExpiration(token);
if (expiration){
return Result.build(null, ResultCodeEnum.TOKEN_ERROR);
}
//解析token,获取用户id和用户类型
Long userId = JwtHelper.getUserId(token);
Integer userType = JwtHelper.getUserType(token);
//准备一个Map集合用于存响应的数据
Map<String,Object> userMap = new HashMap<>();

switch (userType){
case 1:
Admin admin = adminService.getAdminById(userId);
userMap.put("userType",1);
userMap.put("user",admin);
break;
case 2:
Student student = studentService.getAdminById(userId);
userMap.put("userType",2);
userMap.put("user",student);
break;
case 3:
Teacher teacher = teacherService.getAdminById(userId);
userMap.put("userType",3);
userMap.put("user",teacher);
break;
}
return Result.ok(userMap);
}
}

年级管理功能

查询年级信息【分页带条件】

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Api(tags = "年级控制器")
@RestController
@RequestMapping("/sms/gradeController")
public class GradeController {

@Autowired
private GradeService gradeService;

@ApiOperation("查询年级信息,分页带条件")
@GetMapping("/getGrades/{pageNo}/{pageSize}")
public Result getGrades(@ApiParam("分页查询页码数") @PathVariable("pageNo") Integer pageNo, @ApiParam("分页查询页大小") @PathVariable("pageSize") Integer pageSize, @ApiParam("分页查询模糊匹配班级名") String gradeName){
//设置分页信息
Page<Grade> page = new Page<>(pageNo,pageSize);
//调用服务层方法,传入分页信息和查询的条件
IPage<Grade> pageRs = gradeService.getGradeByOpr(page,gradeName);
//封装Result对象并返回
return Result.ok(pageRs);
}
}

Service层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@Service("gradeServiceImpl")
@Transactional
public class GradeServiceImpl extends ServiceImpl<GradeMapper, Grade> implements GradeService {

@Autowired
private GradeMapper gradeMapper;

@Override
public IPage<Grade> getGradeByOpr(Page<Grade> page, String gradeName) {
//设置查询条件
QueryWrapper<Grade> queryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(gradeName)){
queryWrapper.like("name",gradeName);
}
//设置排序规则
queryWrapper.orderByAsc("id");
//返回分页查询数据
return gradeMapper.selectPage(page,queryWrapper);
}
}

添加/修改年级

Controller层代码

1
2
3
4
5
6
7
@ApiOperation("添加或者修改年级信息")
@PostMapping("/saveOrUpdateGrade")
public Result saveOrUpdateGrade(@ApiParam("JSON的grade对象转换后台数据模型") @RequestBody Grade grade){
//调用服务层方法,实现添加或者修改年级信息
gradeService.saveOrUpdate(grade);
return Result.ok();
}

service层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
// MyBatisPlus源码可见
public boolean saveOrUpdate(T entity) {
if (null == entity) {
return false;
} else {
TableInfo tableInfo = TableInfoHelper.getTableInfo(this.entityClass);
Assert.notNull(tableInfo, "error: can not execute. because can not find cache of TableInfo for entity!", new Object[0]);
String keyProperty = tableInfo.getKeyProperty();
Assert.notEmpty(keyProperty, "error: can not execute. because can not find column for id from entity!", new Object[0]);
Object idVal = ReflectionKit.getFieldValue(entity, tableInfo.getKeyProperty());
return !StringUtils.checkValNull(idVal) && !Objects.isNull(this.getById((Serializable)idVal)) ? this.updateById(entity) : this.save(entity);
}
}

删除/批量删除年级

Controller层代码

1
2
3
4
5
6
7
@ApiOperation("删除一个或者多个年级信息")
@DeleteMapping("/deleteGrade")
public Result deleteGradeById(@ApiParam("JSON的年级id集合,映射为后台List<Integer>") @RequestBody List<Integer> ids){
//调用服务层方法,实现删除年级信息
gradeService.removeByIds(ids);
return Result.ok();
}

班级管理功能

回显搜索中的年级选项

Controller层代码

1
2
3
4
5
6
@ApiOperation("获取所有年级信息")
@GetMapping("/getGrades")
public Result getGrades(){
List<Grade> gradeList = gradeService.getBaseMapper().selectList(null);
return Result.ok(gradeList);
}

查询班级信息【分页带条件】

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Api(tags = "班级控制器")
@RestController
@RequestMapping("/sms/clazzController")
public class ClazzController {

@Autowired
private ClazzService clazzService;

@ApiOperation("查询班级信息,分页带条件")
@GetMapping("/getClazzsByOpr/{pageNo}/{pageSize}")
public Result getClazzsByOpr(
@ApiParam("分页查询页码数") @PathVariable("pageNo") Integer pageNo,
@ApiParam("分页查询页大小") @PathVariable("pageSize") Integer pageSize,
@ApiParam("查询条件") Clazz clazz){
//设置分页信息
Page<Clazz> page = new Page<>(pageNo,pageSize);
//调用服务层方法,传入分页信息和查询的条件
IPage<Clazz> pageRs = clazzService.getClazzsByOpr(page,clazz);
//封装Result对象并返回
return Result.ok(pageRs);
}
}

service层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Service("clazzServiceImpl")
@Transactional
public class ClazzServiceImpl extends ServiceImpl<ClazzMapper, Clazz> implements ClazzService {

@Autowired
private ClazzMapper clazzMapper;

/**
* 查询班级信息,带分页条件
* @param page
* @param clazz
* @return
*/
@Override
public IPage<Clazz> getClazzsByOpr(Page<Clazz> page, Clazz clazz) {
QueryWrapper<Clazz> queryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(clazz.getGradeName())){
queryWrapper.like("grade_name",clazz.getGradeName());
}
if (!StringUtils.isEmpty(clazz.getName())){
queryWrapper.like("name",clazz.getName());
}
queryWrapper.orderByAsc("id");
return clazzMapper.selectPage(page,queryWrapper);
}
}

添加/修改班级

Controller层代码

1
2
3
4
5
6
7
@ApiOperation("添加或者修改班级信息")
@PostMapping("/saveOrUpdateClazz")
public Result saveOrUpdateClazz(@ApiParam("JSON的clazz对象") @RequestBody Clazz clazz){
//调用服务层方法,实现添加或者修改年级信息
clazzService.saveOrUpdate(clazz);
return Result.ok();
}

删除/批量删除班级

Controller层代码

1
2
3
4
5
6
7
@ApiOperation("删除一个或者多个班级信息")
@DeleteMapping("/deleteClazz")
public Result deleteClazzByIds(@ApiParam("JSON的班级id集合,映射为后台List<Integer>") @RequestBody List<Integer> ids){
//调用服务层方法,实现删除年级信息
clazzService.removeByIds(ids);
return Result.ok();
}

学生管理功能

回显搜索条件中的班级选项

Controller层代码

1
2
3
4
5
6
@ApiOperation("获取所有班级信息")
@GetMapping("/getClazzs")
public Result getGrades(){
List<Clazz> getClazzs = clazzService.getBaseMapper().selectList(null);
return Result.ok(getClazzs);
}

查询学生信息【分页带条件】

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Api(tags = "学生控制器")
@RestController
@RequestMapping("/sms/studentController")
public class StudentController {

@Autowired
private StudentService studentService;

@ApiOperation("查询学生信息,分页带条件")
@GetMapping("/getStudentByOpr/{pageNo}/{pageSize}")
public Result getStudentsByOpr(
@ApiParam("页码数") @PathVariable("pageNo") Integer pageNo,
@ApiParam("页大小") @PathVariable("pageSize") Integer pageSize,
@ApiParam("查询条件") Student student){
Page<Student> page = new Page<>(pageNo,pageSize);
IPage<Student> studentPage = studentService.getStudentByOpr(page,student);
return Result.ok(studentPage);
}
}

service层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
@Service("studentServiceImpl")
@Transactional
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

@Autowired
private StudentMapper studentMapper;

/**
* 查询学生信息,带分页条件
* @param page
* @param student
* @return
*/
@Override
public IPage<Student> getStudentByOpr(Page<Student> page, Student student) {
QueryWrapper<Student> queryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(student.getClazzName())){
queryWrapper.eq("clazz_name",student.getClazzName());
}
if (!StringUtils.isEmpty(student.getName())){
queryWrapper.eq("name",student.getName());
}
queryWrapper.orderByAsc("id");
return studentMapper.selectPage(page,queryWrapper);
}
}

异步图片上传处理头像

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@ApiOperation("图片上传统一入口")
@PostMapping("/headerImgUpload")
public Result imgUpload(@ApiParam("图像文件") @RequestPart("multipartFile") MultipartFile multipartFile){
//使用UUID随机生成文件名
String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();
//生成新的文件名字
String newFileName = uuid.concat(Objects.requireNonNull(multipartFile.getOriginalFilename()));
//生成文件的保存路径(实际生产环境这里会使用真正的文件存储服务器)
String portraitPath ="/Users/liuwq/Documents/IDEA/Zhxy/target/classes/public/upload/".concat(newFileName);
//保存文件
try {
multipartFile.transferTo(new File(portraitPath));
} catch (IOException e) {
e.printStackTrace();
}
//响应图片路径
String path = "upload/".concat(newFileName);
return Result.ok(path);
}

添加/修改学生

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
@ApiOperation("增加学生信息")
@PostMapping("/addOrUpdateStudent")
public Result addOrUpdateStudent(@RequestBody Student student){
//对学生密码进行加密
if (!StringUtils.isEmpty(student.getPassword())){
student.setPassword(MD5.encrypt(student.getPassword()));
}
//保存学生信息进入数据库
studentService.saveOrUpdate(student);
return Result.ok();
}

删除/批量删除学生

Controller层代码

1
2
3
4
5
6
@ApiOperation("删除一个或者多个学生信息")
@DeleteMapping("/delStudentById")
public Result deleteStudentById(@ApiParam("多个学生id的JSON") @RequestBody List<Integer> ids){
studentService.removeByIds(ids);
return Result.ok();
}

教师管理功能

查询教师信息【分页带条件】

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Api(tags = "教师控制器")
@RestController
@RequestMapping("/sms/teacherController")
public class TeacherController {

@Autowired
private TeacherService teacherService;

@ApiOperation("获取教师信息,分页带条件")
@GetMapping("/getTeachers/{pageNo}/{pageSize}")
public Result getTeachers(
@ApiParam("页码数") @PathVariable("pageNo") Integer pageNo,
@ApiParam("页大小") @PathVariable("pageSize") Integer pageSize,
@ApiParam("查询条件") Teacher teacher){
Page<Teacher> page = new Page<>(pageNo,pageSize);
IPage<Teacher> teacherPage = teacherService.getTeachersByOpr(page,teacher);
return Result.ok(teacherPage);
}
}

service层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 查询教师信息,分页带条件
* @param page
* @param teacher
* @return
*/
@Override
public IPage<Teacher> getTeachersByOpr(Page<Teacher> page, Teacher teacher) {
QueryWrapper<Teacher> queryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(teacher.getClazzName())){
queryWrapper.eq("clazz_name",teacher.getClazzName());
}
if (!StringUtils.isEmpty(teacher.getName())){
queryWrapper.like("name",teacher.getName());
}
queryWrapper.orderByAsc("id");
return teacherMapper.selectPage(page,queryWrapper);
}

添加/修改教师

Controller层代码

1
2
3
4
5
6
7
8
9
@ApiOperation("添加和修改教师信息")
@PostMapping("/saveOrUpdateTeacher")
public Result saveOrUpdateTeacher(@ApiParam("要保存或者修改的JSON格式的Teacher") @RequestBody Teacher teacher){
if (!StringUtils.isEmpty(teacher.getPassword())){
teacher.setPassword(MD5.encrypt(teacher.getPassword()));
}
teacherService.saveOrUpdate(teacher);
return Result.ok();
}

删除/批量删除教师

Controller层代码

1
2
3
4
5
6
@ApiOperation("删除一个或多个教师信息")
@DeleteMapping("/deleteTeacher")
public Result deleteTeacherByIds(@ApiParam("多个教师id的JSON") @RequestBody List<Integer> ids){
teacherService.removeByIds(ids);
return Result.ok();
}

管理员管理功能

查询管理员信息【分页带条件】

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@Api(tags = "系统管理员控制器")
@RestController
@RequestMapping("/sms/adminController")
public class AdminController {

@Autowired
private AdminService adminService;

@ApiOperation("分页获取所有的管理员信息【带条件】")
@GetMapping("/getAllAdmin/{pageNo}/{pageSize}")
public Result getAllAdmin(
@ApiParam("页码数") @PathVariable Integer pageNo,
@ApiParam("页大小") @PathVariable Integer pageSize,
@ApiParam("查询条件") String adminName){
Page<Admin> pageParam = new Page<>(pageNo,pageSize);
IPage<Admin> page = adminService.getAdmins(pageParam, adminName);
return Result.ok(page);
}
}

service层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
* 查询管理员信息,分页带条件
* @param pageParam
* @param adminName
* @return
*/
@Override
public IPage<Admin> getAdmins(Page<Admin> pageParam, String adminName) {
QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
if (!StringUtils.isEmpty(adminName)){
queryWrapper.like("name",adminName);
}
queryWrapper.orderByAsc("id");
return adminMapper.selectPage(pageParam,queryWrapper);
}

添加/修改管理员

Controller层代码

1
2
3
4
5
6
7
8
9
@ApiOperation("添加或修改管理员信息")
@PostMapping("/saveOrUpdateAdmin")
public Result saveOrUpdateAdmin(@RequestBody Admin admin){
if (!StringUtils.isEmpty(admin.getPassword())) {
admin.setPassword(MD5.encrypt(admin.getPassword()));
}
adminService.saveOrUpdate(admin);
return Result.ok();
}

删除/批量删除管理员

Controller层代码

1
2
3
4
5
6
@ApiOperation("删除一个或多个管理员信息")
@DeleteMapping("/deleteAdmin")
public Result deleteAdminByIds(@RequestBody List<Integer> ids){
adminService.removeByIds(ids);
return Result.ok();
}

管理员修改自己的密码

Controller层代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@ApiOperation("更新用户密码")
@PostMapping("/updatePwd/{oldPwd}/{newPwd}")
public Result updatePasswprd(
@ApiParam("token口令") @RequestHeader("token") String token,
@ApiParam("旧密码") @PathVariable("oldPwd") String oldPwd,
@ApiParam("新密码") @PathVariable("newPwd") String newPwd){
boolean expiration = JwtHelper.isExpiration(token);
if (expiration){
//token过期
return Result.fail().message("token失效,请重新登陆后修改密码");
}
//通过token获取当前登录的用户id
Long userId = JwtHelper.getUserId(token);
//通过token获取当前登录的用户类型
Integer userType = JwtHelper.getUserType(token);

// 将明文密码转换为暗文
oldPwd = MD5.encrypt(oldPwd);
newPwd = MD5.encrypt(newPwd);

switch (userType){
case 1:
QueryWrapper<Admin> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id",userId.intValue())
.eq("password",oldPwd);
Admin admin = adminService.getOne(queryWrapper);
if (admin != null){
//修改密码
admin.setPassword(newPwd);
adminService.saveOrUpdate(admin);
}else {
return Result.fail().message("原密码有误!");
}
break;
case 2:
QueryWrapper<Student> queryWrapper2 = new QueryWrapper<>();
queryWrapper2.eq("id",userId.intValue())
.eq("password",oldPwd);
Student student = studentService.getOne(queryWrapper2);
if (student != null){
//修改密码
student.setPassword(newPwd);
studentService.saveOrUpdate(student);
}else {
return Result.fail().message("原密码有误!");
}
break;
case 3:
QueryWrapper<Teacher> queryWrapper3 = new QueryWrapper<>();
queryWrapper3.eq("id",userId.intValue())
.eq("password",oldPwd);
Teacher teacher = teacherService.getOne(queryWrapper3);
if (teacher != null){
//修改密码
teacher.setPassword(newPwd);
teacherService.saveOrUpdate(teacher);
}else {
return Result.fail().message("原密码有误!");
}
break;
}
return Result.ok();
}