黑马点评学习笔记01(手机号校验(正则表达式))

前言

首先登陆界面首先还是基于session实现(我当时也很惊讶,怎么用这个😯,结果看了目录,后面就用Redis和Jwt令牌)可能就是一个过渡吧,先用Session实现一遍,然后才能突出后面的很厉害。其实里面还是有很多小知识点的(Java正则表达式)很值得学习,这个Session实现就当小配角,陪跑🤪我们学。

先来看看概念什么是正则表达式?

对于给定的字符串进行判断,如果字符串符合我们的规则,那么就返回真,否则返回假

先来看一个简单的例子:

java 复制代码
public static void main(String[] args) {
    String str = "oooo";
  	//matches方法用于对给定正则表达式进行匹配,匹配成功返回true,否则返回false
    System.out.println(str.matches("o+"));   //+表示对前面这个字符匹配一次或多次,这里字符串是oooo,正好可以匹配
}

🧱 正则基本语法卡片(常用符号)

字符 描述
* 匹配前面的子表达式零次或多次。例如:zo*能匹配"z"以及"zoo"
+ 匹配前面的子表达式一次或多次,例如:zo+ 能匹配"zoo",但不能匹配"z"。
* 匹配前面的子表达式零次或多次。例如:zo*能匹配"z"以及"zoo"
+ 匹配前面的子表达式一次或多次,例如:zo+ 能匹配"zoo",但不能匹配"z"。
{n} 前面的字符重复n次,
{m,n} 前面的字符重复m到n次 例:\d{8,11} → 8~11个数字
^ 表示"字符串开始 例如:^abc → 必须以 abc 开头
$ 表示"字符串结束,例如:xyz$ → 必须以 xyz 结尾。
. 匹配任意一个字符 例如:a.c → 可匹配 abc、a2c
\d 匹配一个数字(0-9)例如:\d\d → 匹配两个数字
[0-9] 匹配括号内的任意一个字符,例:[aeiou] → 匹配元音字母
[a-z] 匹配一个小写字母,例:
[A-Z] 匹配一个大写字母
[3-9] 前面的字符重复m到n次

了解了正则表达式,我们来看看它在具体项目中怎么使用,先来看看实现流程图

其中涉及到了好多细小的知识点,下面我们以代码为例,慢慢展开来看:

UserController类 :

java 复制代码
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private IUserService userService;

    /**
     * 发送手机验证码
     */
    @PostMapping("code")
    public Result sendCode(@RequestParam("phone") String phone, HttpSession session) {
        // TODO 发送短信验证码并保存验证码
        return userService.sendCode(phone, session);
    }

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

IUserService 接口:

java 复制代码
package com.hmdp.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.hmdp.dto.LoginFormDTO;
import com.hmdp.dto.Result;
import com.hmdp.entity.User;

import javax.servlet.http.HttpSession;

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
public interface IUserService extends IService<User> {

    Result sendCode(String phone, HttpSession session);
    Result login(LoginFormDTO loginForm, HttpSession session);

}

IUserService 接口实现类:

java 复制代码
package com.hmdp.service.impl;

import...

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 虎哥
 * @since 2021-12-22
 */
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {

    @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.保存验证码到session
        session.setAttribute("code", code);

        //5.发送验证码
        System.out.println("发送短信验证码成功,验证码:" + code);

        //5.返回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("手机号格式错误!");
        }

        //2.校验验证码 不一致直接报错 从session中获取
        Object cachecode = session.getAttribute("code");
        String code = loginForm.getCode();
        if (cachecode == null || !cachecode.toString().equals(code)) {
            return Result.fail("验证码错误!");
        }

      

        //3.一致,根据手机号查询用户 select * from tb_user where phone = ?
        User user = query().eq("phone", phone).one();

        //4.判断用户是否存在
        if (user == null) {
            //5.不存在,创建新用户
            user = createUserWithPhone(phone);

        }

        //6.存在,保存用户信息到session
                session.setAttribute("user", BeanUtil.copyProperties(user, UserDTO.class));

        return Result.ok();
    }

    private User createUserWithPhone(String phone) {
        //1.创建用户
        User user = new User();
        user.setPhone(phone);
        user.setNickName(USER_NICK_NAME_PREFIX + RandomUtil.randomString(10));
        //2.保存用户
        save(user);
        return user;

    }

}

LoginInterceptor类:

java 复制代码
package com.hmdp.utils;

import...

@Slf4j
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.不存在,拦截,跳转到登录页面
            log.debug("用户已登录,用户:{}", user);
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            return false;
        }

        //5.存在,保存用户信息到ThreadLocal
        UserHolder.saveUser((UserDTO) user);

        // 6.放行
        return true;
        
}
java 复制代码
package com.hmdp.config;

import...

@Configuration
public class MvcConfig implements WebMvcConfigurer {
    //配置拦截器

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //登录拦截器
        registry.addInterceptor(new LoginInterceptor())
                .addPathPatterns("/**")
                .excludePathPatterns(
                        "/user/code",
                        "/user/login",
                        "/blog/hot",
                        "/shop/**",
                        "/shop-type/**",
                        "/upload/**",
                        "/voucher/**"
                ).order(1);

    }
}

就是很常见的基于session存储来实现的登陆界面,以及Interceptor拦截器,很简单,之前写苍穹外卖的时候都写过了,所以只总结一些新的东西。

🙌首先就是手机号校验(这里就用到了正则表达式)

java 复制代码
 //1.校验手机号
        if (RegexUtils.isPhoneInvalid(phone)) {
            // 2.如果不符合,返回错误信息
            return Result.fail("手机号格式错误!");
        }

是一个来自一个工具类 RegexUtils的方法实现的,它是一个自定义的工具类,用于处理正则表达式 相关的验证。

方法名含义:

  • isPhoneInvalid(phone):判断手机号 是否无效
    • 如果返回 true → 手机号不合法
    • 如果返回 false → 手机号合法

来看看RegexUtils 的源码

java 复制代码
   
   // 校验是否不符合正则格式
    private static boolean mismatch(String str, String regex){
        if (StrUtil.isBlank(str)) {
            return true;
        }
        return !str.matches(regex);
    }

    public abstract class RegexPatterns {
    /**
     * 手机号正则
     */
    public static final String PHONE_REGEX = "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$";
   
}

💡:这里注意一下因为整个项目是黑马很早之前就推出的,手机号的正则表达式已经不正确,需要改一下

中国的手机号通常是:

总共 11位

必须以 1 开头

第二位一般是 3 4 5 6 7 8 9(目前没有 10x、11x、12x 的公众号段)

后面9位是任意数字

r 复制代码
^1(3[0-9]|4[579]|5[0-35-9]|6[6]|7[0135678]|8[0-9]|9[89])\d{8}$

我们拆解一下:

(3[0-9]) → 130~139

(4[579]) → 145、147、149

(5[0-35-9]) → 150153、155159(跳过154)

(6[6]) → 166

(7[0135678]) → 170、171、173、175、176、177、178

(8[0-9]) → 180~189

(9[89]) → 198、199

小白啊!!!写的不好轻喷啊🤯如果觉得写的不好,点个赞吧🤪(批评是我写作的动力)

...。。。。。。。。。。。...

...。。。。。。。。。。。...

相关推荐
li星野5 分钟前
OpenCV4.X学习-视频相关
学习·音视频
万事可爱^1 小时前
LangChain v1.0学习笔记(4)—— 核心组件Models
人工智能·笔记·学习·langchain·大模型
卡布叻_星星2 小时前
笔记之光盘刻录
笔记
寄思~2 小时前
Excel 数据匹配工具 -笔记
笔记·python·学习·excel
朔北之忘 Clancy2 小时前
2020 年 6 月青少年软编等考 C 语言二级真题解析
c语言·开发语言·c++·学习·青少年编程·题解·尺取法
知识分享小能手2 小时前
Ubuntu入门学习教程,从入门到精通,Ubuntu 22.04 中安装 Docker 容器 —— 知识点详解(26)
学习·ubuntu·docker
数据轨迹0012 小时前
CVPR Efficient ViM:视觉 Mamba 的轻量化
经验分享·笔记·facebook·oneapi·twitter
开开心心_Every2 小时前
安卓做菜APP:家常菜谱详细步骤无广简洁
服务器·前端·python·学习·edge·django·powerpoint
wdfk_prog2 小时前
WIN11如何可以安装ISO
linux·笔记·学习
haokan_Jia2 小时前
【高项十大知识域-重点笔记】
笔记