Redis实现分布式会话

Redis实现分布式会话

1、什么是分布式会话

1、如果非常多的人访问,因为单台服务器的访问承受能力是有限的,那么我们就想用多态服务器来承担压力

2、一般通过负载均衡的方式来实现,来分担服务器的压力。

3、负载均衡解释。

官方解释: 网络专用术语,负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。

4、解决方案。

  • session 复制,也就是当一个服务器有新的session保存的时候,通过服务器通信机制,然后将session复制到其他的服务器,如果服务器较多的话,会存在大量的网路和io占用,效率低下。

  • redis实现session共享。

2 准备条件

1、导入资料中的代码

注意修改mysql和redis的地址

访问端口:http://localhost:8081/shop-type/list 如果有数据显示,说明项目部署成功。

2、导入前端代码

3 启动代码

在nginx所在目录下打开一个CMD窗口,输入命令:start nginx

输入http://127.0.0.1:8080

3 验证码

1 redis序列化配置

package com.xinzhi.config;
​
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
​
@Configuration
public class RedisConfig {
​
    @Bean
    public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        // 创建Template
        RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
        // 设置连接工厂
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        // 设置序列化工具
        GenericJackson2JsonRedisSerializer jsonRedisSerializer = new GenericJackson2JsonRedisSerializer();
        // key和 hashKey采用 string序列化
        redisTemplate.setKeySerializer(RedisSerializer.string());
        redisTemplate.setHashKeySerializer(RedisSerializer.string());
        // value和 hashValue采用 JSON序列化
        redisTemplate.setValueSerializer(jsonRedisSerializer);
        redisTemplate.setHashValueSerializer(jsonRedisSerializer);
        return redisTemplate;
    }
}

2、controller

@PostMapping("code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        return userService.sendCode(phone, session);
 }

3、service

public interface IUserService extends IService<User> {

    Result sendCode(String phone, HttpSession session);
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @Resource
    private RedisTemplate redisTemplate;

    @Override
    public Result sendCode(String phone, HttpSession session) {
        //1 校验手机号
        if(RegexUtils.isPhoneInvalid(phone)){
        //2 如果不符合返回错误消息
            return Result.fail("手机号格式错误");
        }
        // 3 生成验证码
        String code = RandomUtil.randomNumbers(6);
        // 4 保存验证码到session
        session.setAttribute("code",code);
        // 5 发送验证码,发送短信验证大家添加
        log.debug("验证码发送成功:"+code);
        return Result.ok();
    }
}

4 登录

1 controller

 /**
     * 登录功能
     * @param loginForm 登录参数,包含手机号、验证码;或者手机号、密码
     */
    @PostMapping("/login")
    public Result login(@RequestBody LoginFormDTO loginForm,HttpSession session){
        return userService.login(loginForm,session);
    }

2 service

@Override
public Result login(LoginFormDTO loginForm, HttpSession session) {
    //1 校验手机号
    String phone = loginForm.getPhone();
    if(RegexUtils.isPhoneInvalid(phone)){
        return Result.fail("手机号码格式错误");
    }
    // 2 从session中获取code并校验
    Object cacheCode = session.getAttribute("code");
    if(cacheCode==null || !cacheCode.toString().equals(loginForm.getCode())){
        return Result.fail("验证码错误");
    }
    // 3 根据手机号查找用户
    User user = query().eq("phone", phone).one();
    // 4 用户不存在则创建用户
    if(user==null){
        user = createUserByPhone(phone);
    }
    // 5 用户保存到session
    session.setAttribute("user", user);
    return Result.ok();
}
private User createUserByPhone(String phone) {
    User user = new User();
    user.setPhone(phone);
    user.setNickName("xinzhi_" + RandomUtil.randomString(8));
    save(user);
    return user;
}

3、创建intercepter包,创建拦截器

package com.xinzhi.intercepter;

import com.xinzhi.entity.User;
import com.xinzhi.utils.UserHolder;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;


public class LoginIntercepter implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1 获取session
        HttpSession session = request.getSession();
        // 2 从session中获取user对象
        Object user = session.getAttribute("user");
        // 3 判断session中时候有对象
        if(user==null){
            // 4 不存在的话,设置401状态
            response.setStatus(401);
            return false;
        }
        //5 存在的话保存到threadlocal中
        UserHolder.saveUser((User)user);
        //6 放行
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        UserHolder.removeUser();
    }
}

4 将拦截器添加到 WebMvcConfigurer 中

package com.xinzhi.config;


import com.xinzhi.intercepter.LoginIntercepter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LoginIntercepter())
                .excludePathPatterns(
                        "/user/code",
                        "/user/login",
                        "/blog/hot",
                        "/shop-type/**",
                        "/shop/**",
                        "/upload/**",
                        "/voucher/**"
                ).order(1);
    }
}

5 user/me处理

@GetMapping("/me")
    public Result me(){
        User user = UserHolder.getUser();
        return Result.ok(user);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值