作业管理系统实现——springboot+jsp

作业管理系统

简介:
   技术:
      jsp + springboot + layui + mybatis + docker + restful api
   功能:
      老师:登录,注册,添加学生、作业(面向自己的学生),查看自己的学生、自己布置的作业以及学生作业的完成情况,删除学生、作业,更改作业信息,退出登录
      学生:登录,注册查看作业、提交作业(可重复提交),退出登录

   github地址: 项目传送门

一、数据库设计

数据库一共有五张表,设计均满足第三范式要求:

  1. student(sid)   
  2. teacher(tid)  
  3. homework(hid)   
  4. student_homework(sid, hid)
  5. teach(sid, tid)

以下是数据库关系模式图
在这里插入图片描述

二、用例设计

用例图

在这里插入图片描述

三、流程图设计

1. 学生流程

在这里插入图片描述

2. 教师流程

在这里插入图片描述

四、详细设计

1. 结构总览

在这里插入图片描述

项目总共两大模块: core 和 web
core:
  主要包含model和util,model存放的是实体类,util存放工具类,这里存放了一个SpringContextUtil,用来获取Context创建bean
web:
  java目录下主要包含一些源代码,config、controller、dao、service,分别存放配置类、路由映射、mybatis访问接口、服务.
  resources下包含springboot的配置文件,mybatis-generator的配置文件,mybatis的mapper文件
  web-app下包含jsp页面和web.xml

2. 登录模块

  1. 采用了前端cookie保持登录状态,当再次打开登录页面时,会进行登录状态的判断,若已登录且未退出,则会自动进行登录,登录成功与登出成功的时候则会改变cookie中的登录状态。
  2. 添加了拦截器设置,用来检验登录状态,未登录时不能访问只有登录后才能访问的页面,通过WebConfig配置学生和老师相关操作的拦截器。
  3. 记住密码功能,使用cookie记住最近一次登录成功的用户名+密码,不小心退出后可以直接登录。
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
//login.jsp进行登录判断,通过cookie获取登录状态和已登录的账号密码
<%
request.setCharacterEncoding("utf-8"); //防止中文乱码
Cookie[] cookies = request.getCookies();
boolean studentLogged = false;
boolean teacherLogged = false;
String username = "";
String password = "";
if(cookies != null){
for (Cookie c : cookies) {
if ("loginStatus".equals(c.getName())) {
String loginStatus = c.getValue();
if ("student_true".equals(loginStatus)) {
response.sendRedirect("/student/studentHome");
} else if ("teacher_true".equals(loginStatus)) {
response.sendRedirect("/teacher/teacherHome");
}
break;
}
}
for (Cookie c : cookies) {
if ("loginStatus".equals(c.getName())) {
String loginStatus = c.getValue();
if ("student_false".equals(loginStatus)) {
studentLogged = true;
} else if ("teacher_false".equals(loginStatus)) {
teacherLogged = true;
}
break;
}
}
if(teacherLogged || studentLogged){
//输入框显示账号密码
for(Cookie c : cookies){
if("username".equals(c.getName())){
username = URLDecoder.decode(c.getValue(), "utf-8");
}
if("password".equals(c.getName())){
password = URLDecoder.decode(c.getValue(), "utf-8");
}
}
}
}
%>
1
2
3
4
5
6
7
//login.jsp 显示密码
<% if(!username.equals("") && !password.equals("") && studentLogged){ %>
<script>
document.getElementById("s_username").value = <%=username%>;
document.getElementById("s_password").value = <%=password%>;
</script>
<%}%>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

//StudentInterceptor拦截示例
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Cookie[] cookies = request.getCookies();
String loginStatus = "";
for (Cookie c : cookies) {
if ("loginStatus".equals(c.getName())) {
loginStatus = c.getValue();
if ("student_true".equals(loginStatus)) {
return true;
}
break;
}
}
response.sendRedirect("/login");
return false;
}

3. service设计

  1. 抽象出StudentService和TeacherService两个接口,在impl包下进行实现,好处是有新的实现时上层不用做修改。
    1. 使用@Transactional注解TeacherServiceImpl中的addHomework, removeStudent, deleteHomework三个方法,因为方法当中的多个sql必须绑定执行才符合逻辑,也可以使用之前学到的AOP代理实现,就是稍微麻烦点。

4. Restful api设计

url method description
/ get 跳转至登录界面
/login get 跳转至登录界面
/logout get 退出登录
/studentLogin post 学生登录
/teacherLogin post 教师登录
/studentRegister get 跳转至学生注册界面
/studentRegister post 学生注册
/teacherRegister get 跳转至教师注册界面
/teacherRegister post 教师注册
/register-success get 注册成功界面
/studentHome get 学生主页(自己的作业列表)
/homework get 查看作业
/homework post 提交/更新作业
/new-homework get 跳转至添加作业界面
/new-homework post 添加作业
/homework post 修改作业
/homework get 跳转至修改作业界面
/homework delete 删除作业
/new-student get 跳转至给自己班级添加学生的界面
/new-student post 添加1个或多个学生到自己班级
/student delete 将学生移除班级
/teacherHome get 教师主页(该教师班级学生列表)
/teacherHomework get 作业列表(仅含该教师布置)
/studentHomework get 某一作业的所有学生的完成情况

5. 其他设计

  1. js表单验证,登录、注册、提交作业以及布置作业时的验证。
  2. 表单提交错误相关提示,密码错误、用户表不存在等提示信息。
  3. dao层与mapper是通过myabtis-generator插件生成的。
  4. 重复提交时会自动显示之前提交内容,教师修改作业也是一样的

这里举两个例子:
密码必须6-12位,不含空格
在这里插入图片描述
密码错误:
在这里插入图片描述

五、界面展示

1.登录注册

1.1学生登录(登陆成功会用cookie记住账户密码)

在这里插入图片描述

1.2 教师登录(这里使用cookie记住了账户密码)

在这里插入图片描述

1.3 学生注册

在这里插入图片描述

1.4 教师注册

在这里插入图片描述

1.3 注册成功:

在这里插入图片描述

2.学生部分

2.1 学生主页

在这里插入图片描述

2.2 提交作业(可重复提交,之前有提交内容时会自动显示)

在这里插入图片描述

3. 教师部分

3.1 主页(自己教的学生)

可以对自己教的学生进行添加和移除
在这里插入图片描述

3.2 从不属于自己学生的列表添加自己的学生

在这里插入图片描述

3.3 自己发布的作业列表,可以添加新作业、查看、删除某一作业

在这里插入图片描述

3.4 修改作业内容(自动显示之前的内容)

在这里插入图片描述

3.5 发布新的作业在这里插入图片描述
3.6 查看某一作业自己所有学生的完成情况在这里插入图片描述

六、Docker部署(多模块Maven项目)

1. docker 部署springboot镜像

1.1环境准备(以下操作在springboot的web模块进行)
1
2
3
4
5
6
7
8
9
//由于springboot对jsp不友好,需要将maven-plugin改为1.4.2.RELEASE版本
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.4.2.RELEASE</version>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
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
//一些docker打包的插件
<plugin>
<dependencies>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
<groupId>com.spotify</groupId>
<artifactId>dockerfile-maven-plugin</artifactId>
<version>1.4.13</version>
<executions>
<execution>
<id>default</id>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<repository>${docker.image.prefix}/${project.artifactId}</repository>
<tag>${project.version}</tag>
<buildArgs>
<JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
</buildArgs>
</configuration>
</plugin>
1.2 Dockerfile编写
1
2
3
4
5
6
7
8
9
10
11
12
FROM openjdk:8-jre

ENTRYPOINT ["java", "-jar", "/usr/share/myservice/app.jar"]

VOLUME /usr/share/myservice

RUN mkdir -p /usr/share/myservice

WORKDIR /usr/share/myservice

ARG JAR_FILE
ADD ${JAR_FILE} /usr/share/myservice/app.jar
1.3开始制作
1
2
3
4
5
6
7
8
//进入父模块,执行如下命令,打包父工程里面的依赖
mvn clean install package -Dmaven.test.skip

//进入入口模块(一般是web模块,这儿是springboot的web模块)执行如下命令,入口镜像打包和生成镜像
mvn package dockerfile:build -Dmaven.test.skip

//使用docker images查看生成镜像
docker images
1.4 运行测试
1
2
//本地运行测试
docker run --name service -p 8088:8083 springboot/web:1.0-SNAPSHOT
截图(Docker Desktop)

在这里插入图片描述

2. docker-compose 部署springboot+mysql

上面的是没有整合mysql的,依赖本地mysql,现在给springboot项目整合docker的mysql
2.1相关配置
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
//在根目录下新建docker-compose.yml,配置springboot和mysql的相关配置
version: '3.8'

services:

webapp:
build:
context: ./web
dockerfile: Dockerfile
restart: always
ports:
- 8088:8083
volumes:
- /vol/development
depends_on:
- mysql
links:
- mysql:mysql

mysql:
container_name: mysql-container
build:
context: ./mysql
dockerfile: Dockerfile
restart: always
ports:
- 33068:3306
environment:
MYSQL_DATABASE: class
MYSQL_ROOT_HOST: '%'
MYSQL_ROOT_PASSWORD: 123456
command: [
'mysqld',
'--innodb-buffer-pool-size=20M',
'--character-set-server=utf8',
'--collation-server=utf8_general_ci',
'--default-time-zone=+8:00',
'--lower-case-table-names=1',
'--default-authentication-plugin=mysql_native_password'
]
2.2 mysql目录下有两个文件:calss.sql和Dockerfile
1
2
3
4
//Dockerfile
FROM mysql:8.0.20
//将clas.sql添加到初始化执行的文件夹下,这样启动时就会自动执行
ADD ./class.sql /docker-entrypoint-initdb.d/class.sql
2.3 web目录下的 Dockerfile(和之前差不多)
1
2
3
4
5
6
7
8
9
10
//Dockerfile
FROM openjdk:8-jre

ENTRYPOINT ["java", "-jar", "/usr/share/myservice/app.jar"]

VOLUME /usr/share/myservice
RUN mkdir -p /usr/share/myservice
WORKDIR /usr/share/myservice
//这里在我的机器之前的JAR_FILE报错,换了这个
ADD /target/web.jar /usr/share/myservice/app.jar
2.4 运行docker-compose命令
1
2
//执行该命令,制作启动镜像
docker-compose up
然后就可以成功制作并启动了(DockerDesktop):

在这里插入图片描述

注:以上两种方式运行时都要将springboot中mysql配置中url中的ip换成自己电脑的ipv4地址。

七、总结

  1. 使用layui如果想通过ajax提交form一定要在ajax提交后写上:return false;否则表单会提交两遍!
  2. springboot对jsp的支持较差,要添加的东西比较多,我在我的pom.xml中注释了出来,遇到问题的童鞋也可以参考一下。
  3. mybatis-generator插件真的好用,使用也比较简单,感兴趣的小伙伴可以学一下!
  4. 关于mybatis,配置mapper和dao层时要求:
    在mapper文件中namespace等于对应接口的全限定名;
    接口中的方法名和mapper文件中的statement(,…标签)的id属性值一致;
    接口中的方法输入值参数和mapper文件中statement的parameterType指定的类型一致。
    接口中的方法的返回值类型和mapper文件中statement的resultType指定的类型一致。

  5. docker访问外部时一定要注意将localhost之类的换成本地的ipv4地址!这里需要将springboot配置中的localhost更换成你的ipv4地址。