1. Redis安装与常用命令
2. Redis实现分布式Session
2.1 方法1_使用SpringSession实现
1. 添加依赖
spring data redis、对象池commons-pool2、spring-session
<!-- spring data redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- commons-pool2 对象池依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<!-- spring-session 依赖 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
2.添加配置
redis:
# 超时时间
timeout: 10000ms
# 服务器地址
host: 192.168.222.129
# 服务器端口,默认6379
port: 6379
# 数据库,默认0
database: 0
# 密码
password: root
lettuce:
pool:
#最大连接数,默认8
max-active: 1024
#最大连接阻塞等待时间,默认-1
max-wait: 10000ms
#最大空闲连接,默认8
max-idle: 200
#最小空闲连接,默认0
min-idle: 5
session将自动存储在redis
2.2 将用户信息存入Redis
1.添加依赖
<!-- spring data redis 依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- commons-pool2 对象池依赖 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
2.配置redis
同上
3.添加redis配置类
/**
* @description: Redis配置类
*/
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
//Key序列化
redisTemplate.setKeySerializer(new StringRedisSerializer());
//Value序列化
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
//Hash序列化
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
//注入连接工厂
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
}
4.修改代码
//将用户信息存入redis
// 生成cookie
String cookie = UUIDUtil.uuid();
// 将用户信息存入redis
redisTemplate.opsForValue().set("user:" + cookie, user);
// 使用session
//request.getSession().setAttribute(cookie, user);
CookieUtil.setCookie(request, response, "userCookie", cookie);
//取出redis
public User getUserByCookie(String userCookie, HttpServletRequest request, HttpServletResponse response) {
if(!StringUtils.hasLength(userCookie)){
return null;
}
User user = (User)redisTemplate.opsForValue().get("user:" + userCookie);
if(user != null){
CookieUtil.setCookie(request, response, "userCookie", userCookie);
}
return user;
}
完整代码
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Autowired
private UserMapper userMapper;
@Autowired
private RedisTemplate redisTemplate;
/**
* 登录
* @return com.example.seckill.vo.RespBean
**/
@Override
public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {
String mobile = loginVo.getMobile();
String password = loginVo.getPassword();
User user = userMapper.selectById(mobile);
if(null == user){
throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
}
if(!MD5Util.frompassToDBPass(password, user.getSalt()).equals(user.getPassword())){
throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
}
// 生成cookie
String cookie = UUIDUtil.uuid();
// 将用户信息存入redis
redisTemplate.opsForValue().set("user:" + cookie, user);
// 使用session
//request.getSession().setAttribute(cookie, user);
CookieUtil.setCookie(request, response, "userCookie", cookie);
return RespBean.success();
}
/**
* 根据Cookie获取用户
* @return com.example.seckill.pojo.User
**/
@Override
public User getUserByCookie(String userCookie, HttpServletRequest request, HttpServletResponse response) {
if(!StringUtils.hasLength(userCookie)){
return null;
}
User user = (User)redisTemplate.opsForValue().get("user:" + userCookie);
if(user != null){
CookieUtil.setCookie(request, response, "userCookie", userCookie);
}
return user;
}
}
3. 项目优化——跳转页面参数验证
定义WebConfig类实现
由于每一个接口都需要做用户校验,比较麻烦。于是加上自定义的参数校验,来定义用户参数,通过这个参数之后,在controller入参之前就做好了参数校验,判断cookie是否为空,非空的话就获取用户信息,最后传到对应的controller里面去。
WebMvcConfigurer中的addArgumentResolvers()
该方法可以用在对于Controller中方法参数传入之前对该参数进行处理。然后将处理好的参数在传给Controller中的方法。
具体的流程
- UserArgumentResolver自定义实现类
/**
* 自定义用户参数
* @ClassName: UserArgumentResolver
*/
@Component
public class UserArgumentResolver implements HandlerMethodArgumentResolver {
@Autowired
private ITUserService itUserService;
//判断类型,若controller需要的类型如下进行判断处理
@Override
public boolean supportsParameter(MethodParameter parameter) {
Class<?> parameterType = parameter.getParameterType();
return parameterType == TUser.class;
}
//如果上面为true则执行该函数
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
HttpServletRequest nativeRequest = webRequest.getNativeRequest(HttpServletRequest.class);
HttpServletResponse nativeResponse = webRequest.getNativeResponse(HttpServletResponse.class);
String userTicket = CookieUtil.getCookieValue(nativeRequest, "userTicket");
if (StringUtils.isEmpty(userTicket)) {
return null;
}
return itUserService.getUserByCookie(userTicket, nativeRequest, nativeResponse); //该方法将会返回User对象
}
}
- 实现WebConfig方法
package com.example.seckilldemo.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import java.util.List;
/**
* MVC配置类
*/
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Autowired
private UserArgumentResolver userArgumentResolver;
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(userArgumentResolver);
}
}
- Controller中的方法调用
@RequestMapping("/toList")
public String toLogin(Model model,User user) {
model.addAttribute("user", user); //这里在controller类中,且需要User,就会自动进入到参数验证,
return user==null? "login"||"goodsList";
}