本次作业采用java完成,首先展示一下我的整体架构
这里以CS(课程)包为例进行讲解,每个包下面设置四个文件夹,分别为controller(控制器)、entity(用途:用于存放实体类,与数据库中的基本属性保持一致,实现set和get方法)
mapper(对数据库进行数据操作,他的方法语句是针对数据库操纵的,实现一些增删改查操作)、service(为controller层提供接口)
关于架构的具体理解,可以参考链接 这个讲的还比较清楚
整体是这个样子哒 上面的 cs、inline、student里面的架构都是一样的,下面的templates里面放置HTML,实现前端页面
在前端页面中用到了layui进行渲染,关于layui的使用可以参考官方文档
上手比较容易,直接看文档就可以上手,其实就是在原来HTML的基础上,加一些渲染,本质没有变(就好像你还是你,只是换了一身衣服hhhhh)
首先来展示一下登录页面的代码:
这里我就分前端和后台分别来写啦!
前端:(新建一个HTML,我这里取名为login.html,见名知意)
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>用户登录</title>
<div th:include="header :: imports"></div>
</head>
<body>
<form id="login" action="/login/checkExist" method="post" class="layui-container" style="margin-top: 200px">
<div class="layui-form-item">
<label class="layui-form-label">用户名</label>
<div class="layui-input-block">
<input type="text" name="username" placeholder="请输入用户名" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码</label>
<div class="layui-input-block">
<input type="password" name="password" placeholder="请输入密码" class="layui-input">
</div>
</div>
<!-- <div class="code">-->
<!-- <input type = "text" value="" placeholder="请输入验证码(不区分大小写)" >-->
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" type="submit">登录</button>
<button class="layui-btn" onclick="register()">注册</button>
</div>
</div>
</form>
<div id="list">
</div>
</body>
<script>
$(function () {
$("#login").validate({
rules: {
username: {
required: true
},
password: {
required: true
}
},
onkeyup: false,
success: "valid",
submitHandler: function (form) {
$(form).ajaxSubmit({
type: 'POST',
url: "/login/checkExist",
success: function (data) {
if (data.code == "1") {
if (data.data.type == "student") {
location.href = "/student/studentInfo?id=" + data.data.id
} else if (data.data.type == "teacher") {
location.href = "/teacher/teacherInfo?id=" + data.data.id
}
} else {
layer.msg(data.msg)
}
}
})
}
})
})
function register() {
location.href = "/register"
}
</script>
</html>
后台:
package com.example.demo.inline.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo.inline.entity.AjaxResult;
import com.example.demo.inline.entity.LoginLog;
import com.example.demo.inline.entity.SysUser;
import com.example.demo.inline.service.LoginLogService;
import com.example.demo.inline.service.SysUserService;
import com.example.demo.inline.util.UserUtils;
import com.example.demo.student.entity.Student;
import com.example.demo.student.entity.Teacher;
import com.example.demo.student.service.StudentService;
import com.example.demo.student.service.TeacherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.time.LocalDateTime;
import java.util.Objects;
/**
* Controller class
*
* @author apple
* @date 2020/4/28
*/
@Controller
@RequestMapping("login")
public class LoginController extends BaseController {
@Autowired
private SysUserService sysUserService;
@Autowired
private StudentService studentService;
@Autowired
private TeacherService teacherService;
@Autowired
private LoginLogService loginLogService;
@RequestMapping
public String index() {
return "login";
}
@RequestMapping("checkExist")
@ResponseBody
public AjaxResult login(SysUser sysUser) {
// 1. 与数据库进行连接,检查用户名密码是否正确
//处理登录,select * from sys_user where username = #{username} and password = #{password}、
//创建一个约束包装器
var password = sysUser.getPassword();
var encryptPassword = UserUtils.encryptPassword(password);
sysUser.setPassword(encryptPassword);
var sysUserWrapper = Wrappers.lambdaQuery(sysUser);
var user = sysUserService.getOne(sysUserWrapper, false);
//判断是否为空
var exist = Objects.nonNull(user);
if (exist) {
//判断是什么类型
var userType = user.getUserType();
// 封装成功的json数据
var success = success();
// 获得当前表的 id
var userId = user.getId();
// 记录登录信息
logLogin(userId);
// 设置返回信息
var jsonObject = new JSONObject();
// 判断是什么类型
switch (userType) {
case ADMIN:
break;
case TEACHER:
var teacherWrapper = Wrappers.lambdaQuery(Teacher.class);
teacherWrapper.eq(Teacher::getUserId, userId);
var teacher = teacherService.getOne(teacherWrapper);
jsonObject.put("type", "teacher");
jsonObject.put("id", teacher.getId());
success.put("data", jsonObject);
break;
case STUDENT:
var studentWrapper = Wrappers.lambdaQuery(Student.class);
studentWrapper.eq(Student::getUserId, userId);
var student = studentService.getOne(studentWrapper);
jsonObject.put("type", "student");
jsonObject.put("id", student.getId());
success.put("data", jsonObject);
break;
default:
break;
}
return success;
} else {
return error("对不起,找不到该用户");
}
}
/**
* 记录登录逻辑
* @param userId 登录用户的 id
*/
private void logLogin(Integer userId) {
var loginLog = new LoginLog();
var now = LocalDateTime.now();
loginLog.setUserId(userId)
.setLoginTime(now);
loginLogService.save(loginLog);
}
@GetMapping("showLogs")
public String showAllLogs(Model model) {
var allLogList = loginLogService.list();
model.addAttribute("allLogList", allLogList);
return "/showLogs";
}
}
这里主要就是先要判断用户类型,判断是老师还是学生,然后根据用户类型,判断用户输入的账号和密码是否正确,如果正确的话,才可以登录进去
然后来展示一下用户注册的代码:
前端:
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>注册</title>
<div th:include="header :: imports"></div>
</head>
<body>
<div class="layui-container" style="margin-top: 80px">
<form id="register" action="/register/registerUser" method="post" class="layui-form">
<div>
<div class="layui-form-item">
<label class="layui-form-label">用户名:</label>
<div class="layui-input-block">
<input name="username" class="layui-input" type="text">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">密码:</label>
<div class="layui-input-block">
<input name="password" type="password" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">用户类型</label>
<div class="layui-input-block">
<select name="userType" class="layui-input" lay-filter="userType">
<option value="" selected>请选择</option>
<option value="1">老师</option>
<option value="2">学生</option>
</select>
</div>
</div>
<div id="common" hidden>
<div class="layui-form-item">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input type="text" name="name" class="layui-input">
</div>
</div>
</div>
<div id="student" hidden>
<div class="layui-form-item">
<label class="layui-form-label">性别:</label>
<div class="layui-input-block">
<select name="gender" class="layui-input" lay-filter="userType">
<option value="0">男</option>
<option value="1">女</option>
<option value="" selected>请选择</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">生日:</label>
<div class="layui-input-block">
<input id="birthday" type="date" name="birthday" class="layui-input" value="">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">入学日期:</label>
<div class="layui-input-block">
<input id="enrollmentDate" type="date" name="enrollmentDate" class="layui-input" value="">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">专业:</label>
<div class="layui-input-block">
<input name="major" class="layui-input" value="">
</div>
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" type="submit">注册</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</div>
</body>
<script>
// 设置验证提交
$(function () {
$("#register").validate({
rules: {
username: {
required: true
},
password: {
required: true
}
},
onkeyup: false,
success: "valid",
submitHandler: function (form) {
$(form).ajaxSubmit({
type: 'POST',
url: "/register/registerUser",
success: function (data) {
if (data.code == 1) {
layer.msg("注册成功", function () {
return location.href = "/login"
})
} else {
layer.msg(data.msg)
}
}
})
}
})
})
layui.use(["form", "laydate"], function () {
let laydate = layui.laydate
let form = layui.form
form.render()
// 检测选择的选项,渲染不同的 div
form.on("select(userType)", function (data) {
switch (data.value) {
case "0":
$("#common").hide()
$("#student").hide()
break
case "1":
$("#common").show()
$("#student").hide()
break
case "2":
$("#common").show()
$("#student").show()
laydate.render({
elem: "#birthday",
show: true,
position: "fixed",
trigger: "click"
})
laydate.render({
elem: "#enrollmentDate",
show: true,
position: "fixed",
trigger: "click"
})
break
default:
break
}
})
})
</script>
</html>
用户类型有两种,分别是 学生 和 老师 ,注册的时候的个人信息也是不一样的,老师的个人信息只有老师姓名,学生的个人信息有姓名、性别、生日、入学日期、专业
这是老师的页面:
这是学生的页面:
这里实现上有一个小技巧就是,在针对不同用户注册的时候,将需要展示的所有信息都在HTML上渲染出来,通过layui的hide()和show()方法分别控制就可以完成啦
就类似这种
后端
package com.example.demo.inline.controller;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo.inline.entity.AjaxResult;
import com.example.demo.inline.entity.SysUser;
import com.example.demo.inline.service.SysUserService;
import com.example.demo.inline.util.UserUtils;
import com.example.demo.student.entity.Student;
import com.example.demo.student.entity.Teacher;
import com.example.demo.student.enums.Gender;
import com.example.demo.student.service.StudentService;
import com.example.demo.student.service.TeacherService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import java.time.LocalDate;
import java.util.Objects;
/**
* RegisterController class
* 注册控制器
*
* @author apple
* @date 2020/5/24
*/
@Controller
@RequestMapping("register")
public class RegisterController extends BaseController {
@Autowired
private SysUserService sysUserService;
@Autowired
private StudentService studentService;
@Autowired
private TeacherService teacherService;
@RequestMapping
public String register() {
return "register";
}
/**
* 注册用户,由于这个地方不知道是什么用户,所以除了设置登录用户的信息外,需要将其他参数单独列出来
* @param sysUser 注册用户
* @param name 用户姓名
* @param birthday 学生生日
* @param enrollmentDate 学生注册时间
* @param major 学生主修
* @param gender 学生性别
* @return 是否注册成功
*/
@PostMapping("registerUser")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult registerUser(SysUser sysUser, String name, LocalDate birthday, LocalDate enrollmentDate, String major, Gender gender) {
var userLambdaQueryWrapper = Wrappers.lambdaQuery(SysUser.class);
userLambdaQueryWrapper.eq(SysUser::getUsername, sysUser.getUsername());
var user = sysUserService.getOne(userLambdaQueryWrapper);
if (Objects.nonNull(user)) {
return error("对不起,此用户已存在,不能添加");
} else {
var encryptPassword = UserUtils.encryptPassword(sysUser.getPassword());
sysUser.setPassword(encryptPassword);
sysUserService.save(sysUser);
var userWrapper = Wrappers.lambdaQuery(sysUser);
user = sysUserService.getOne(userWrapper);
}
var userType = user.getUserType();
var userId = user.getId();
boolean isSave = true;
switch (userType) {
case STUDENT:
var student = new Student();
student.setUserId(userId)
.setBirthday(birthday)
.setEnrollmentDate(enrollmentDate)
.setMajor(major)
.setGender(gender);
isSave = studentService.save(student);
break;
case TEACHER:
var teacher = new Teacher();
teacher.setUserId(userId)
.setName(name);
isSave = teacherService.save(teacher);
break;
default:
throw new IllegalArgumentException("对不起,没找到对应参数");
}
return toAjax(isSave);
}
}
后端也是建了一个controller,感觉把不同的功能分开会比较清晰
然后接下来来到了老师的个人页面
上边本来想设置几个菜单栏,但我实在是太菜了,怎么也加不上,尝试了好久就只能跳转链接,所以就只能这样丑了。。
这个代码就不需要展示啦,就是加按钮,然后不停地跳转链接
然后接下来看看 【我所教的课程】
【添加课程】
前端
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>添加课程</title>
<div th:include="header :: imports"></div>
</head>
<body>
<form id="addCourse" action="/teacher/addCourse" method="post" class="layui-form">
<input type="text" th:value="${teacherId}" name="teacherId" hidden>
<div class="layui-form-item">
<label class="layui-form-label">课程名</label>
<div class="layui-input-block">
<input type="text" name="name" placeholder="请输入课程名" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">学分</label>
<div class="layui-input-block">
<input type="text" name="score" placeholder="请输入学分" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" type="submit">提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</body>
<script>
$(function () {
$("#addCourse").validate({
rules: {
name: {
required: true
},
score: {
required: true,
number: true
}
},
onkeyup: false,
success: "valid",
submitHandler: function (form) {
$(form).ajaxSubmit({
success: function (data) {
if (data.code == 1) {
layer.msg("添加成功", function () {
//先得到当前iframe层的索引
let index = parent.layer.getFrameIndex(name)
parent.layer.close(index)
})
} else {
layer.msg(data.msg)
}
}
})
}
})
})
</script>
</html>
后台
/**
* 老师添加课程
*
* @param teacherId 老师的 id
* @param course 需要添加的课程
* @return 添加结果
*/
@PostMapping("addCourse")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult addCourse(Integer teacherId, Cs course) {
// 1.添加课程
var csWrapper = Wrappers.lambdaQuery(course);
var selectCourse = csService.getOne(csWrapper);
var courseId = 0;
if (Objects.isNull(selectCourse)) {
csService.save(course);
course = csService.getOne(csWrapper);
courseId = course.getId();
} else {
courseId = selectCourse.getId();
}
var teacherCs = new TeacherCs();
teacherCs.setTeacherId(teacherId)
.setCsId(courseId);
var teacherCSWrapper = Wrappers.lambdaQuery(teacherCs);
var one = teacherCsService.getOne(teacherCSWrapper);
if (Objects.isNull(one)) {
return toAjax(teacherCsService.save(teacherCs));
} else {
return error("该课程已添加。");
}
}
这里会判断该老师是否添加过该课程,如果添加过的话,会提示【已经添加过】
删除课程
/**
* 删除学生课程
*
* @param studentCourseVOJSONList 学生课程 VO 的 JSON 列表
* @return 是否删除学生课程
*/
@PostMapping("deleteStudents")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult deleteStudents(@RequestBody JSONArray studentCourseVOJSONList) {
var studentCourseVOList = studentCourseVOJSONList.toJavaList(StudentCourseVO.class);
var studentCsIdList = studentCourseVOList.stream()
.map(StudentCourseVO::getId)
.collect(Collectors.toUnmodifiableList());
return toAjax(studentCsService.removeByIds(studentCsIdList));
}
@PostMapping("deleteCourse")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult deleteCourse(@RequestBody JSONArray jsonArray) {
var teacherCourseVOS = jsonArray.toJavaList(TeacherCourseVO.class);
teacherCourseVOS.forEach(teacherCourseVO -> {
var id = teacherCourseVO.getId();
LambdaQueryWrapper<StudentCs> query = Wrappers.lambdaQuery();
query.select(StudentCs::getId)
.eq(StudentCs::getTeacherCsId, id);
var list = studentCsService.list(query);
var idList = list.stream()
.map(StudentCs::getId)
.collect(Collectors.toUnmodifiableList());
studentCsService.removeByIds(idList);
teacherCsService.removeById(id);
});
return success("删除成功");
}
编辑课程:
@GetMapping("editCourseScoreBefore")
public String editCourseScore(Integer id, Model model) {
TeacherCs teacherCs = teacherCsService.getById(id);
Integer courseId = teacherCs.getCsId();
Cs course = csService.getById(courseId);
model.addAttribute("course", course);
return "/teacher/editCourseScore";
}
@PostMapping("editCourseScore")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult editCourseScore(Cs course) {
return toAjax(csService.updateById(course));
}
}
体现在编辑课程的学分上,我也没想到别的还能改啥了🤣
点击课程后,老师可以看到选修该课程的学生、并可以编辑成绩
/**
* 展示课程的详细信息,选课人数,以及控制学生的成绩
*
* @param model 模板引擎
* @param id 老师课程关联表的 id 值
* @return 展示课程的详细信息的页面
*/
@GetMapping("showCourseDetail")
public String showCourseDetail(Model model, Integer id) {
LambdaQueryWrapper<StudentCs> studentCsWrapper = Wrappers.lambdaQuery();
studentCsWrapper.eq(StudentCs::getTeacherCsId, id);
var studentCsList = studentCsService.list(studentCsWrapper);
var studentCourseVOList = studentCsList.stream()
.map(studentCs -> studentService.convertToVO(studentCs))
.collect(Collectors.toUnmodifiableList());
model.addAttribute("studentCourseVOList", studentCourseVOList);
return "/teacher/courseDetail";
}
/**
* 进入编辑学生信息页面
*
* @param model 模板引擎
* @param id 学生课程表的 id 值 (t_student_cs)
* @return 编辑学生信息的窗口
*/
@GetMapping("editSelectCourseStudentInfo/{id}")
public String editSelectCourseStudentInfo(Model model,
@PathVariable("id") Integer id) {
var studentCs = studentCsService.getById(id);
var studentCourseVO = studentService.convertToVO(studentCs);
model.addAttribute("studentCourseVO", studentCourseVO);
return "/teacher/editStudentCourse";
}
/**
* 编辑学生成绩
*
* @param studentCourseVO 学生 VO 类对象
* @return 是否编辑成功
*/
@PostMapping("editStudentScore")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult editStudentScore(StudentCourseVO studentCourseVO) {
var studentCs = studentService.convertToNonVO(studentCourseVO);
studentCs.setScore(studentCourseVO.getScore());
return toAjax(studentCsService.updateById(studentCs));
}
/**
* 删除学生课程
*
* @param studentCourseVOJSONList 学生课程 VO 的 JSON 列表
* @return 是否删除学生课程
*/
@PostMapping("deleteStudents")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult deleteStudents(@RequestBody JSONArray studentCourseVOJSONList) {
var studentCourseVOList = studentCourseVOJSONList.toJavaList(StudentCourseVO.class);
var studentCsIdList = studentCourseVOList.stream()
.map(StudentCourseVO::getId)
.collect(Collectors.toUnmodifiableList());
return toAjax(studentCsService.removeByIds(studentCsIdList));
}
这个课程只有这一条记录
有的课程还没有学生选修,就没有记录
老师查看用户名和密码:
后台
/**
* 查看用户名和密码
* @param model 模板引擎
* @return 展示老师用户名密码路径
*/
@GetMapping("showUsernameAndPassword")
public String showUsernameAndPassword(Model model) {
var userList = sysUserService.list();
model.addAttribute("userList", userList);
return "/teacher/usernameAndPassword";
}
账号和加密后的密码
加密方法:
package com.example.demo.inline.util;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
/**
* UserUtils class
*
* @author apple
* @date 2020/5/28
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class UserUtils {
private static final byte[] KEY = {8, -116, -106, -3, -74, -112, 92, -25, -21, -11, -85, -77, -26, -60, 110, 24};
private static final SymmetricCrypto AES = new SymmetricCrypto(SymmetricAlgorithm.AES, KEY);
/**
* 加密密码
* @param password 需要加密的密码
* @return 加密成功的密码
*/
public static String encryptPassword(String password) {
return AES.encryptHex(password);
}
/**
* 解密数据库中的密码
* @param encryptPassword 数据库中加密的密码
* @return 解密后的密码
*/
public static String decryptPassword(String encryptPassword) {
return AES.decryptStr(encryptPassword, CharsetUtil.CHARSET_UTF_8);
}
}
日志显示:
/**
* 记录登录逻辑
* @param userId 登录用户的 id
*/
private void logLogin(Integer userId) {
var loginLog = new LoginLog();
var now = LocalDateTime.now();
loginLog.setUserId(userId)
.setLoginTime(now);
loginLogService.save(loginLog);
}
@GetMapping("showLogs")
public String showAllLogs(Model model) {
var allLogList = loginLogService.list();
model.addAttribute("allLogList", allLogList);
return "/showLogs";
}
这里和登录写在了一起,每次登录,就记录一下
对学生信息进行增删改查
package com.example.demo.student.controller;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.example.demo.cs.entity.Cs;
import com.example.demo.cs.service.CsService;
import com.example.demo.inline.controller.BaseController;
import com.example.demo.inline.entity.AjaxResult;
import com.example.demo.inline.entity.StudentCs;
import com.example.demo.inline.entity.TeacherCs;
import com.example.demo.inline.service.StudentCsService;
import com.example.demo.inline.service.TeacherCsService;
import com.example.demo.student.entity.Student;
import com.example.demo.student.enums.Gender;
import com.example.demo.student.service.StudentService;
import com.example.demo.student.service.TeacherService;
import com.example.demo.student.vo.StudentCourseVO;
import com.example.demo.student.vo.TeacherCourseVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* StudentController class
*
* @author apple
* @date 2020/5/3
*/
@Controller
@RequestMapping("student")
@Slf4j
public class StudentController extends BaseController {
@Autowired
private StudentService studentService;
@Autowired
private StudentCsService studentCsService;
@Autowired
private CsService csService;
@Autowired
private TeacherCsService teacherCsService;
@Autowired
private TeacherService teacherService;
/**
* 展示所有学生
*
* @param model 前端模板
* @return 展示的学生数据
*/
@RequestMapping
public String showData(Model model) {
var list = studentService.list();
model.addAttribute("students", list);
return "/student/list";
}
@GetMapping("addBefore")
public String addBefore() {
return "/student/addStudent";
}
@PostMapping("add")
@Transactional(rollbackFor = Exception.class)
@ResponseBody
public AjaxResult add(Student student) {
var studentWrapper = Wrappers.lambdaQuery(Student.class);
studentWrapper.eq(Student::getNo, student.getNo());
var one = studentService.getOne(studentWrapper);
if (Objects.isNull(one)) {
return toAjax(studentService.save(student));
} else {
return error("对不起,该学号已存在,无法添加。");
}
}
@GetMapping("search")
public String search() {
return "/student/search";
}
@GetMapping("searchByName")
@ResponseBody
public AjaxResult searchByName(String name) {
/*创建约束条件的包装器*/
var studentWrapper = Wrappers.lambdaQuery(Student.class);
studentWrapper.eq(Student::getName, name);
var studentList = studentService.list(studentWrapper);
return success(studentList);
}
@GetMapping("searchByNo")
@ResponseBody
public AjaxResult searchByNo(String no) {
var studentWrapper = Wrappers.lambdaQuery(Student.class);
studentWrapper.eq(Student::getNo, no);
var studentList = studentService.list(studentWrapper);
return success(studentList);
}
@GetMapping("searchBySex")
@ResponseBody
public AjaxResult searchBySex(Gender gender) {
var studentWrapper = Wrappers.lambdaQuery(Student.class);
studentWrapper.eq(Student::getGender, gender);
var studentList = studentService.list(studentWrapper);
return success(studentList);
}
@GetMapping("editBefore")
public String editBefore(Integer id, Model model) {
var student = studentService.getById(id);
model.addAttribute("student", student);
return "/student/edit";
}
@PostMapping("editStudent")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult edit(Student student) {
return toAjax(studentService.updateById(student));
}
@PostMapping("delete/{id}")
@Transactional(rollbackFor = Exception.class)
@ResponseBody
public AjaxResult delete(@PathVariable("id") Integer id) {
return toAjax(studentService.removeById(id));
}
@GetMapping("change")
public String change() {
return "/student/change";
}
@PostMapping("changeBy")
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> changeName(Student student, String no) {
var jsonObject = new JSONObject();
var studentWrapper = Wrappers.lambdaQuery(Student.class);
studentWrapper.eq(Student::getNo, no);
studentService.update(student, studentWrapper);
return jsonObject;
}
/**
* 展示学生信息
*
* @param model 需要绑定的模板
* @param id 需要查找学生表的 id
* @return 学生个人信息的位置
*/
@GetMapping("studentInfo")
public String studentInfo(Model model, Long id) {
if (Objects.isNull(id)) {
id = 2L;
}
var student = studentService.getById(id);
model.addAttribute("student", student);
return "/student/studentInfo";
}
/**
* 进入学生选课界面
*
* @param model 模板引擎
* @param id 学生 id
* @return 学生选课界面
*/
@GetMapping("course/{id}")
public String chooseCourse(Model model,
@PathVariable("id") Integer id) {
LambdaQueryWrapper<StudentCs> studentCsWrapper = Wrappers.lambdaQuery();
studentCsWrapper.eq(StudentCs::getStudentId, id);
var chooseNonVOList = studentCsService.list(studentCsWrapper);
var chooseList = chooseNonVOList.stream()
.map(studentCs -> studentService.convertToVO(studentCs))
.collect(Collectors.toUnmodifiableList());
var courseIdSet = chooseList.stream().map(StudentCourseVO::getCourseId).collect(Collectors.toUnmodifiableSet());
model.addAttribute("chooseList", chooseList);
// 1. 查询所有课程 id
var allCourseList = csService.list();
// 去除已选择的课程
allCourseList.removeIf(course -> courseIdSet.contains(course.getId()));
// 将对应未选择的课程添加到界面上
var nonExistCourseIdSet = allCourseList.stream()
.map(Cs::getId)
.collect(Collectors.toUnmodifiableSet());
LambdaQueryWrapper<TeacherCs> teacherCsWrapper = Wrappers.lambdaQuery();
for (var courseId : nonExistCourseIdSet) {
teacherCsWrapper.eq(TeacherCs::getCsId, courseId).or();
}
var teacherCourseList = teacherCsService.list(teacherCsWrapper);
var teacherCourseVOList = teacherCourseList.stream()
.map(teacherCs -> teacherService.convertToVO(teacherCs))
.collect(Collectors.toUnmodifiableList());
model.addAttribute("teacherCourseVOList", teacherCourseVOList);
model.addAttribute("studentId", id);
return "/student/chooseCourse";
}
/**
* 学生添加课程
* @param jsonObject 传输的数据对象
* 其中包含的 JSON 对象如下:{
* "studentId": Integer 学生的 id
* "teacherCourseVOList": Array 未添加的课程列表
* }
* @return 添加课程的结果
*/
@PostMapping(value = "addChooseCourse")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult addCourse(@RequestBody JSONObject jsonObject) {
var studentId = jsonObject.getInteger("studentId");
var teacherCourseVOJSONList = jsonObject.getJSONArray("teacherCourseVOList");
var teacherCourseVOList = teacherCourseVOJSONList.toJavaList(TeacherCourseVO.class);
// 找到所有老师对应的课程
var teacherCsList = teacherCourseVOList.stream()
.map(teacherCourseVO -> teacherService.convertToNonVO(teacherCourseVO))
.collect(Collectors.toUnmodifiableList());
var studentCsList = new ArrayList<StudentCs>(teacherCsList.size());
teacherCsList.forEach(teacherCs -> {
var studentCs = new StudentCs();
studentCs.setTeacherCsId(teacherCs.getId());
studentCs.setStudentId(studentId);
studentCsList.add(studentCs);
});
return toAjax(studentCsService.saveBatch(studentCsList, studentCsList.size()));
}
}
前端代码
增加
<!DOCTYPE HTML>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>添加</title>
<div th:include="header :: imports"></div>
</head>
<body>
<form id="addStudent" action="/student/add" method="post">
<div class="layui-form-item">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input type="text" name="name" placeholder="请输入姓名" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">学号</label>
<div class="layui-input-block">
<input type="text" name="no" placeholder="请输入学号" class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">生日</label>
<div class="layui-input-block">
<input type="date" name="birthday">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">入学时间</label>
<div class="layui-input-block">
<input type="date" name="enrollmentDate">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">性别</label>
<div class="layui-input-block">
<label>
<input type="radio" name="gender" value="0"/> 男
</label>
<label>
<input type="radio" name="gender" value="1"/> 女
</label>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">专业</label>
<div class="layui-input-block">
<input class="layui-input" type="text" name="major" placeholder="请输入专业">
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" type="submit">立即提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</body>
<script>
$(function () {
$("#addStudent").validate({
rules: {
name: {
required: true
},
no: {
required: true,
number: true,
},
birthday: {
required: true
},
enrollmentDate: {
required: true
},
gender: {
required: true
},
major: {
required: true
},
},
onkeyup: false,
debug: true,
success: "valid",
submitHandler: function (form) {
$(form).ajaxSubmit({
success: function (data) {
if (data.code == "1") {
layer.open({
title: "添加成功",
content: data.msg,
btn: ["确定"],
yes: function (index, layero) {
location.href = "/student"
},
cancel: function (index, layero) {
}
})
} else {
layer.msg(data.msg)
}
}
})
}
})
})
</script>
</html>
查找
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>查找</title>
<div th:include="header :: imports"></div>
</head>
<body>
<div class="layui-main" style="margin-top: 20px">
<p class="layui-field-title">请选择你要根据什么查询</p>
<select id="options">
<option value="0">姓名</option>
<option value="1">学号</option>
<option value="2">性别</option>
</select>
<input id="name" type="text" name="name" class="layui-input-block">
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" type="submit" id="submit">查询</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
<table id="table">
</table>
</body>
<script>
//给提交按钮添加点击事件
$("#submit").click(function () {
let name = $("#name").val()
let url = "/student/"
let options = $("#options option:selected").val()
switch (options) {
case "0":
url = url + "searchByName?name=" + name
break;
case "1":
url = url + "searchByNo?no=" + name
break;
case "2":
url = url + "searchBySex?gender=" + name
break;
}
$.ajax({
//阿贾克斯(局部刷新)
contentType: "text/html;charset=UTF-8",
url: url, //请求的url地址
async: true,//请求是否异步,默认为异步,这也是ajax重要特性
type: "get", //请求方式
success: function (req) {
if (req.code == 1) {
let data = req.data
layui.use("table", function () {
let table = layui.table
table.render({
elem: "#table",
height: 300,
data: data,
// 注意:在开启 thymeleaf 渲染页面的时候,[[ 连着使用的时候,会触发表达表达式转化异常。
cols: [
[
{
field: "id",
title: "id值",
width: 80,
align: "center"
},
{
field: "name",
title: "姓名",
width: 80,
align: "center"
},
{
field: "gender",
title: "性别",
width: 100,
align: "center",
templet: function (name) {
if (name == "FEMALE") {
return "男";
} else {
return "女";
}
}
},
{
field: "no",
title: "学号",
width: 180,
align: "center"
},
{
field: "birthday",
title: "生日",
width: 200,
align: "center"
},
{
field: "major",
title: "课程",
width: 100,
align: "center"
}
]
]
})
})
}
},
complete: function () {
//请求完成的处理
},
error: function () {
//请求出错处理
}
})
})
</script>
</html>
删除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>删除</title>
</head>
<body>
<form action="/student/delete" method="post">
<div>
<table>
<tr>
<td>请输入您要删除学生的学号!</td>
</tr>
</table>
</div>
<div>
<table>
<tr>
<td>学号:</td>
<td><input type="text" name="no" placeholder="学号"></td>
</tr>
</table>
</div>
<div>
<div>
<input type="submit" value=" 提交 "/>
<input type="reset" value=" 重置 "/>
</div>
</div>
</form>
</body>
</html>
编辑
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>编辑</title>
<div th:include="header :: imports"></div>
</head>
<body>
<form id="edit" action="/student/editStudent" method="post">
<input name="id" th:value="${student.id}" hidden>
<div th:object="${student}">
<div class="layui-form-item">
<label class="layui-form-label">序号</label>
<div class="layui-input-block">
<input name="id" th:value="${student.id}" hidden class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">姓名</label>
<div class="layui-input-block">
<input name="name" th:value="${student.name}" hidden class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">学号</label>
<div class="layui-input-block">
<input name="no" th:value="${student.no}" hidden class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">生日</label>
<div class="layui-input-block">
<input type = "date" name="birthday" th:value="${student.birthday}" hidden class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">入学日期</label>
<div class="layui-input-block">
<input type="date" name="enrollmentDate" th:value="${student.enrollmentDate}" hidden class="layui-input">
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">性别</label>
<div class="layui-input-block">
<select name="gender" lay-verify="" class="layui-input layui-unselect">
<option value="0">男</option>
<option value="1">女</option>
</select>
</div>
</div>
<div class="layui-form-item">
<label class="layui-form-label">专业</label>
<div class="layui-input-block">
<input name="major" th:value="${student.major}" hidden class="layui-input">
</div>
</div>
</div>
<div class="layui-form-item">
<div class="layui-input-block">
<button class="layui-btn" type="submit">提交</button>
<button type="reset" class="layui-btn layui-btn-primary">重置</button>
</div>
</div>
</form>
</body>
<script>
// 设置验证提交
$(function () {
$("#edit").validate({
rules: {
name: {
required: true
},
no: {
required: true
},
birthday: {
required: true
},
enrollmentDate: {
required: true
},
gender: {
required: true
},
major: {
required: true
},
},
onkeyup: false,
debug: true,
success: "valid",
submitHandler: function (form) {
$(form).ajaxSubmit({
type: 'POST',
success: function (data) {
if (data.code == "1") {
layer.msg("编辑成功", function () {
location.href = "/student"
})
} else {
layer.msg("对不起,修改有误,无法修改。")
}
}
})
}
})
})
</script>
</html>
学生选课
前端
<!DOCTYPE html>
<html lang="zh" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>学生选课</title>
<div th:include="header :: imports"></div>
</head>
<body>
<input type="text" id="studentId" name="studentId" th:value="${studentId}" hidden/>
<div id="isChoose" class="layui-container">
<label class="layui-form-label">已选课程</label>
<table class="layui-table">
<tr>
<td>索引</td>
<td>课程</td>
<td>老师</td>
<td>成绩</td>
</tr>
<tr th:each="chooseCourse, count:${chooseList}">
<td th:text="${count.count}"></td>
<td th:text="${chooseCourse.courseName}"></td>
<td th:text="${chooseCourse.teacherName}"></td>
<td th:text="${chooseCourse.score}"></td>
</tr>
</table>
</div>
<div class="layui-container">
<label class="layui-form-label">未选课程</label>
<table id="notChoose" lay-filter="test" class="layui-table"></table>
</div>
</body>
<script type="text/html" id="bar">
<a class="layui-btn layui-btn-primary layui-btn-sm" lay-event="add">添加</a>
</script>
<script th:inline="javascript">
layui.use("table", function () {
let table = layui.table
table.render({
elem: "#notChoose",
toolbar: "#bar",
data: [[${teacherCourseVOList}]],
cols: [
[
{
type: 'checkbox',
fixed: 'left'
},
{
field: 'id',
title: 'ID',
width: 80,
sort: true,
fixed: 'left'
},
{
field: "courseName",
title: '课程名',
width: 130,
sort: true,
fixed: 'left'
},
{
field: 'teacherName',
title: '教师名',
width: 100
},
{
field: 'score',
title: '学分',
width: 80,
sort: true
}
]
]
})
// 监听头工具栏事件
table.on('toolbar(test)', function (obj) {
// 检查选中状态
let checkStatus = table.checkStatus(obj.config.id)
//获取选中的数据
let studentId = $("#studentId").val()
let data = {
"studentId": studentId,
"teacherCourseVOList": checkStatus.data
}
data = JSON.stringify(data)
switch (obj.event) {
// 添加选中的课程
case 'add':
$.ajax({
contentType: "application/json;charset=UTF-8",
data: data,
dataType: "json",
url: "/student/addChooseCourse", //请求的url地址
type: "post", //请求方式
success: function (req) {
if (req.code == 1) {
layer.msg("选课成功", function () {
location.reload()
})
} else {
layer.msg("对不起,该课程已选。")
}
},
complete: function () {
//请求完成的处理
},
error: function () {
//请求出错处理
}
})
break
}
})
})
</script>
</html>
后端
/**
* 进入学生选课界面
*
* @param model 模板引擎
* @param id 学生 id
* @return 学生选课界面
*/
@GetMapping("course/{id}")
public String chooseCourse(Model model,
@PathVariable("id") Integer id) {
LambdaQueryWrapper<StudentCs> studentCsWrapper = Wrappers.lambdaQuery();
studentCsWrapper.eq(StudentCs::getStudentId, id);
var chooseNonVOList = studentCsService.list(studentCsWrapper);
var chooseList = chooseNonVOList.stream()
.map(studentCs -> studentService.convertToVO(studentCs))
.collect(Collectors.toUnmodifiableList());
var courseIdSet = chooseList.stream().map(StudentCourseVO::getCourseId).collect(Collectors.toUnmodifiableSet());
model.addAttribute("chooseList", chooseList);
// 1. 查询所有课程 id
var allCourseList = csService.list();
// 去除已选择的课程
allCourseList.removeIf(course -> courseIdSet.contains(course.getId()));
// 将对应未选择的课程添加到界面上
var nonExistCourseIdSet = allCourseList.stream()
.map(Cs::getId)
.collect(Collectors.toUnmodifiableSet());
LambdaQueryWrapper<TeacherCs> teacherCsWrapper = Wrappers.lambdaQuery();
for (var courseId : nonExistCourseIdSet) {
teacherCsWrapper.eq(TeacherCs::getCsId, courseId).or();
}
var teacherCourseList = teacherCsService.list(teacherCsWrapper);
var teacherCourseVOList = teacherCourseList.stream()
.map(teacherCs -> teacherService.convertToVO(teacherCs))
.collect(Collectors.toUnmodifiableList());
model.addAttribute("teacherCourseVOList", teacherCourseVOList);
model.addAttribute("studentId", id);
return "/student/chooseCourse";
}
/**
* 学生添加课程
* @param jsonObject 传输的数据对象
* 其中包含的 JSON 对象如下:{
* "studentId": Integer 学生的 id
* "teacherCourseVOList": Array 未添加的课程列表
* }
* @return 添加课程的结果
*/
@PostMapping(value = "addChooseCourse")
@ResponseBody
@Transactional(rollbackFor = Exception.class)
public AjaxResult addCourse(@RequestBody JSONObject jsonObject) {
var studentId = jsonObject.getInteger("studentId");
var teacherCourseVOJSONList = jsonObject.getJSONArray("teacherCourseVOList");
var teacherCourseVOList = teacherCourseVOJSONList.toJavaList(TeacherCourseVO.class);
// 找到所有老师对应的课程
var teacherCsList = teacherCourseVOList.stream()
.map(teacherCourseVO -> teacherService.convertToNonVO(teacherCourseVO))
.collect(Collectors.toUnmodifiableList());
var studentCsList = new ArrayList<StudentCs>(teacherCsList.size());
teacherCsList.forEach(teacherCs -> {
var studentCs = new StudentCs();
studentCs.setTeacherCsId(teacherCs.getId());
studentCs.setStudentId(studentId);
studentCsList.add(studentCs);
});
return toAjax(studentCsService.saveBatch(studentCsList, studentCsList.size()));
}
到这里所有的功能就都结束啦!
啊附上视频讲解的网址:https://www.bilibili.com/video/BV1DZ4y1p737/
这次大实验总体做下来用了将近40天左右,中间也有一段时间感觉自己做不出来了,感觉跟老师一起用c#可能会好许多,好在最后坚持下来了,虽然做的不是那么完美,但自己已经很满意啦!这次不仅锻炼了对数据库的使用,还对JAVA开发有了一点点概念,希望以后可以继续加油!