本人的毕业设计,页面设计感觉不咋地,感觉可以做出更好的页面效果,但是时间有限。我后期有时间再优化,虽然毕业设计过了,但是作为本人大学四年写的代码量最多的项目,还是有必要后期不断优化的。
项目目前已升级,技术栈采用:Springboot+mybatis+Springsecurity+redis+elasticsearch 学习一个框架其实是一件挺困难的事情,但是后期开发用的多了,自然就熟练和掌握了,不讲了,直接上项目。
1. 开发环境搭建
1.1 项目中用到的技术
Springboot2+mybatis+Springsecurity+thymeleaf+redis+elasticsearch+layuimini
1.2 项目结构
2.项目展示
2.1 网站的首页
页面我个人觉得还是好看的,作为一个Java后端开发人员,学习点前端知识还是很有必要的,Java开发人员不要求深入了解前端内容,但是前端基础内容是很多公司都要求的必需会的。菜单导航栏用的是bootstrap的导航组件,轮播图也是bootstrap的轮播组件,随便看一下官网的文档就可以做出来了,感兴趣的朋友可以自学一下,学过html和css基础很快就可以做出来的。
2.2 登录和注册功能
登录功能采用Springsecurity进行登录和鉴权,前端发送ajax请求到后端,后端主要通过实现UsernamePasswordAuthenticationFilter接口实现自己的登录逻辑,这里结合了验证码校验逻辑。基本代码如下:
package com.example.music.filter;
import com.alibaba.fastjson.JSON;
import com.example.music.common.enums.ResultEnum;
import com.example.music.common.enums.ValidateCodeEnum;
import com.example.music.common.exception.ValidateCodeException;
import com.example.music.common.utlis.CommonResult;
import com.example.music.dto.AuthenticationRequest;
import com.example.music.dto.ImageCode;
import com.example.music.dto.MyUserDetails;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.thymeleaf.util.StringUtils;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
/**
* @author: guojm
* @date: 2021/12/17 7:59
* @description: 处理用户登录的过滤器
*/
public class LoginAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
// 用户登录认证管理器
private AuthenticationManager authenticationManager;
public LoginAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
// 后端登录接口
super.setFilterProcessesUrl("/login");
}
/**
* 执行验证的过程的方法
* @param request
* @param response
* @return
* @throws AuthenticationException
*/
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
AuthenticationRequest loginUser = null;
try {
// 从输入流中获取到登录的信息
loginUser = new ObjectMapper().readValue(request.getInputStream(), AuthenticationRequest.class);
} catch (IOException e) {
e.printStackTrace();
}
// 先校验验证码是否正确
validateCode(request,loginUser.getImageCode());
// 再进行用户名和密码认证
Authentication authenticate = authenticationManager.authenticate(
new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword(), new ArrayList<>())
);
return authenticate;
}
/**
* 登录验证成功时候调用的方法
* @param request
* @param response
* @param chain
* @param authResult
* @throws IOException
* @throws ServletException
*/
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
FilterChain chain, Authentication authResult) throws IOException, ServletException {
MyUserDetails userDetails = (MyUserDetails) authResult.getPrincipal();
response.setContentType("application/json;charset=UTF-8");
//使用session保存用户信息
HttpSession session = request.getSession();
session.setAttribute("user",userDetails);
response.getWriter().write(JSON.toJSONString(new CommonResult(ResultEnum.SUCCESS,"登录成功")));
}
/**
* 登录验证失败时候调用的方法
* @param request
* @param response
* @param failed
* @throws IOException
* @throws ServletException
*/
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
response.setContentType("application/json;charset=UTF-8");
// 用户验证码校验失败
if(failed instanceof ValidateCodeException){
response.getWriter().write(JSON.toJSONString(new CommonResult(ResultEnum.VALIDATE_CODE_ERROR,failed.getMessage())));
}
// 用户名或者密码输入错误
else if (failed instanceof BadCredentialsException) {
response.getWriter().write(JSON.toJSONString(new CommonResult(ResultEnum.USER_LOGIN_FAILED,ResultEnum.USER_LOGIN_FAILED.getMessage())));
}
// 账户已经被禁用
else if(failed instanceof DisabledException){
response.getWriter().write(JSON.toJSONString(new CommonResult(ResultEnum.USER_IS_DISABLED,ResultEnum.USER_IS_DISABLED.getMessage())));
}
}
/**
* 验证码的校验方法
* @param request
* @param requestImageCode
*/
private void validateCode(HttpServletRequest request,String requestImageCode) {
// 获取存放到session中的验证码
ImageCode imageCode = (ImageCode) request.getSession().getAttribute(ValidateCodeEnum.VALIDATE_CODE_SESSION_KEY.getValue());
// 判断输入的验证码是否为空
if(StringUtils.isEmpty(requestImageCode)){
throw new ValidateCodeException(ValidateCodeEnum.VALIDATE_CODE_EMPTY);
}
// 判断session中保存的验证码是否为空
if(imageCode == null){
throw new ValidateCodeException(ValidateCodeEnum.VALIDATE_CODE_REQUEST);
}
// 判断session中保存的验证码是否过期
if(imageCode.isExpried()){
request.getSession().removeAttribute(ValidateCodeEnum.VALIDATE_CODE_SESSION_KEY.getValue());
throw new ValidateCodeException(ValidateCodeEnum.VALIDATE_CODE_EXPIRED);
}
// 判断session中保存的验证码和用户输入的验证码是否一致
if(!StringUtils.equalsIgnoreCase(imageCode.getCode(),requestImageCode)){
throw new ValidateCodeException(ValidateCodeEnum.VALIDATE_CODE_ERROR);
}
}
}
2.3 榜单页面
2.4 歌手页面
2.5 专辑页面
2.6 MV页面和MV播放页面
mv播放采用的是video.js视频播放插件,很好用的一个插件,mv播放页面支持对mv进行评论的功能。
2.7 音乐播放器界面
我自己写的一个h5的音乐播放器,利用h5的<audio>音频标签实现歌曲播放很简单。我刚开始的时候想在网上找一个开源的音乐播放器,发现都没有自己喜欢的,所以我决定自己开发。我刚开始没有思路,后面在网上慢慢找资料学习和对比现在主流音乐网站的音乐播放器的功能,就自己开发出来了。播放器支持歌曲列表的操作,如移除指定歌曲、清空歌曲列表、点击歌曲进行播放等;歌曲支持点击进度条和拖动按钮实现快进和快退操作,歌曲支持简单的行匹配效果,歌词支持动画平滑滚动效果;歌手的图片会根据后台上传的歌手图片中查找出来显示,带点图片感觉比较好看一点。
2.8 后台登陆界面和后台主页
后台登陆界面也是自己设计的,重点是好看哈哈。。慢慢的我发现了设计页面的窍门,背景很重要,背景随便找张色彩丰富的图片利用ps进行高斯模糊效果,就很好看了。这个登陆界面做过项目以来设计的最好看的登陆界面,感觉进入这个界面是不是很想登陆看看什么效果。。
2.9 用户管理
用户管理支持用户查询、编辑、删除、添加等操作。
2.10 权限管理
权限管理采用简单的RBAC权限模型,RBAC是(Role-BasedAccess Control)的英文缩写,意思是基于角色的访问控制。这里分为角色管理和权限管理两个模块,后续更细的权限管理还可以自行扩展。在Springsecurity中我们可以自定义一个判断用户的角色对某资源(接口)是否有权限访问的类,在WebSecurityConfigurerAdapter的configure方法中配置即可。
package com.jm.jwt.auth.security;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
/**
* @author: gjm
* @date: 2021/1/23
*/
@Component("myAuthorityService")
public class RBACAuthorityService {
@Value("${server.servlet.context-path}")
private String contextPath;
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
//获取用户名称
Object username = authentication.getPrincipal();
//获取资源
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
Iterator<? extends GrantedAuthority> iterator = authorities.iterator();
boolean hasPermission = false;
if (username != null) {
while(iterator.hasNext()){
GrantedAuthority authority = iterator.next();
String role = authority.getAuthority();
//这里对指定角色ROLE_ADMIN能访问的url进行配置
if(role.equals("ROLE_ADMIN")){
Set<String> urls = new HashSet();
// 这些url都是ROLE_ADMIN角色登录后所能访问的,可以从数据库中动态查询
urls.add(contextPath+"/user/**");
urls.add(contextPath+"/power/**");
urls.add(contextPath+"/role/**");
urls.add(contextPath+"/powerRoleRef/**");
urls.add(contextPath+"/userRoleRef/**");
AntPathMatcher antPathMatcher = new AntPathMatcher();
//获取当前请求的uri
String requestURI = request.getRequestURI();
//判断当前请求的uri是否被允许访问
for (String url : urls) {
if (antPathMatcher.match(url,requestURI)) {
hasPermission = true;
break;
}
}
}
}
} else {
return false;
}
return hasPermission;
}
}
2.11 歌手管理
后台管理的功能基本都是比较简单CRUD,我们很容易上手,在学习中不断思考和优化我们的代码才是项目的本质,就是一句话,熟能生巧,后面拿来直接用即可。
以上就是项目中的一部分功能模块,项目代码量我觉得够多了。开发这个项目以前是为了毕业设计一顿乱整,现在更多的是学习和使用技术,不懂得地方就去学习,检验你学习成果的最好依据就是你的成品。