黑马点评学习笔记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

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

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

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

相关推荐
Nan_Shu_6142 小时前
学习:uniapp全栈微信小程序vue3后台(28)
前端·学习·微信小程序·小程序·uni-app
JanelSirry2 小时前
VMware+RockyLinux+ikuai+docker+cri-docker+k8s+calico BGP网络 自用 实践笔记(二)
笔记·docker·kubernetes
举焰3 小时前
VSCode+MSVC+Qmake环境搭建笔记
c++·ide·笔记·vscode·msvc·qt5·qmake
岑梓铭3 小时前
《考研408数据结构》第二章《线性表(顺序表、链表)》复习笔记
数据结构·笔记·考研
xiaofan6720133 小时前
金融分析师职场学习技能提升方法分享
学习·金融
林炳然4 小时前
将软件从C盘迁移至D盘:释放系统盘空间的终极指南
笔记
Source.Liu4 小时前
mdBook 开源笔记
笔记·rust·markdown
Lyre丶4 小时前
Ubuntu 24.04 LTS 安装GAMIT
linux·经验分享·学习·ubuntu·gamit
strongwyy4 小时前
esp32墨水屏学习3
学习