自定义校验
首先创建一个注解(之前只用到了创建类和接口第一次发现还可以创建注解)
@Documented
@Constraint(validatedBy = {StateValidation.class})//知道提供校验规则的类
@Target({ ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface State {
String message() default "state参数的值只能说已发布或者草稿";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
创建这个注解还是挺简单的,直接把java自带的接口打开,然后把这几个复制下来就行,主要修改的就是message,就是不符合时的报错信息
然后再把提供校验的类写上去就可以,接下来就是要创建校验类
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;
}
}
校验类也是很简单的,只需要继承一个校验类接口,在接口后面写上两个参数,第一个参数是刚才写好的注解名,然后后一个是需要参数校验的参数类型,
下面就是重写一个isValid函数就可以了,s就是要校验的参数值,剩下的就是判断就行。
最后就是使用注解即可
这种注解的意思就是可传可不传,不是必须的,要是不写这个的话,如果不传就会报错
@RequestParam(required = false) Integer categoryId
条件分页
请求参数说明:
参数名称 | 说明 | 类型 | 是否必须 | 备注 | |
---|---|---|---|---|---|
pageNum | 当前页码 | number | 是 | ||
pageSize | 每页条数 | number | 是 | ||
categoryId | 文章分类ID | number | 否 | ||
state | 发布状态 | string | 否 | 已发布 | 草稿 |
响应数据说明:
{ "code": 0, "message": "操作成功", "data": { "total": 1, "items": [ { "id": 5, "title": "陕西旅游攻略", "content": "兵马俑,华清池,法门寺,华山...爱去哪去哪...", "coverImg": "https://big-event-gwd.oss-cn-beijing.aliyuncs.com/9bf1cf5b-1420-4c1b-91ad-e0f4631cbed4.png", "state": "草稿", "categoryId": 2, "createTime": "2023-09-03 11:55:30", "updateTime": "2023-09-03 11:55:30" } ] } }
这个我觉得是比较重要的,之前做小组团队项目的时候,我负责前端,想要的数据其实大多数都是这种,我觉得是比较常见的
首先要有一个pageBean的类,自动分页,还挺方便的
//分页返回结果对象
@Data
@NoArgsConstructor
@AllArgsConstructor
public class PageBean <T>{
private Long total;//总条数
private List<T> items;//当前页数据集合
}
controller层还挺简单的,只需要生成一个对象传递即可
@GetMapping
public Result<PageBean<Article>> list(
Integer pageNum ,Integer pageSize,@RequestParam(required = false) Integer categoryId,
@RequestParam(required = false) String state){
PageBean<Article> pb= articleService.list(pageNum,pageSize,categoryId,state);
return Result.success(pb);
}
然后是service层,觉得没有可以理解的,直接记忆就好,mapper层返回的list对象,直接强转为page,然后再把page里的填充到pageBean中
@Override
public PageBean<Article> list(Integer pageNum, Integer pageSize, Integer categoryId,
String state) {
//创建pageBean对象
PageBean<Article> pb =new PageBean<>();
//2.开启分页查询
PageHelper.startPage(pageNum,pageSize);
//3.调用mapper
Map <String,Object> map=ThreadLocalUtil.get();
Integer id=(Integer) map.get("id");
List<Article> as= articleMapper.list(categoryId,state,id);
//page中提供了方法,可以获取PageHelper分页查询后,得到的消息记录条数和当页数据
Page<Article> p =(Page<Article>) as;
//把数据填充到pageBean对象中
pb.setTotal(p.getTotal());
pb.setItems(p.getResult());
return pb;
}
mapper层由于有两个不确定是否有的参数,所以需要再resource中新建一个与mapper相同位置的包
记得包中间用 “ \ ” 分割,然后新建一个xml文件,
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.study.big_event.mapper.ArticleMapper">
<!-- 动态sql-->
<select id="list" resultType="com.study.big_event.pojo.Article">
select * from article
<where>
<if test="categoryId!=null">
category_id=#{categoryId}
</if>
<if test="state!=null">
and state=#{state}
</if>
and create_user=#{userId}
</where>
</select>
</mapper>
大概长这样,其实与之前的注解sql差不多,但是多了一个if,所以我觉得这种参数不确定的用这种方式方便一点,动态生成(确实还没想到用注解怎么写)
然后就可以愉快的使用了
redis的简单使用
之前学习的jwt会有一点问题,当我们修改密码并且重新登录后,会产生新的令牌,但是此时的旧的令牌并没有过期,这就导致新的与旧的可以同时使用,所以此时就需要redis的使用,将生成jwt进行存储,在使用的时候进行比较,相同时才可以进行操作
首先就是安装redis,因为这个视频的老师已经把安装好的软件发过来了,所有就先跳过
然后导入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
再修改配置文件
data:
redis:
host: localhost
port: 6379
然后就是简单的使用,通过StringRedisTemplate对象,使用opsForValue()函数就可以拿来使用了,类似于map
set函数就是键值对
get键就可以获取值
set还可以设置一个过期时间,时间一到自动删除
@SpringBootTest
public class RedisTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testSet(){
ValueOperations<String, String> Operations = stringRedisTemplate.opsForValue();
Operations.set("id","123");
Operations.set("username","1",15, TimeUnit.SECONDS);
}
@Test
public void testGet(){
ValueOperations<String, String> Operations = stringRedisTemplate.opsForValue();
String id = Operations.get("id");
System.out.println(id);
}
}
然后就是将redis应用到实际中,首先,在用户登录之后把token存入redis中,设置失效时长与jwtutil中失效的时长相同
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
stringStringValueOperations.set(token,token,1, TimeUnit.HOURS);
然后在登录拦截器中,拿出redis中保存的token,如果token没有了,就抛出异常
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
String redisToken=stringStringValueOperations.get(token);
if (redisToken==null){
throw new RuntimeException();
}
最后就是在修改密码之后,把当前的token在redis中给删除掉,首先想要获取token则需要@RequestHeader("Authorization") String token ,自动在请求头中获取token,然后调用 stringStringValueOperations.getOperations().delete(token);即可删除
@PatchMapping("/updatePwd")
public Result updatePwd(@RequestBody Map<String,String> params ,@RequestHeader("Authorization") String token ){
//校验参数
................................................(修改密码逻辑)
ValueOperations<String, String> stringStringValueOperations = stringRedisTemplate.opsForValue();
stringStringValueOperations.getOperations().delete(token);
return Result.success();
//调用service
}
打包springboot项目
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
首先安装这个插件,然后我看老师没有教,但是我一直在打包的时候出错,查阅了csdn,加了一行 <skipTests>true</skipTests>,就好了
<properties>
<java.version>17</java.version>
<skipTests>true</skipTests>
</properties>
然后在targrt目录下就能找到jar包了
有这个就可以成功放到服务器上了(过几天买个服务器玩玩)
小结
今天学的东西很重要,分页传递,还有redis,分页传递就是利用pageBean,自动帮助分页,但是用法要记住,list转换为page,然后page里的东西再放到pageBean中,redis就是Nosql,非关系型数据库,之前上数据库的时候老师讲过,但是一直都没有使用过,今天只掌握了简单的传入与传出和删除,应该还有很多没学到的知识,总之,今天差不多就是把后端开发的整个流程全部了解了,等会创一个vue项目,把前端也搞一下,看数据交互方面有没有问题,之前只会post和get请求,打算再深入了解一下,就这样吧,突然觉得自己学的有点太快了,三天把springboot学完了,还是改一下名字,就叫菜鸟日记吧,三天速通还是有点太过分了,肯定还是有很多的细节忘记了,没事,开个新的项目自己手搓!!