基于javaweb+mysql的springboot成绩管理系统(前后端分离+java+vue+springboot+ssm+mysql+maven)
运行环境
Java≥8、MySQL≥5.7、Node.js≥10
开发工具
后端:eclipse/idea/myeclipse/sts等均可配置运行
前端:WebStorm/VSCode/HBuilderX等均可
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SpringBoot成绩管理系统(前后端分离+java+vue+springboot+ssm+mysql+maven)
一、项目简述
本系统功能包括: 超豪华成绩管理系统,学生,教师,管理员三类用户集 成,课程表管理,成绩查询,成绩详情数据统计,课程录 入,用户管理,账号管理。
二、项目运行
环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX (Webstorm也 行)+ Eclispe (IntelliJ IDEA,Eclispe,MyEclispe,Sts都支 持)。
项目技术: Springboot + Maven + Mybatis + Vue等等组成, B/S模式+ Maven等等。
@Autowired
private TeacherCourseService teacherCourseService;
@PostMapping
public void add(@RequestBody JSONArray teacherCourseInfo) {
List<TeacherCourse> list = JSONObject.parseArray(teacherCourseInfo.toJSONString(), TeacherCourse.class);
teacherCourseService.add(list);
}
@DeleteMapping("/{ids}")
public void delete(@PathVariable("ids") Integer[] ids) {
List<Integer> idsList = Arrays.asList(ids);
teacherCourseService.delete(idsList);
}
@PutMapping
public void update(@RequestBody TeacherCourse teacherCourse) {
teacherCourseService.update(teacherCourse);
}
@GetMapping("/getCourseListById/{id}")
public List<TeacherCourse> getCourseListById(@PathVariable("id") String id) {
return teacherCourseService.getCourseListById(id);
}
@GetMapping("/getProfessionInfoByTeacher/{teacherId}")
public List<Map<String, Object>> getProfessionInfo(@PathVariable("teacherId") String teacherId) {
return teacherCourseService.getProfessionInfo(teacherId);
}
@GetMapping("/getProfessionInfoByAdmin")
public List<Map<String, Object>> getProfessionInfoByAdmin() {
return teacherCourseService.getProfessionInfoByAdmin();
}
@GetMapping("/getCourseInfo")
public TeacherCourse getCourseInfo(@RequestParam Map<String, Object> condition) {
return teacherCourseService.getCourseInfo(condition);
}
}
@Override
public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
//通过所有OPTION请求
if(httpServletRequest.getMethod().toUpperCase().equals("OPTIONS")){
return true;
}
String token = httpServletRequest.getHeader("Authorization");// 从 http 请求头中取出 token
String refreshToken = httpServletRequest.getHeader("freshToken");// 从 http 请求头中取出 token
Enumeration<String> headerNames = httpServletRequest.getHeaderNames();
//2.遍历
while(headerNames.hasMoreElements()){
String name = headerNames.nextElement();
//通过请求头的名称获取请求头的值
String value = httpServletRequest.getHeader(name);
System.out.println(name+"----"+value);
}
// 如果不是映射到方法直接通过
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
//检查是否有passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
// 获取 token 中的 用户信息
String userValue = null;
try {
userValue = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new RuntimeException("401");
}
Map<String, Object> map = new HashMap<>();
map.put("level", (userValue).substring(0,1));
map.put("id", (userValue).substring(1));
User user = userService.findUser(map);
if (user == null) {
throw new RuntimeException("用户不存在,请重新登录");
}
/**
* Description 管理员账户控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/user/admin")
public class AdminController {
@Autowired
private AdminService adminService;
@PostMapping
public void addAdmin(@RequestBody User user) {
adminService.add(user);
}
@DeleteMapping("/{ids}")
public void delete(@PathVariable("ids") Integer[] ids) {
List<Integer> idsList = Arrays.asList(ids);
adminService.delete(idsList);
}
@PutMapping
public void update(@RequestBody User user) {
adminService.update(user);
}
@GetMapping("/getAdminList")
public PagingResult<User> getAdminList (@RequestParam Map<String, Object> condition,
@RequestParam(required = false, name = "$limit", defaultValue = "10") Integer limit,
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return adminService.getAdminList(rowBounds, condition);
}
}
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return courseService.getCourseList(rowBounds, condition);
}
@GetMapping("/getCourseByMap")
private List<Course> getCourseByMap (@RequestParam Map<String, Object> condition) {
return courseService.getCourseByMap(condition);
}
}
/**
* Description 课程表控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/timetable")
public class TimetableController {
@Autowired
private TimetableService timetableService;
@PostMapping
public void add(@RequestBody JSONArray WeekCourseList) {
List<WeekCourse> list = JSONObject.parseArray(WeekCourseList.toJSONString(), WeekCourse.class);
timetableService.add(list);
}
@GetMapping("/getTimetable")
public List<WeekCourse> getStudentList (@RequestParam Map<String, Object> condition) {
/**
* Description 解决vue+spring boot跨域问题
* Author: zjh
**/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS")
.maxAge(3600 * 24);
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加自定义拦截器和拦截路径,此处对所有请求进行拦截,除了登录界面和登录接口
registry.addInterceptor(appInterceptor())
.addPathPatterns("/api/sms/**")//添加拦截路径,拦截所有
.excludePathPatterns("/login"); // 排除的拦截路径
WebMvcConfigurer.super.addInterceptors(registry);
}
@Bean
public HandlerInterceptor appInterceptor(){
return new AuthenticationInterceptor();
}
}
/**
public class StudentController {
@Autowired
private StudentService studentService;
@PostMapping
public void addStudent(@RequestBody User user) {
studentService.addStudent(user);
}
@DeleteMapping("/{ids}")
public void delete(@PathVariable("ids") String[] ids) {
List<String> idsList = Arrays.asList(ids);
studentService.delete(idsList);
}
@PutMapping
public void update(@RequestBody User user) {
studentService.update(user);
}
@GetMapping("/getStudentList")
public PagingResult<User> getStudentList (@RequestParam Map<String, Object> condition,
@RequestParam(required = false, name = "$limit", defaultValue = "10") Integer limit,
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return studentService.getStudentList(rowBounds, condition);
}
}
/**
* Description 管理员账户控制层
* Author: zjh
public Map<String, Object> getUserTotal (@RequestParam Map<String, Object> condition) {
return scoreService.getUserTotal(condition);
}
}
/**
* Description 解决vue+spring boot跨域问题
* Author: zjh
**/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS")
.maxAge(3600 * 24);
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加自定义拦截器和拦截路径,此处对所有请求进行拦截,除了登录界面和登录接口
registry.addInterceptor(appInterceptor())
.addPathPatterns("/api/sms/**")//添加拦截路径,拦截所有
.excludePathPatterns("/login"); // 排除的拦截路径
WebMvcConfigurer.super.addInterceptors(registry);
}
@Bean
public HandlerInterceptor appInterceptor(){
return new AuthenticationInterceptor();
}
}
// 如果不是映射到方法直接通过
if (!(object instanceof HandlerMethod)) {
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) object;
Method method = handlerMethod.getMethod();
//检查是否有passtoken注释,有则跳过认证
if (method.isAnnotationPresent(PassToken.class)) {
PassToken passToken = method.getAnnotation(PassToken.class);
if (passToken.required()) {
return true;
}
}
// 获取 token 中的 用户信息
String userValue = null;
try {
userValue = JWT.decode(token).getAudience().get(0);
} catch (JWTDecodeException j) {
throw new RuntimeException("401");
}
Map<String, Object> map = new HashMap<>();
map.put("level", (userValue).substring(0,1));
map.put("id", (userValue).substring(1));
User user = userService.findUser(map);
if (user == null) {
throw new RuntimeException("用户不存在,请重新登录");
}
Date oldTime = JWT.decode(token).getExpiresAt();
Date refreshTime = JWT.decode(refreshToken).getExpiresAt();
long oldDiff = oldTime.getTime() - new Date().getTime();//这样得到的差值是毫秒级别
long refreshDiff = refreshTime.getTime() - new Date().getTime();//这样得到的差值是毫秒级别
if (oldDiff <= 0) {
if (refreshDiff <= 0) {
logger.error("=== token 已过期, 请重新登录 ===");
httpServletResponse.sendError(401);
return false;
// throw new RuntimeException("401");
/**
* Description 管理员账户控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/user/admin")
public class AdminController {
@Autowired
private AdminService adminService;
@PostMapping
public void addAdmin(@RequestBody User user) {
adminService.add(user);
}
@DeleteMapping("/{ids}")
public void delete(@PathVariable("ids") Integer[] ids) {
List<Integer> idsList = Arrays.asList(ids);
adminService.delete(idsList);
}
@PutMapping
public void update(@RequestBody User user) {
adminService.update(user);
}
@GetMapping("/getAdminList")
public PagingResult<User> getAdminList (@RequestParam Map<String, Object> condition,
@RequestParam(required = false, name = "$limit", defaultValue = "10") Integer limit,
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return adminService.getAdminList(rowBounds, condition);
}
}
@GetMapping("/getProfessionInfoByAdmin")
public List<Map<String, Object>> getProfessionInfoByAdmin() {
return teacherCourseService.getProfessionInfoByAdmin();
}
@GetMapping("/getCourseInfo")
public TeacherCourse getCourseInfo(@RequestParam Map<String, Object> condition) {
return teacherCourseService.getCourseInfo(condition);
}
}
/**
* Description 成绩查询控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/score")
public class ScoreController {
@Autowired
private ScoreService scoreService;
@GetMapping("/getCourseList")
public PagingResult<Course> getCourseList (@RequestParam Map<String, Object> condition,
@RequestParam(required = false, name = "$limit", defaultValue = "10") Integer limit,
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return scoreService.getCourseList(rowBounds, condition);
/**
* Description 解决vue+spring boot跨域问题
* Author: zjh
**/
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "DELETE", "PUT", "PATCH", "OPTIONS")
.maxAge(3600 * 24);
}
// 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加自定义拦截器和拦截路径,此处对所有请求进行拦截,除了登录界面和登录接口
registry.addInterceptor(appInterceptor())
.addPathPatterns("/api/sms/**")//添加拦截路径,拦截所有
.excludePathPatterns("/login"); // 排除的拦截路径
WebMvcConfigurer.super.addInterceptors(registry);
}
@Bean
public HandlerInterceptor appInterceptor(){
return new AuthenticationInterceptor();
}
}
@GetMapping("/getCourseInfo")
public TeacherCourse getCourseInfo(@RequestParam Map<String, Object> condition) {
return teacherCourseService.getCourseInfo(condition);
}
}
/**
* Description 成绩查询控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/score")
public class ScoreController {
@Autowired
private ScoreService scoreService;
@GetMapping("/getCourseList")
public PagingResult<Course> getCourseList (@RequestParam Map<String, Object> condition,
@RequestParam(required = false, name = "$limit", defaultValue = "10") Integer limit,
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return scoreService.getCourseList(rowBounds, condition);
}
@PostMapping
private void addEntry(@RequestBody JSONArray UserScore) {
List<Score> list = JSONObject.parseArray(UserScore.toJSONString(), Score.class);
scoreService.addEntry(list);
}
@GetMapping("/export")
public List<Course> getExportList (@RequestParam Map<String, Object> condition) {
/**
* Description 登陆用户控制层
* Author: zjh
**/
@RestController
@UserLoginToken
@RequestMapping("/api/sms/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/login")
@PassToken
public User getStudentInfo (@RequestParam Map<String, Object> condition) {
Map<String, Object> map = new HashMap<>();
map.put("username", condition.get("username").toString());
map.put("password", condition.get("password").toString());
map.put("level", condition.get("level"));
User user = userService.getStudentInfo(map);
// String token = userService.getToken(user, 60* 60 * 1000); // 有效期1h
String token = userService.getToken(user, 24*60* 60 * 1000);
String refreshToken = userService.getToken(user, 24*60*60*1000); // 有效期一天
user.setToken(token);
user.setRefreshToken(refreshToken);
return user;
}
@GetMapping("/edit/password")
public boolean update (@RequestParam Map<String, Object> condition) {
Map<String, Object> map = new HashMap<>();
/**
* Description 上传控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/upload")
public class UploadController {
@Autowired
private UploadService uploadService;
@PostMapping("/headImg")
@ResponseBody
public String upload(MultipartFile file, HttpServletRequest request) throws IOException {
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
// 储存位置
String url = "sms/static/img/";
// 图片名
String ImgName = file.getOriginalFilename();
String uid = UUID.randomUUID().toString();
assert ImgName != null;
// 获取后缀名
String str = ImgName.substring(ImgName.lastIndexOf("."));
@Autowired
private TeacherCourseService teacherCourseService;
@PostMapping
public void add(@RequestBody JSONArray teacherCourseInfo) {
List<TeacherCourse> list = JSONObject.parseArray(teacherCourseInfo.toJSONString(), TeacherCourse.class);
teacherCourseService.add(list);
}
@DeleteMapping("/{ids}")
public void delete(@PathVariable("ids") Integer[] ids) {
List<Integer> idsList = Arrays.asList(ids);
teacherCourseService.delete(idsList);
}
@PutMapping
public void update(@RequestBody TeacherCourse teacherCourse) {
teacherCourseService.update(teacherCourse);
}
@GetMapping("/getCourseListById/{id}")
public List<TeacherCourse> getCourseListById(@PathVariable("id") String id) {
return teacherCourseService.getCourseListById(id);
}
@GetMapping("/getProfessionInfoByTeacher/{teacherId}")
public List<Map<String, Object>> getProfessionInfo(@PathVariable("teacherId") String teacherId) {
return teacherCourseService.getProfessionInfo(teacherId);
}
@GetMapping("/getProfessionInfoByAdmin")
public List<Map<String, Object>> getProfessionInfoByAdmin() {
return teacherCourseService.getProfessionInfoByAdmin();
}
@GetMapping("/getCourseInfo")
public TeacherCourse getCourseInfo(@RequestParam Map<String, Object> condition) {
return teacherCourseService.getCourseInfo(condition);
}
}
/**
* Description 成绩查询控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/score")
public class ScoreController {
@Autowired
private ScoreService scoreService;
@GetMapping("/getCourseList")
public PagingResult<Course> getCourseList (@RequestParam Map<String, Object> condition,
@RequestParam(required = false, name = "$limit", defaultValue = "10") Integer limit,
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return scoreService.getCourseList(rowBounds, condition);
}
@PostMapping
private void addEntry(@RequestBody JSONArray UserScore) {
List<Score> list = JSONObject.parseArray(UserScore.toJSONString(), Score.class);
scoreService.addEntry(list);
}
@GetMapping("/export")
public List<Course> getExportList (@RequestParam Map<String, Object> condition) {
return scoreService.getExportList(condition);
}
@GetMapping("/getUserNum")
public List<Map<String, Object>> getUserNum (@RequestParam Map<String, Object> condition) {
return scoreService.getUserNum(condition);
}
@GetMapping("/getUserTotal")
public Map<String, Object> getUserTotal (@RequestParam Map<String, Object> condition) {
return scoreService.getUserTotal(condition);
}
}
/**
logger.error("=== token 已过期, 请重新登录 ===");
httpServletResponse.sendError(401);
return false;
// throw new RuntimeException("401");
}
}
String newToken = userService.getToken(user, 60* 60 * 1000);
String newRefToken = userService.getToken(user, 24*60*60*1000);
// 更新token
httpServletResponse.setHeader("Authorization", newToken);
httpServletResponse.setHeader("freshToken", newRefToken);
//检查有没有需要用户权限的注解
// if (method.isAnnotationPresent(UserLoginToken.class)) { // 是否使用@UserLoginToken注解
// UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
// if (userLoginToken.required()) {
// 执行认证
if (token == null) {
throw new RuntimeException("=== 无token,请重新登录 ===");
}
// 利用用户密码,解密验证 token
JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();
try {
jwtVerifier.verify(token);
} catch (JWTVerificationException e) {
logger.error("=== token验证失败 ===");
httpServletResponse.sendError(401);
return false;
// throw new RuntimeException("401");
}
// return true;
// }
// }
return true;
}
@Override
public void postHandle(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest httpServletRequest,
HttpServletResponse httpServletResponse,
Object o, Exception e) throws Exception {
}
@DeleteMapping("/{ids}")
public void delete(@PathVariable("ids") Integer[] ids) {
List<Integer> idsList = Arrays.asList(ids);
courseService.delete(idsList);
}
@PutMapping
public void update(@RequestBody Course course) {
courseService.update(course);
}
@GetMapping("/getCourseList")
private PagingResult<Course> getCourseList (@RequestParam Map<String, Object> condition,
@RequestParam(required = false, name = "$limit", defaultValue = "10") Integer limit,
@RequestParam(required = false, name = "$offset", defaultValue = "0") Integer offset) {
RowBounds rowBounds = new RowBounds(offset, limit);
return courseService.getCourseList(rowBounds, condition);
}
@GetMapping("/getCourseByMap")
private List<Course> getCourseByMap (@RequestParam Map<String, Object> condition) {
return courseService.getCourseByMap(condition);
}
}
/**
* Description 课程表控制层
* Author: zjh
**/
@RestController
@RequestMapping("/api/sms/timetable")
public class TimetableController {
@Autowired
private TimetableService timetableService;
@PostMapping