项目具有下面几个亮点:
首先是将 Session 存储到了 Redis 中,实现了 Session 的共享,使得其在分布式环境下可以使用。
然后我对密码进行了一个加盐加密操作,保证了密码的安全性。
我使用 Redis 实现了点赞功能,因为 Redis 的写入和读取速度非常快,很适合点赞这种高频率操作。
然后就是我对博客展示列表页面增加了一个分页功能。
目前就是我项目的介绍,老师您如果您有哪些想详细了解的可以指出来。
MD5密码是一种数字摘要算法,它可以将任意长度的字符串转换成一个128位的散列值,也就是一个16字节的数字。
为什么要使用加盐加密呢? 首先如果只是单纯使用 MD5 加密,由于 MD5 加密每次生成的值都是相同的,很容易通过暴力枚举的方式进行破解。而加盐加密通过生成随机 32 位盐值,每次生成的密码都是不同的,增加密码安全性。
/**
* 对密码进行加密
* @param password
* @return
*/
public static String encrypt(String password){
// 随机生成不同的 32 位的盐值
String salt = UUID.randomUUID().toString().replace("-","");//替换“-”为空
// 生成最终密码 (盐值 + 密码) 进行加密
String finalPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
return salt + finalPassword;
}
/**
* 解密验证密码正确性
* @param password 待验证的密码
* @param finalPassword 数据库中饭加密了的密码
* @return
*/
public static boolean decrypt(String password,String finalPassword){
// 获得前面 32 位的盐值
String salt = finalPassword.substring(0,32);
// 通过待验证密码 + 盐值生成最终待确认密码
String securityPassword = DigestUtils.md5DigestAsHex((salt + password).getBytes());
return finalPassword.equals(salt + securityPassword);
}
初始化当前总页面数量函数实现。
/* 初始化总页数 */
@Override
public Object initTotalPage(Integer pageSize) {
List<Blog> blogs = list();
if(blogs != null) {
// Math.ceil: 如果是 2.x 结果为 3
return (int) Math.ceil(blogs.size() * 1.0 / pageSize);
}
return 0;
}
初始化博客列表函数实现。
public List<Blog> initBlogs(Integer pageIndex, Integer pageSize){
if(pageIndex != null && pageSize != null && pageIndex > 0 && pageSize > 0) {
Integer offset = pageSize * (pageIndex - 1);
return mapper.initBlogs(pageSize,offset);
}
return null;
}
<select id="initBlogs" resultType="com.example.demo.entity.Blog">
select * from blog_info limit #{pageSize} offset #{offset}
</select>
Redis 中的点赞记录是存储在 Set 中的,每一个 Set 代表一个博客,存储的是给博客点赞过的用户 id。
而数据库中的点赞记录表如下图所示:使用了 blog_id 和 user_id 保证每条记录的唯一性。
@Transactional
public Object likeBlog(HttpServletRequest request,String likedBlogId) {
// 得到当前用户对象
User curUser = SessionUnit.getLoginUser(request);
if(curUser == null) {
return AjaxResult.fail(-1,"当前用户对象为空");
}
// 创建 Redis key: RedisKey + 博客ID
String key = RedisKeyUtils.BLOG_LIKED_KEY + likedBlogId;
// 判断当前用户是否点赞过
/* 这里返回的是一个 Boolean, 可能为空, 这样可以防止空指针异常 */
/**/
boolean liked = Boolean.TRUE.equals(stringRedisTemplate.opsForSet().isMember(key,curUser.getId().toString()));
// 如果该用户已经点赞过
if(liked) {
/* 数据库操作 */
// 点赞数量 - 1
boolean isSuccess = blogService.update().setSql("like_count = like_count - 1").eq("id",likedBlogId).update();
if(!isSuccess) {
return AjaxResult.fail(-1,"数据库更新失败");
}
// 移除数据库中该条记录
QueryWrapper<BlogLike> wrapper = new QueryWrapper<>();
wrapper.eq("blog_id",likedBlogId);
wrapper.eq("user_id",curUser.getId());
remove(wrapper);
/* Redis 操作 */
// 移除 set 中的该条记录
stringRedisTemplate.opsForSet().remove(key,curUser.getId().toString());
} else {
// 用户没有点赞过
// 点赞数量 + 1
boolean isSuccess = blogService.update().setSql("like_count = like_count + 1").eq("id",likedBlogId).update();
if(!isSuccess) {
return AjaxResult.fail(-1,"数据库更新失败");
}
// 新增一条点赞记录
/* 这里一直报类型错误,暂时不知道什么原因,用传统的 MyBatis 好了 */
// BlogLike blogLike = new BlogLike(Integer.valueOf(likedBlogId),curUser.getId());
// save(blogLike);
mapper.saveLike(likedBlogId,curUser.getId().toString());
/* Redis 操作 */
// 新增 set 一条记录
stringRedisTemplate.opsForSet().add(key,curUser.getId().toString());
}
return AjaxResult.success(1,"用户点赞成功");
}
功能测试:
性能测试:
界面测试:
安全性测试:
易用性测试:
兼容性测试:
如果是按照接口测试来设计的话:
前端:
修改 Axios 的路径 Url,路径记得加 http://,不然配置即使排除还是会拦截。
// axios.defaults.baseURL = "http://localhost:9090"
axios.defaults.baseURL = "Your own host + Port"
修改完前端配置后,将其打包生成 dist 文件夹:
npm run build
后端:
修改上传图片的文件路径:
// 保存头像的文件路径
// public static final String AVATAR_FILE_PATH = "D:/IDEA Project/MyProject(Github)/MyBlogSystem-III/vue/public/img/avatar/";
// Linux 中存放图片的文件路径
public static final String AVATAR_FILE_PATH = "/home/mycnblog-pplus/vue/dist/img/avatar/";
修改配置文件 application.yml 和 application.properties
修改 Redis 的库序号( database )
# Redis Configuration
spring.redis.host="Your own host"
spring.redis.password="Your own password"
spring.redis.port=6379
spring.redis.database=4
spring.redis.timeout=1800000
spring.redis.lettuce.pool.max-active=20
spring.redis.lettuce.pool.max-wait=-1
spring.redis.lettuce.pool.max-idle=5
spring.redis.lettuce.pool.min-idle=0
修改 MySQL 的密码,如果没有密码则设置为空:
spring:
datasource:
url: jdbc:mysql://localhost:3306/mycnblog_pplus?characterEncoding=utf8&useSSL=false
username: root
#如果要部署到云服务器这里密码要更改(没有密码则为空)
password: "Your own password"
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置数据源类型
type: com.zaxxer.hikari.HikariDataSource
修改完成后,双击 package 即可将项目打成 Jar 包
在 target 文件夹中找到已经打包好的 Jar 包
Vue 项目部署:可以看这篇博客,讲的很详细
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2
违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务