11.26_黑马Redis实战篇短信登录笔记

实战篇2

bug1 如何让这行东西竖着展示出来啊?

11.26_黑马Redis实战篇短信登录笔记_第1张图片

11.26_黑马Redis实战篇短信登录笔记_第2张图片

解决方案:

将此文件复制到idea的文件目录下,再在idea中打开它。

11.26_黑马Redis实战篇短信登录笔记_第3张图片

11.26_黑马Redis实战篇短信登录笔记_第4张图片

11.26_黑马Redis实战篇短信登录笔记_第5张图片

11.26_黑马Redis实战篇短信登录笔记_第6张图片

更改数据库的密码 以及我的redis当时是没有设置密码的 也要进行改动

bug2  在导入sql文件的时候,出现了权限的问题。我试了很久,最后决定卸载mysql,重新安装MySQL即可。11.26_黑马Redis实战篇短信登录笔记_第7张图片

注意点:

我是直接在D盘删除mysql文件夹,应该是清理不到位的。

因此,在安装mysql的时候,要注意几个方面:

针对拒绝访问这个问题:一定要在管理员身份下打开cmd.

针对系统找不到指定的文件这个问题:除了要检查高级设置里的配置环境外,要将下载的mysql下载回原来mysql的位置。eg:我原来的mysql下载在D盘,那我重新安装mysql的时候就要放在D盘。

其余的跟着黑马的JAVAWEB2023下载mysql即可以。

bug3 重新安装mysql后,在导入sql文件的时候,出现了database selected问题。

解决方案:

1、检查database的密码和用户是否正确

11.26_黑马Redis实战篇短信登录笔记_第8张图片

2、记住database的名称,这里叫作hmdp。所以创建的时候也要是hmdp

11.26_黑马Redis实战篇短信登录笔记_第9张图片

11.26_黑马Redis实战篇短信登录笔记_第10张图片

11.26_黑马Redis实战篇短信登录笔记_第11张图片

11.26_黑马Redis实战篇短信登录笔记_第12张图片

然后在相对应的控制台将sql文件复制黏贴执行就可以啦。

实战篇3

11.26_黑马Redis实战篇短信登录笔记_第13张图片

11.26_黑马Redis实战篇短信登录笔记_第14张图片

实战篇5

11.26_黑马Redis实战篇短信登录笔记_第15张图片

细节:反向编码,避免层层嵌套的编码方式,使代码更加清晰。

@Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {

        //1,校验手机号
        String phone = loginForm.getPhone();
        if (RegexUtils.isPhoneInvalid(phone)) {
            //2.如果不符合,返回错误信息
            return Result.fail("手机格式错误!");
        }
        //2,校验验证码
        Object cacheCode = session.getAttribute("code");
        String code = loginForm.getCode();
        if (cacheCode == null || !cacheCode.toString().equals(code)) {
            //3,不一致,报错
            return Result.fail("校验码错误");
        }
        //4,一致,根据手机号查询用户
        User user = query().eq("phone", phone).one();
        //5,判断用户是否存在
        if (user == null) {
            //6,不存在,创建新用户并保存
            user = createUserWithPhone(phone);
        }
        //7,保存用户信息到session
        session.setAttribute("user", user);
        return Result.ok();
    }
    private  User createUserWithPhone(String phone){
        User user = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
        save(user);
        return null;
    }

实战篇6

一次性拦截,不用每次访问controller都要拦截一次

11.26_黑马Redis实战篇短信登录笔记_第16张图片

package com.hmdp.utils;

import com.hmdp.dto.UserDTO;
import org.springframework.web.servlet.HandlerInterceptor;

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

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1,获取session
        HttpSession session =request.getSession();
        //2,获取session中的用户
        Object user = session.getAttribute("user");
        //3,判断用户是否存在
        if(user == null){
            //4,不存在,拦截,返回401状态码
            response.setStatus(401);
            return false;
        }
        //5,存在,保存用户信息到ThreadLocal
        UserHolder.saveUser((UserDTO) user);
        //6,放行
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //移除用户
        UserHolder.removeUser();
    }
}
package com.hmdp.config;

import com.hmdp.utils.LoginInterceptor;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class MvcConfig implements WebMvcConfigurer {

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

细节: 

1,alt +insert  可以快捷生成方法

2,长按ctrl 选择两个以上的东西

3,@Configuration用于定义配置类

实战篇7

因为返回完整的用户信息,容易产生敏感信息泄露的问题,因此得解决它。

再做一个UserDTO来封装信息。

//7,保存用户信息到session
        session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));
        return Result.ok();

细节:

1,User是个类名,User.class会得到一个Class(字节码对象)类型的对象,这个对象包含这个类的所有属性

实战篇8

11.26_黑马Redis实战篇短信登录笔记_第17张图片

实战篇9

以手机号码为key获取验证码

以token为key用于访问页面,用token而不用手机号码可以减少隐私泄露的风险。

后端要将token返回给前端

采用Hash结构,有利于修改信息,也可以减少存储的内容(比如存储的格式)

11.26_黑马Redis实战篇短信登录笔记_第18张图片

11.26_黑马Redis实战篇短信登录笔记_第19张图片

实战篇10

  @autowired与@resource的区别是什么?

@resource

11.26_黑马Redis实战篇短信登录笔记_第20张图片

11.26_黑马Redis实战篇短信登录笔记_第21张图片

因此,现在是会报错的。

所以解决方案有:

1、删除一个myservice

2、写清楚到底是注入哪一个名称。比如它这里写清楚是注入没有serviceimpl0111.26_黑马Redis实战篇短信登录笔记_第22张图片

@autowired

11.26_黑马Redis实战篇短信登录笔记_第23张图片

解决方案:

1,加上@primary11.26_黑马Redis实战篇短信登录笔记_第24张图片

2,加上@Qualifier

11.26_黑马Redis实战篇短信登录笔记_第25张图片

3,删除service,只保留一个service

来源视频面试:@Resource和@Autowired区别?_哔哩哔哩_bilibili

细节:

1,设置过期时间:expire 

eg:stringRedisTemplate.expire("baike",1000 , TimeUnit.MILLISECONDS);

2,当项目中有许多JAVA类,想快速找到想要的JAVA类,则按Ctrl + E 可以出现选择框选择。

public class LoginInterceptor implements HandlerInterceptor {

    private StringRedisTemplate stringRedisTemplate;

    public LoginInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1,获取请求头中的token
        String token = request.getHeader("authorization");
       if(StrUtil.isBlank(token)) {
           response.setStatus(401);
           return false;
       }
        //2,基于token获取redis中的用户
        String key = RedisConstants.LOGIN_USER_KEY + token;
        Map userMap = stringRedisTemplate.opsForHash().entries(key);
        //3,判断用户是否存在
        if(userMap.isEmpty()){
            //4,不存在,拦截,返回401状态码
            response.setStatus(401);
            return false;
        }
        //5,将查询到的Hash数据转为UserDTO对象
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
        //6,存在,保存用户信息到ThreadLocal
        UserHolder.saveUser(userDTO);
        //7,刷新token有效期
        stringRedisTemplate.expire(key,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
        //8,放行
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        //移除用户
        UserHolder.removeUser();
    }
}
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl implements IUserService {
    //注入redis的配置
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public Result sendcode(String phone, HttpSession session) {
        //1.校验手机号
        if(RegexUtils.isPhoneInvalid(phone)){
            //2.如果不符合,返回错误信息
            return Result.fail("手机格式错误!");
        }
        //3.符合,生成验证码
        String code = RandomUtil.randomNumbers(6);
        //4.保存验证码到redis
        stringRedisTemplate.opsForValue().set(LOGIN_CODE_KEY+phone,code,LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //5.发送验证码
        log.info("发送短信验证码成功,验证码:{}",code);
        //返回ok
        return Result.ok();
    }

    @Override
    public Result login(LoginFormDTO loginForm, HttpSession session) {

        //1,校验手机号
        String phone = loginForm.getPhone();
        if (RegexUtils.isPhoneInvalid(phone)) {
            //2.如果不符合,返回错误信息
            return Result.fail("手机格式错误!");
        }
        //3,从redis获取验证码并校验
        String cacheCode = stringRedisTemplate.opsForValue().get(LOGIN_CODE_KEY + phone);
        String code = loginForm.getCode();
        if (cacheCode == null || !cacheCode.toString().equals(code)) {
            //不一致,报错
            return Result.fail("校验码错误");
        }
        //4,一致,根据手机号查询用户
        User user = query().eq("phone", phone).one();
        //5,判断用户是否存在
        if (user == null) {
            //6,不存在,创建新用户并保存
            user = createUserWithPhone(phone);
        }
        //7,保存用户信息到redis
        //7.1 随机生成token,作为登陆令牌
        String token = UUID.randomUUID().toString();
        //7.2 将User对象转为HashMap存储
        UserDTO userDTO = BeanUtil.copyProperties(user, UserDTO.class);
        Map userMap = BeanUtil.beanToMap(userDTO,new HashMap<>(),
                CopyOptions.create()
                        .setIgnoreNullValue(true)
                        .setFieldValueEditor((fieldName,fieldvalue)->fieldvalue.toString()));
        //7.3存储
        String tokenKey = LOGIN_USER_KEY + token;
        stringRedisTemplate.opsForHash().putAll(tokenKey,userMap);
        //7.4 设置token有效期
        stringRedisTemplate.expire(tokenKey,LOGIN_USER_TTL,TimeUnit.MINUTES);
        //8 返回token
        return Result.ok();
    }
    private  User createUserWithPhone(String phone){
        User user = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
        save(user);
        return null;
    }
}

11.26_黑马Redis实战篇短信登录笔记_第26张图片 实战篇11

一些小问题:如果只有原先的一个拦截器的话,它只会拦截需要登录的路径,对于不需要登录的路径它不拦截。这就会导致如果用户没有登陆就访问页面的话,那三十分钟后token不会自动刷新,那就会造成token失效,不合理。

11.26_黑马Redis实战篇短信登录笔记_第27张图片

public class LoginInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1,判断是否需要拦截(ThreadLocal中是否有用户)
        if (UserHolder.getUser() == null) {
            // 没有,需要拦截,设置状态码
            response.setStatus(401);
            //拦截
            return false;
        }
        //由用户,则放行
        return true;
    }
}
public class RefreshTokenInterceptor implements HandlerInterceptor {

    private StringRedisTemplate stringRedisTemplate;

    public RefreshTokenInterceptor(StringRedisTemplate stringRedisTemplate) {
        this.stringRedisTemplate = stringRedisTemplate;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //1,获取请求头中的token
        String token = request.getHeader("authorization");
       if(StrUtil.isBlank(token)) {
           return true;
       }
        //2,基于token获取redis中的用户
        String key = LOGIN_USER_KEY + token;
        Map userMap = stringRedisTemplate.opsForHash().entries(key);
        //3,判断用户是否存在
        if(userMap.isEmpty()){
            return true;
        }
        //5,将查询到的Hash数据转为UserDTO对象
        UserDTO userDTO = BeanUtil.fillBeanWithMap(userMap, new UserDTO(), false);
        //6,存在,保存用户信息到ThreadLocal
        UserHolder.saveUser(userDTO);
        //7,刷新token有效期
        stringRedisTemplate.expire(key,RedisConstants.LOGIN_USER_TTL, TimeUnit.MINUTES);
        //8,放行
        return true;
    }

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

 注意点:

1,

11.26_黑马Redis实战篇短信登录笔记_第28张图片

2,  order:0先执行,1后执行 

你可能感兴趣的:(redis,java,笔记)