目录
完善登录功能
对前端传过来的明文密码进行md5加密处理
password = DigestUtils.md5DigestAsHex(password.getBytes());
这样既可
注册接口参数校验
Spring Validation
Spring 提供的一个参数校验框架,使用预定义的注解完成参数校验
使用Spring Validation,对注册接口的参数进行合法性校验
引入Spring Validation 起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
在参数前面添加@Pattern注解
在Controller类上添加@Validated注解
令牌主动失效机制
- 登录成功后,给浏览器响应令牌的同时,把该令牌存储到redis中
- LoginInterceptor拦截器中,需要验证浏览器携带的令牌,并同时需要获取到redis中存储的与之相同的令牌
- 当用户修改密码成功后,删除redis中存储的旧令牌
SpringBoot集成redis
导入spring-boot-starter-data-redis起步依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
在yml配置文件中,配置redis连接信息
调用APl(StringRedisTemplate)完成字符串的存取操作
package com.yjj.bigEvent;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import java.util.concurrent.TimeUnit;
@SpringBootTest
public class RedisTest {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Test
public void testSet(){
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
operations.set("username","zhangsan");
operations.set("id","1",15, TimeUnit.SECONDS);//这个设置了失效时间
}
@Test
public void testGet(){
ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
System.out.println(operations.get("username"));
System.out.println(operations.get("id"));
}
}
完善分页查询
pom.xml:
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
mapper:动态sql
<?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.sky.mapper.EmployeeMapper">
<select id="pageQuery" resultType="com.sky.entity.Employee">
select * from employee
<where>
<if test="name!=null and name!=''">
and name like concat('%',#{name},'%')
</if>
</where>
order by create_time desc
</select>
</mapper>
service:
完善日期格式
解决方式:
方式一:在属性上加入注解,对日期进行格式化
@JsonFormat(pattern ="yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
方式二:在 WebMvcConfiguration 中扩展Spring MVC的消息转换器,统一对日期类型进行格式化处理
//扩展springMvc框架的消息转化器
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
log.info("扩展消息转化器..");
//创建一个消息转化器对象
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
//需要为消息转化器设置一个对象转化器,对象转化器可以将java对象序列化为json数据
converter.setObjectMapper(new JacksonObjectMapper());
//将自己的消息转化器加入容器中
converters.add(0,converter);
}
更新文章分类和添加文章分类的分组校验
添加文章中没有传id参数
更新文章分类中传了id参数
这样运行起来就会报错
可以这样👇
package com.yjj.bigevent.Pojo;
import com.fasterxml.jackson.annotation.JsonFormat;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.groups.Default;
import lombok.Data;
import java.time.LocalDateTime;
@Data
public class Category {
@NotNull(groups = Update.class)
private Integer id;//主键ID
@NotEmpty
private String categoryName;//分类名称
@NotEmpty
private String categoryAlias;//分类别名
private Integer createUser;//创建人ID
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;//创建时间
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;//更新时间
//如果说某个校验项没有指定分组,默认属于Default分组
// 分组之间可以继承,A extends B那么A中拥有B中所有的校验项
public interface Add extends Default {
}
public interface Update extends Default{
}
}
就不会报错了
自定义校验
自定义注解State
package com.yjj.bigevent.Anno;
import com.yjj.bigevent.Validation.StateValidation;
import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
@Target({ FIELD})//元注解
@Retention(RUNTIME)//元注解
@Documented//元注解
@Constraint(validatedBy = { StateValidation.class})//指定提供校验规则的类
public @interface State {
//提供校验失败后的提示信息
String message() default "state参数的值只能是已发布或者草稿";
//指定分组
Class<?>[] groups() default { };
//负载获取到State注解的附加信息
Class<? extends Payload>[] payload() default { };
}
自定义校验数据的类StateValidation实现ConstraintValidator接口
package com.yjj.bigevent.Validation;
import com.yjj.bigevent.Anno.State;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class StateValidation implements ConstraintValidator<State,String> {
//@param value 将来要校验的数据
//@param context context in which the constraint is evaluated
//@return 如果返回false,则校验不通过,如果返回true,则校验通过
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
//提供校验规则
if (value==null) {
return false;
}
if (value.equals("已发布")||value.equals("草稿")){
return true;
}
return false;
}
}
在需要校验的地方使用自定义注解
测试
文件上传
导入阿里云的依赖坐标
pom.xml
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>3.17.4</version>
</dependency>
如果使用的是Java 9及以上的版本,则需要添加JAXB相关依赖。添加JAXB相关依赖示例代码如下:
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>
<!-- no more than 2.3.3-->
<dependency>
<groupId>org.glassfish.jaxb</groupId>
<artifactId>jaxb-runtime</artifactId>
<version>2.3.3</version>
</dependency>
工具类:
package com.yjj.bigEvent.Utils;
import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import java.io.InputStream;
public class AliOssUtil {
private static final String ENDPOINT = "https://加上访问端口(https://oss-cn-hangzhou.aliyuncs.com)";
private static final String ACCESS_KEY_ID = "ACCESS的id";
private static final String SECRET_ACCESS_KEY = "ACCESS的secret";
private static final String BUCKET_NAME = "自己的bucket名字";
//上传文件,返回文件的公网访问地址
public static String uploadFile(String objectName, InputStream inputStream){
// 创建OSSClient实例。
OSS ossClient = new OSSClientBuilder().build(ENDPOINT,ACCESS_KEY_ID,SECRET_ACCESS_KEY);
//公文访问地址
String url = "";
try {
// 创建存储空间。
ossClient.createBucket(BUCKET_NAME);
ossClient.putObject(BUCKET_NAME, objectName, inputStream);
url = "https://"+BUCKET_NAME+"."+ENDPOINT.substring(ENDPOINT.lastIndexOf("/")+1)+"/"+objectName;
} catch (OSSException oe) {
System.out.println("Caught an OSSException, which means your request made it to OSS, "
+ "but was rejected with an error response for some reason.");
System.out.println("Error Message:" + oe.getErrorMessage());
System.out.println("Error Code:" + oe.getErrorCode());
System.out.println("Request ID:" + oe.getRequestId());
System.out.println("Host ID:" + oe.getHostId());
} catch (ClientException ce) {
System.out.println("Caught an ClientException, which means the client encountered "
+ "a serious internal problem while trying to communicate with OSS, "
+ "such as not being able to access the network.");
System.out.println("Error Message:" + ce.getMessage());
} finally {
if (ossClient != null) {
ossClient.shutdown();
}
}
return url;
}
}