赞
踩
基于javaweb+mysql的springboot在线学习系统(java+springboot+mybatis+vue+mysql+redis)
私信源码获取及调试交流
运行环境
Java≥8、MySQL≥5.7、Node.js≥10
开发工具
后端:eclipse/idea/myeclipse/sts等均可配置运行
前端:WebStorm/VSCode/HBuilderX等均可
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SpringBoot在线学习系统(java+springboot+mybatis+vue+mysql+redis)
一、项目运行 环境配置:
Jdk1.8 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。
项目技术:
Spring + SpringBoot+ mybatis + Maven + Vue 等等组成,B/S模式 + Maven管理等等。
/** */ @RestController @RequestMapping("/note") public class NoteController { private static final Logger logger = LoggerFactory.getLogger(NoteController.class); @Value("${onlinelearning.path.upload.file}") private String fileUploadPath; @Value("${onlinelearning.path.domain}") private String domain; @Resource private HostHolder hostHolder; @Resource private NoteService noteService; /** * 分页查询出所有用户上传的笔记 */ @GetMapping("/all/{pageIndex}") public String getPageOfNote(@PathVariable("pageIndex") Integer pageIndex) { IPage<Note> list = noteService.getPageOfNote(pageIndex); return SystemUtil.getJSONString(200, "", new HashMap<String, Object>() {{ put("total", list.getTotal()); put("noteList", list.getRecords()); }}); } /** * 上传笔记 */ @PostMapping("/add") public String uploadHeader(MultipartFile file) { String fileName; if (file == null || (fileName = file.getOriginalFilename()) == null) { return SystemUtil.getJSONString(2013, "您还没有选择文件!"); }
/** */ @RestController @RequestMapping("/love") public class LoveController { @Resource private HostHolder hostHolder; @Resource private LoveService loveService; /** * 点赞 或 取消点赞,只需要传 帖子id,当前操作人id 直接从 hostHolder 中取即可 */ @GetMapping("/change") public String changeLove(Integer postId) { Integer uid = hostHolder.getUser().getId(); Map<String, Object> res = loveService.changeLove(postId, uid); return SystemUtil.getJSONString((Integer) res.get("code"), (String) res.get("msg"), new HashMap<String, Object>() {{ put("resLove", res.get("resLove")); }}); } } //跨域处理 @Configuration public class MyCorsFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With"); chain.doFilter(req, res); }
//这里需要处理一下user,让其不显示某些字段值 res.put("user", SystemUtil.handleUser(user)); return SystemUtil.getJSONString(200, "", res); } /** * 修改密码 */ @PostMapping("/password") public String updatePassword(@RequestBody UpdatePasswordRequestVO requestVO, @CookieValue("ticket") String ticket) { String errMsg = userService.updatePassword(requestVO, hostHolder.getUser()); if (errMsg.equals("")) { userService.logout(ticket); //修改密码成功后要前端要重新登录 return SystemUtil.getJSONString(200, "修改成功,即将退出重新登录!"); } return SystemUtil.getJSONString(2014, errMsg); } /** * 修改用户它信息(除了密码和头像) * 其实也就只修改3个字段,邮箱、手机、性别 */ @PostMapping("/updateProfile") public String updateProfile(@RequestBody User user) { boolean isOk = userService.updateProfile(user, hostHolder.getUser().getId()); int code = isOk ? 200 : 2100; String msg = isOk ? "修改成功!" : "修改失败!"; return SystemUtil.getJSONString(code, msg); } }
/** */ @RestController @RequestMapping("/user") public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); private final static List<String> imgExtends = Arrays.asList(".jpg", ".png", ".jpeg", ".gif"); @Value("${onlinelearning.path.upload.img}") private String imgUploadPath; @Value("${onlinelearning.path.domain}") private String domain; @Resource private HostHolder hostHolder; @Resource private UserService userService; /** * 更新头像 */
} /** */ @RestController @RequestMapping("/favorite") public class FavoriteController { @Resource private FavoriteService favoriteService; @Resource private HostHolder hostHolder; /** * 添加或取消收藏,传个课程id即可,用户id从后台获取 */ @GetMapping("/change") public String addFavorite(Integer subjectId) { Map<String, Object> res = favoriteService.changeFavorite(subjectId, hostHolder.getUser().getId()); return SystemUtil.getJSONString((Integer) res.get("code"), (String) res.get("msg")); } /** * 删除收藏 */ @DeleteMapping("/delete/{id}") public String delFavorite(@PathVariable("id") Integer id) { boolean isOk = favoriteService.delFavoriteById(id); int code = isOk ? 200 : 2300; String msg = isOk ? "删除成功!" : "删除失败!"; return SystemUtil.getJSONString(code, msg); }
@GetMapping("/header/{fileName}") public void getUserHeader(@PathVariable("fileName") String fileName, HttpServletResponse response) { // 服务器存放路径 fileName = imgUploadPath + "/" + fileName; // 文件后缀 String suffix = fileName.substring(fileName.lastIndexOf(".")); // 响应图片 response.setContentType("image/" + suffix); try ( // java 7 写在这里会自动添加finally代码块来关闭流 FileInputStream fis = new FileInputStream(fileName); OutputStream os = response.getOutputStream() ) { byte[] buffer = new byte[1024]; int b = 0; while ((b = fis.read(buffer)) != -1) { os.write(buffer, 0, b); } } catch (IOException e) { logger.error("读取头像失败: " + e.getMessage()); } } /** * 用户主页,可以查看别人的个人信息 */ @GetMapping("/profile/{userId}") public String getProfilePage(@PathVariable("userId") int userId) { User user = userService.getUserById(userId); if (user == null) { throw new GlobalException(2007, "该用户不存在!"); } Map<String, Object> res = new HashMap<>(); //这里需要处理一下user,让其不显示某些字段值 res.put("user", SystemUtil.handleUser(user)); return SystemUtil.getJSONString(200, "", res); } /** * 修改密码 */ @PostMapping("/password") public String updatePassword(@RequestBody UpdatePasswordRequestVO requestVO, @CookieValue("ticket") String ticket) { String errMsg = userService.updatePassword(requestVO, hostHolder.getUser()); if (errMsg.equals("")) {
public String addComment(@RequestBody Comment comment) { boolean isOk = commentService.save(comment); //重新查询一下插入的评论信息 Comment one = isOk ? commentService.getById(comment.getId()) : null; if (isOk) { //查询成功才往 post 表更新 replynum 字段 postService.updateReplynumOfPost(1, comment.getPostId()); return SystemUtil.getJSONString(200, "评论成功!", new HashMap<String, Object>() {{ put("comment", one); }}); } return SystemUtil.getJSONString(4000, "评论失败!"); } /** * todo:暂时不做这个功能 * 传评论 id 和 评论层级 level * 删除评论,传一个参数,评论id,还要对其子评论进行递归删除 * 分情况讨论 * ①若 level 为0,则直接删除 id 为 id的那条评论 和 parentId 为 id 的所有记录 * ②若 level 为1,则拿出那条记录的 parentId,然后查出 parentId+(level=2)+(targetId=待删除level=1的评论的那个uid) * 另外加上直接删除该条评论 * ③若 level 为2,则直接删除 id 为 id的那条评论 * ④减去该帖子被删除的回复数 */ @PostMapping("/del/{id}") public String delComment(@PathVariable("id") Integer id) { boolean isOk = commentService.removeById(id); int code = isOk ? 200 : 2300; String msg = isOk ? "删除成功!" : "删除失败!"; return SystemUtil.getJSONString(code, msg); } } /**
String fileName; if (file == null || (fileName = file.getOriginalFilename()) == null) { return SystemUtil.getJSONString(2013, "您还没有选择图片!"); } String suffix = fileName.substring(fileName.lastIndexOf(".")); if (StringUtils.isBlank(suffix) || !imgExtends.contains(suffix.toLowerCase())) { return SystemUtil.getJSONString(2013, "图片格式不正确!"); } // 生成随机文件名 String newFileName = SystemUtil.generateUUID() + suffix; // 构建上传文件的存放 "文件夹" 路径 File fileDir = new File(imgUploadPath); if (!fileDir.exists()) { // 递归生成文件夹 fileDir.mkdirs(); } // 确定文件存放的路径 File dest = new File(fileDir.getAbsolutePath() + "/" + newFileName); try { // 存储文件 file.transferTo(dest); } catch (IOException e) { logger.error("上传图片失败: " + e.getMessage()); throw new RuntimeException("上传文件失败,服务器发生异常!", e); } // 更新当前用户的头像的路径(web访问路径) // http://localhost:8006/user/header/xxx.png User user = hostHolder.getUser(); String headerUrl = domain + "/user/header/" + newFileName; userService.updateHeader(user.getId(), headerUrl); return SystemUtil.getJSONString(200, "上传成功!", new HashMap<String, Object>() {{ put("imgUrl", headerUrl); }}); } /** * 获取用户头像 */ @GetMapping("/header/{fileName}") public void getUserHeader(@PathVariable("fileName") String fileName, HttpServletResponse response) { // 服务器存放路径 fileName = imgUploadPath + "/" + fileName; // 文件后缀 String suffix = fileName.substring(fileName.lastIndexOf(".")); // 响应图片 response.setContentType("image/" + suffix); try ( // java 7 写在这里会自动添加finally代码块来关闭流 FileInputStream fis = new FileInputStream(fileName); OutputStream os = response.getOutputStream() ) {
*/ @GetMapping("/logout") public void logout(@CookieValue("ticket") String ticket) { userService.logout(ticket); } } public class HttpIpUtils { /** * 真实ip地址 */ public static String getClientIp(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) { //多次反向代理后会有多个ip值,第一个ip才是真实ip int index = ip.indexOf(","); if (index != -1) { return ip.substring(0, index); } else { return ip; } } ip = request.getHeader("X-Real-IP"); if (!StringUtils.isEmpty(ip) && !"unKnown".equalsIgnoreCase(ip)) { return ip; } return request.getRemoteAddr(); } /** * 获取用户真实IP地址,不使用request.getRemoteAddr(); 的原因是有可能用户使用了代理软件方式避免真实IP地址 */ public static String getRealClientIp(HttpServletRequest request) { String ip; try { ip = request.getHeader("x-forwarded-for"); if ((ip == null) || (ip.length() == 0) || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); }
//全局异常处理 @ControllerAdvice @RestController public class CommonAdvice { private static Logger logger = LoggerFactory.getLogger(CommonAdvice.class); /** * 原始异常处理 */ @ExceptionHandler(Exception.class) @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) String handleExceptionForErrorOne(Exception e, HttpServletRequest request) { logger.info("Exception message:{}", e.getMessage()); logger.info("Exception from:{}", e.getCause()); logger.info("Exception print:{}", e); return SystemUtil.getJSONString(HttpStatus.INTERNAL_SERVER_ERROR.value(), e.getMessage()); } /** * 自定义全局异常处理 */ @ExceptionHandler(GlobalException.class) String handleExceptionForErrorTwo(GlobalException e, HttpServletRequest request) { logger.info("MyException message:{}", e.getMessage()); logger.info("MyException from:{}", e.getCause()); logger.info("MyException print:{}", e); return SystemUtil.getJSONString(e.getCode(), e.getMessage()); } }
@Aspect @Component public class SysLogAspect { @Pointcut("execution(* com.gll.onlinelearning.controller..*.*(..))") public void log() { } @Before("log()") public void doBefore(JoinPoint joinPoint) throws UnsupportedEncodingException { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String method = request.getMethod(); StringBuffer paramsValue = new StringBuffer(); Object paramsName = null; // get请求 if (HttpMethod.GET.toString().equals(method)) { String queryString = request.getQueryString(); if (!StringUtils.isEmpty(queryString)) { paramsName = JSON.parseObject(JSON.toJSONString(joinPoint.getSignature())).get("parameterNames"); paramsValue.append(URLDecoder.decode(queryString, "UTF-8")); } } else { //其他请求 Object[] paramsArray = joinPoint.getArgs(); paramsName = JSON.parseObject(JSON.toJSONString(joinPoint.getSignature())).get("parameterNames"); for (Object o : paramsArray) { paramsValue.append(o).append(" "); } } String ip = HttpIpUtils.getClientIp(request); log.info("URLParamName:" + paramsName); log.info("URLParamValue:" + paramsValue); log.info("URL:{},HTTP_METHOD:{},IP:{},Method:{}", request.getRequestURL().toString(), request.getMethod(), ip, joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); } }
// 根据网卡取本机配置的IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } assert inet != null; ip = inet.getHostAddress(); } } // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 // / "***.***.***.***".length() if (ip != null && ip.length() > 15) { // = 15 if (ip.indexOf(",") > 0) { ip = ip.substring(0, ip.indexOf(",")); } } } catch (Exception e) { ip = ""; } return ip; } } @Slf4j
if (StringUtils.isBlank(suffix) || !imgExtends.contains(suffix.toLowerCase())) { return SystemUtil.getJSONString(2013, "图片格式不正确!"); } // 生成随机文件名 String newFileName = SystemUtil.generateUUID() + suffix; // 构建上传文件的存放 "文件夹" 路径 File fileDir = new File(imgUploadPath); if (!fileDir.exists()) { // 递归生成文件夹 fileDir.mkdirs(); } // 确定文件存放的路径 File dest = new File(fileDir.getAbsolutePath() + "/" + newFileName); try { // 存储文件 file.transferTo(dest); } catch (IOException e) { logger.error("上传图片失败: " + e.getMessage()); throw new RuntimeException("上传文件失败,服务器发生异常!", e); } // 更新当前用户的头像的路径(web访问路径) // http://localhost:8006/user/header/xxx.png User user = hostHolder.getUser(); String headerUrl = domain + "/user/header/" + newFileName; userService.updateHeader(user.getId(), headerUrl); return SystemUtil.getJSONString(200, "上传成功!", new HashMap<String, Object>() {{ put("imgUrl", headerUrl); }}); } /** * 获取用户头像 */ @GetMapping("/header/{fileName}") public void getUserHeader(@PathVariable("fileName") String fileName, HttpServletResponse response) { // 服务器存放路径 fileName = imgUploadPath + "/" + fileName; // 文件后缀 String suffix = fileName.substring(fileName.lastIndexOf(".")); // 响应图片 response.setContentType("image/" + suffix); try ( // java 7 写在这里会自动添加finally代码块来关闭流
try ( // java 7 写在这里会自动添加finally代码块来关闭流 FileInputStream fis = new FileInputStream(fileName); OutputStream os = response.getOutputStream() ) { byte[] buffer = new byte[1024]; int b = 0; while ((b = fis.read(buffer)) != -1) { os.write(buffer, 0, b); } } catch (IOException e) { logger.error("读取头像失败: " + e.getMessage()); } } /** * 用户主页,可以查看别人的个人信息 */ @GetMapping("/profile/{userId}") public String getProfilePage(@PathVariable("userId") int userId) { User user = userService.getUserById(userId); if (user == null) { throw new GlobalException(2007, "该用户不存在!"); } Map<String, Object> res = new HashMap<>(); //这里需要处理一下user,让其不显示某些字段值 res.put("user", SystemUtil.handleUser(user)); return SystemUtil.getJSONString(200, "", res); } /** * 修改密码 */ @PostMapping("/password") public String updatePassword(@RequestBody UpdatePasswordRequestVO requestVO, @CookieValue("ticket") String ticket) { String errMsg = userService.updatePassword(requestVO, hostHolder.getUser()); if (errMsg.equals("")) { userService.logout(ticket); //修改密码成功后要前端要重新登录 return SystemUtil.getJSONString(200, "修改成功,即将退出重新登录!"); } return SystemUtil.getJSONString(2014, errMsg); } /** * 修改用户它信息(除了密码和头像)
*/ @DeleteMapping("/delete/{id}") public String delFavorite(@PathVariable("id") Integer id) { boolean isOk = favoriteService.delFavoriteById(id); int code = isOk ? 200 : 2300; String msg = isOk ? "删除成功!" : "删除失败!"; return SystemUtil.getJSONString(code, msg); } /** * 分页查询出当前登录用户的收藏,当前登录的用户 uid 从 HostHolder 中取,可有模糊搜索共用一个接口 */ @GetMapping("/all") public String getPageOfFavorite(Integer pageIndex, String searchContent) { Integer uid = hostHolder.getUser().getId(); List<PageOfFavoriteResultVO> voList = favoriteService.pageOfFavoriteByUidOrTitle(uid, pageIndex, searchContent); int total = favoriteService.getCountOfFavoriteByUidOrTitle(uid, searchContent); return SystemUtil.getJSONString(200, "", new HashMap<String, Object>() {{ put("total", total); put("favoriteList", voList); }}); } } //全局异常处理 @ControllerAdvice @RestController public class CommonAdvice { private static Logger logger = LoggerFactory.getLogger(CommonAdvice.class); /** * 原始异常处理
//日志切面 @Slf4j @Aspect @Component public class SysLogAspect { @Pointcut("execution(* com.gll.onlinelearning.controller..*.*(..))") public void log() { } @Before("log()") public void doBefore(JoinPoint joinPoint) throws UnsupportedEncodingException { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); String method = request.getMethod(); StringBuffer paramsValue = new StringBuffer(); Object paramsName = null; // get请求 if (HttpMethod.GET.toString().equals(method)) { String queryString = request.getQueryString(); if (!StringUtils.isEmpty(queryString)) { paramsName = JSON.parseObject(JSON.toJSONString(joinPoint.getSignature())).get("parameterNames"); paramsValue.append(URLDecoder.decode(queryString, "UTF-8")); } } else { //其他请求 Object[] paramsArray = joinPoint.getArgs(); paramsName = JSON.parseObject(JSON.toJSONString(joinPoint.getSignature())).get("parameterNames"); for (Object o : paramsArray) { paramsValue.append(o).append(" "); } } String ip = HttpIpUtils.getClientIp(request); log.info("URLParamName:" + paramsName); log.info("URLParamValue:" + paramsValue); log.info("URL:{},HTTP_METHOD:{},IP:{},Method:{}", request.getRequestURL().toString(), request.getMethod(), ip, joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName()); } }
} } //跨域处理 @Configuration public class MyCorsFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { HttpServletResponse response = (HttpServletResponse) res; response.setHeader("Access-Control-Allow-Origin", "*"); response.setHeader("Access-Control-Allow-Credentials", "true"); response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE, HEAD"); response.setHeader("Access-Control-Max-Age", "3600"); response.setHeader("Access-Control-Allow-Headers", "access-control-allow-origin, authority, content-type, version-info, X-Requested-With"); chain.doFilter(req, res); } @Override public void destroy() { } }
/** */ @RestController @RequestMapping("/user") public class UserController { private static final Logger logger = LoggerFactory.getLogger(UserController.class); private final static List<String> imgExtends = Arrays.asList(".jpg", ".png", ".jpeg", ".gif"); @Value("${onlinelearning.path.upload.img}") private String imgUploadPath; @Value("${onlinelearning.path.domain}") private String domain; @Resource private HostHolder hostHolder; @Resource private UserService userService; /** * 更新头像 */ @PostMapping("/updateAvatar") public String uploadHeader(MultipartFile file) { String fileName; if (file == null || (fileName = file.getOriginalFilename()) == null) { return SystemUtil.getJSONString(2013, "您还没有选择图片!"); } String suffix = fileName.substring(fileName.lastIndexOf(".")); if (StringUtils.isBlank(suffix) || !imgExtends.contains(suffix.toLowerCase())) { return SystemUtil.getJSONString(2013, "图片格式不正确!"); } // 生成随机文件名 String newFileName = SystemUtil.generateUUID() + suffix; // 构建上传文件的存放 "文件夹" 路径 File fileDir = new File(imgUploadPath); if (!fileDir.exists()) { // 递归生成文件夹 fileDir.mkdirs(); } // 确定文件存放的路径 File dest = new File(fileDir.getAbsolutePath() + "/" + newFileName); try { // 存储文件 file.transferTo(dest); } catch (IOException e) {
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。