基于b站springboot3+vue3的项目学习
获取用户详细信息
1根据用户名查询用户
1.实现思路
因为url路径中的请求参数为控制,因此需要从登录功能中封装的token解析用户名
- 第一步是使用@Request Header主键,将token添加到方法参数中
- 调用jwt工具类的parsetoken,此方法会按照设置好的key进行反向解析,将信息封装到Map类型中
- 调用get获取username
- 最后调用service层中的findbyusername方法
- 完成
2.优化思路
解决代码复用性高的问题 - 使用Threadlocal工具类
- 在拦截器中进行令牌验证时,验证token后
- 调用threadlocal的set方法储存 对象值claims
- 在controller中调用thread local的get方法
Map<String,Object> map = ThreadLocalUtil.get();
String username = (String)map.get("username");
3.解释一下Threadlocal
- 我的理解:是一个工具,为一个用户分配一个线程,只要用户的状态允许,我们就可以在任何地方通过线程获取用户的信
- 下面是gpt的解释:
– ThreadLocal 是 Java 中的一个工具类,它提供了线程局部变量的功能。简单来说,ThreadLocal 允许您在每个线程中存储和获取独立的变量,而不会与其他线程的变量产生冲突。
以下是 ThreadLocal 的一些关键特点和用法:
独立存储: 每个线程都有自己的变量副本,线程之间互不影响。
线程隔离: 可以将数据与线程关联起来,使得数据在整个线程生命周期内可用,但不会被其他线程访问。
线程安全: ThreadLocal 内部使用了线程封闭技术,确保了数据的线程安全性。
简化线程共享: 适用于需要在多个方法或类中传递数据,但又不想使用方法参数传递的情况。
避免传递参数: 可以避免将上下文数据作为方法参数传递,从而简化代码,提高可读性和可维护性。
完成这个共呢个遇见的bug
1.jwt依赖版本过低问题,会导致工具类中的方法失效
2.最2b的bug,重新获取token,因为拦截器的excludePathPatterns(“/user/login”,“/user/register”);
路径设置错误,导致登录页面也被拦截
2更新用户基本信息
基本信息更新
1.controller层调用service的update方法,在impl实现方法的具体业务逻辑
2.调用持久层mapper的update方法,添加@Update注解,完成
3.实体参数的校验
- 在实体类的成员变量中添加注解
– @Notnull
– @NotEmpty
– Email
@NotNull
private Integer id;//主键ID
private String username;//用户名
@JsonIgnore
private String password;//密码
@NotEmpty
@Pattern(regexp = "^\\S{1,10}$")
private String nickname;//昵称
@NotEmpty
@Email
private String email;//邮箱
- 在controller接口方法上添加@Validated注解
更新头像
主要注意的是参数限制,使用@URL注解验证url地址是否正确
修改密码
@RequestBody注解 将前端传过来的json转换为map类型
- 校验参数
String oldPwd = params.get("old_pwd");
String newPwd = params.get("new_pwd");
String re = params.get("re_pwd");
if(!StringUtils.hasLength(oldPwd)||!StringUtils.hasLength(newPwd)||!StringUtils.hasLength(re)){
return Result.error("缺少必要的参数");
}
//调用userService根据用户名拿到原密码,再和oldpwd比对
Map<String,Object> map = ThreadLocalUtil.get();
String username = (String)map.get("username");
User loginuser = userService.findByUserName(username);
if(!loginuser.getPassword().equals(Md5Util.getMD5String(oldPwd))){
return Result.error("原密码填写不正确");
}
- 调用service的updatePwd方法
- 最后调用mapper的updatePwd方法,写入update sql语句完成
文章分类
新增文章分类
很重要的一个点,进行参数校验
因为前端给的json数据只有两个,所以其他的参数需要在impl层中手动添加
category.setCreateTime(LocalDateTime.now());
category.setUpdateTime(LocalDateTime.now());
Map<String,Object> map = ThreadLocalUtil.get();
Integer id = (Integer) map.get("id");
category.setCreateUser(id);
// 因为id在前端中也没有要求
// 所以在impl中添加
mapper层代码
/**
* 添加图书分类
* @param category
*/
@Insert("insert into category(category_name, category_alias, create_user, create_time, update_time)"+
"values (#{categoryName},#{categoryAlias},#{createUser},#{createTime},#{updateTime})")
void add(Category category);
文章分类列表
- 请求路径:当请求路径相同时,可以根据请求类型来进行分类
- 响应结果:因为查看的结果是一个列表,所有Result的类型是一个Category类型的list集合
public Result<List<Category>> list()
获取文章分类详情
更新文章分类
一个重点,定义分组,区分校验参数
- 在实体类内部定义接口
- 通过groups属性指定
- 给@Validated注解的value属性赋值
- 默认属于default分组
删除文章分类
文章相关接口
对草稿设置自定义注解
- 自定义注解State
- 自定义校验数据的类StateValidation
- 在需要校验的地方使用自定义注解
eg:
1.自定义注解State
@Documented//元注解
@Constraint(validatedBy = {Statevalidation.class})//指定需要检验规则的类
@Target({ElementType.FIELD,})
@Retention(RUNTIME)
public @interface State {
//提供校验失败后的提示信息
String message() default "{state参数的值只能是已发布或草稿}";
//指定分组
Class<?>[] groups() default {};
//负载 获取到State注解的附加信息
Class<? extends Payload>[] payload() default {};
}
2.自定义校验数据的类StateValidation
public class Statevalidation implements ConstraintValidator<State,String> {
@Override
public boolean isValid(String s, ConstraintValidatorContext constraintValidatorContext) {
//提供校验规则
if(s == null){
return false;
}
if(s.equals("已发布")||s.equals("草稿")){
return true;
}
return false;
}
}
增
删
改
查
使用pagehelper插件完成
1.对反回结果的类型处理
public Result<PageBean<Article>> list()
2.充分封装一个类pagebean,有两个变量total总条数 和 items数据集合,这个类的泛型是一个文章类
3.在serviceImpl中开启分页查询
//创建pageBean对象
PageBean<Article> pb = new PageBean<>();
//开启分页查
PageHelper.startPage(pageNum,pageSize);
//查询当前用户id
Map<String,Object> map = ThreadLocalUtil.get();
Integer userId = (Integer) map.get("id");
//调用mapper
List<Article> as = articleMapper.list(userId,categoryId,state);
Page<Article> p = (Page<Article>) as;
//把数据填充到PageBean对象中
pb.setTotal(p.getTotal());
pb.setItems(p.getResult());
return pb;