1.0 初始化项目
1.1 首先导入相关依赖
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--热部署-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--jwt依赖-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
<!--lombok 支持-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
1.2 配置相关配置文件
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/ajax?useSSL=false&serverTimezone=UTC
username: root
password: 1234
redis:
host: 127.0.0.1
port: 6379
lettuce:
pool:
max-active: 8 #最大连接
max-idle: 8 #最大空闲连接
min-idle: 0 #最小空闲连接
max-wait: 100ms #连接等待时间
mybatis:
type-aliases-package: com.pojo # 别名
mapper-locations: classpath:/mapper/*.xml # xml文件
configuration:
map-underscore-to-camel-case: true #驼峰命名
lazy-loading-enabled: true #延迟加载
1.3 调试redis是否可用
// 写入一条String数据
redisTemplate.opsForValue().set("name", "杀掉巴嘎");
// 获取string数据
Object name = redisTemplate.opsForValue().get("name");
System.out.println("name = " + name);
System.out.println(user);
保存的数据可读性差进行序列化后解决
添加序列化存储对象代码
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory){
// 创建RedisTemplate对象
RedisTemplate<String, Object> template = new RedisTemplate<>();
// 设置连接工厂
template.setConnectionFactory(connectionFactory);
// 创建JSON序列化工具
GenericJackson2JsonRedisSerializer jsonRedisSerializer =
new GenericJackson2JsonRedisSerializer();
// 设置Key的序列化
template.setKeySerializer(RedisSerializer.string());
template.setHashKeySerializer(RedisSerializer.string());
// 设置Value的序列化
template.setValueSerializer(jsonRedisSerializer);
template.setHashValueSerializer(jsonRedisSerializer);
// 返回
return template;
}
}
解决后
统一返回类
/**
* 返回统一类
* @param <T>
*/
@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ResponseResult<T> {
/**
* 状态码
*/
private Integer code;
/**
* 提示信息,如果有错误时,前端可以获取该字段进行提示
*/
private String msg;
/**
* 查询到的结果数据,
*/
private T data;
public ResponseResult(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public ResponseResult(Integer code, T data) {
this.code = code;
this.data = data;
}
public ResponseResult(Integer code, String msg, T data) {
this.code = code;
this.msg = msg;
this.data = data;
}
}
登录代码
@Override
public ResponseResult login(@Valid User user) {
User user1 = userMapper.selectUserByName(user.getUsername());
String userId = String.valueOf(user.getId());
//生成token
String jwt = JwtUtil.createJWT(userId);
Map<String,String> map = new HashMap<>();
map.put("token",jwt);
//用户名密码正确
if(user.getPassword().equals(user1.getPassword())){
redisCache.setCacheObject("login"+userId,user1);
return new ResponseResult(200,"登陆成功",map);
}
return new ResponseResult(200,"用户名或密码错误");
}
拦截器代码
@AllArgsConstructor
public class UserLoginInterceptor implements HandlerInterceptor {
private RedisCache redisCache;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
//获取token
String token = request.getHeader("token");
if (!StringUtils.hasText(token)) {
//放行
return false;
}
String userId;
try {
Claims claims = JwtUtil.parseJWT(token);
userId = claims.getSubject();
}catch (Exception e){
e.printStackTrace();
throw new RuntimeException("token非法");
}
//从redis中获取用户信息
String redisKey = "login" + userId;
User loginUser = redisCache.getCacheObject(redisKey);
if(Objects.isNull(loginUser)){
throw new RuntimeException("用户未登录");
}
return true;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
}
}
注册拦截器的代码
@Configuration
public class LoginConfig implements WebMvcConfigurer {
@Autowired
RedisCache redisCache;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration loginIntercept = registry.addInterceptor(new UserLoginInterceptor(redisCache));
loginIntercept.addPathPatterns("/**")
.excludePathPatterns("/user/login", //不被拦截的对象
"/user/register",
"/**/*.html", //html静态资源
"/**/*.js", //js静态资源
"/**/*.css" //css静态资源
);
}
}
写controller、service、mapper,mapper.xml层代码根据username和password查询
出现错误1
经过一系列排查,找到原因,未配置mybatis相关配置信息
mybatis:
type-aliases-package: fei.entity.pojo # 别名
mapper-locations: classpath:/mapper/*.xml # xml文件
configuration:
map-underscore-to-camel-case: true #驼峰命名
lazy-loading-enabled: true #延迟加载
出现的错误2
实现拦截器的时候写的redis工具类一直报null,出现空指针异常如下
解决方案
原因是拦截器的加载在springcontext之前,所以自动注入redis工具类是null。
但是在WebMvcConfigurer可以注入成功,然后通过构造器进行注入
拦截器注册器中注入,通过构造方法
增加拦截器构造方法,将redis工具类当作属性注入
下一次写,异常处理,返回给前端的异常进行封装