JavaWeb_仿小米商场,(2)用户注册

JavaWeb_仿小米商场,(2):用户注册

1 业务描述

注册业务旨在收集和管理用户的个人信息,是未来提供个性化服务的基础。相应的前端页面如下方静态H5页面图所示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pU0b5THs-1652276034718)(D:\鲲鹏培训\项目\仿小米商城\项目编写过程截图\用户注册界面.png)]

网页中提供多个输入框,并给出对应的提示信息,逐步引导用户根据提示向输入框中填写信息。最终点击下方的 注册 按钮完成用户注册。

前端ajax验证,用户名在输入后鼠标丢失焦点的时候发送求情到servlet检查用户是否在数据库中存在,不存在则可以注册,存在则给出提示

前端ajax验证,邮箱在输入后鼠标丢失焦点的时候发送求情到servlet检查邮箱是否在数据库中存在,不存在则可以注册,存在则给出提示

注册成功后给出提示

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AsIfcGBF-1652276034719)(D:\鲲鹏培训\项目\仿小米商城\项目编写过程截图\注册后激活界面.png)]

进一步地,为了验证联系方式的有效性,在完成注册功能后,前端还会提示用户执行 激活 操作:通过向用户注册时填写的邮箱发送验证邮件。在邮件正文中引导用户点击相应的超链接完成账户激活,并在激活页面提供登录链接,引导用户登录网站。整个注册业务流程完毕

2 业务分析

2.1 业务流程抽象

在本案例中,注册业务分为两阶段:

注册阶段:用户根据前端页面的提示信息填写相应内容,进而提交至后台处理,最终将信息保存至数据库。
激活阶段:系统后台自动向用户填写的邮件地址发送一封 激活邮件,邮件中包含一个激活链接。用户通过点击激活链接向服务器发送一个请求,服务器在接收到该请求后,再向用户浏览器回写激活成功信息。

2.2 可能的技术难点与解决策略

1避免机器人批量注册

添加验证码,优先核对,不满足直接跳出方法。(后续单独写一篇博客分析此功能)

2如何保证激活用户的唯一性?

在 tab_user 表中添加字段:active_code 。它是一种保证唯一性的序列码,本案例中调用 Java 中的工具类 UUID 生成序列并作为用户的激活码。在用户注册时生成并与用户信息一并写入数据库,同时向用户提交的邮件地址发送一封带有激活码链接的邮件。只有用户在邮件中点击了这个链接,使用带有激活码的URL向服务器发出请求,服务器才能收到用户“发来的”激活码,并在后端完成校验并向用户端浏览器回写响应信息。

3如何定义和处理激活状态?

在 tab_user 表中添加两个字段:status 。status 用于标注用户是否激活,它只有两种可能的取值:Y(已激活)和 N(未激活)。在用户刚刚提交注册表单时,后端在数据库中添加用户信息时对该字段设为 N,当用户在激活邮件中点击激活链接向服务器发送激活请求时,服务器在核对通过的前提下将该字段修改为 Y。

前端校验用户填写的表单信息:正则表达式校验,这里参考了暮光乐鱼的博客,他的正则表达式写的要比我的好。

非空 :.+
字符集 :^\w{6,20}$
手机号 :1(3|4|5|7|8)\d{9}
邮箱 :^\w+(.\w+)*@\w+(.\w+)+$

3 代码实现

3.1 信息验证与提交

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SPs1wpZj-1652276034720)(D:\鲲鹏培训\项目\仿小米商城\项目编写过程截图\信息验证与提交流程.png)]

3.1.1前端

通过ajax异步校验用户名是否存在

   $(function () {
            $("#username").change(function () {
                //使用ajax 做username 的异步验证 checkUsername?username=xxxx
                $.get("user.do?action=checkUserName", "username=" + this.value, function (data) {
                    if (data == 1) {
                        $("#usernameMsg").html("用户名已经存在").css("color", "red");
                        $("#registerBtn").attr("disabled", true);
                    } else {
                        $("#usernameMsg").html("用户名可用").css("color", "green");
                        $("#registerBtn").removeAttr("disabled");
                    }
                })
            });
        })
    

通过ajax校验邮箱是否存在

   $(function () {
            $("#email").change(function () {
                //使用ajax 做username 的异步验证 checkUsername?username=xxxx
                $.get("user.do?action=checkEmial", "username=" + this.value, function (data) {
                    if (data == 1) {
                        $("#usernameMsg").html("邮箱已经存在").css("color", "red");
                        $("#registerBtn").attr("disabled", true);
                    } else {
                        $("#usernameMsg").html("邮箱可用").css("color", "green");
                        $("#registerBtn").removeAttr("disabled");
                    }
                })
            });
        })


3.1.2 用户名邮箱校验Servlet代码

@WebServlet("/user.do")
public class UserServlet extends BaseServlet implements Serializable {
    //...............
    public String checkUserName(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        IUserService userService=new UserServiceImpl();
        User user=new User();
        String username = req.getParameter("username");
        user.setUsername(username);
        boolean falg=userService.queryDataByUser(user);
        return falg==true?"0":"1";
    }

    public String checkEmail(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {

        IUserService userService=new UserServiceImpl();
        User user=new User();
        String email = req.getParameter("email");
        user.setEmail(email);
        boolean falg=userService.queryDataByUser(user);
        return falg==false?"0":"1";
    }
    
    //.............................

表单提交函数


    //单词字符 8-12
    function checkUsername(){
        const s = $("#username").val();
        const check = /^\w{2,20}$/;
        const flag = check.test(s);
        if(flag){
            $("#username").css("border","");
        }else{
            $("#username").css("border","1px solid red");
        }
        return flag;
    }
    // 单词字符,8-12
    function checkPassword(){
        const s = $("#password").val();
        const check = /^\w{4,20}$/;
        const flag = check.test(s);
        if(flag){
            $("#password").css("border","");
        }else{
            $("#password").css("border","1px solid red");
        }
        return flag;
    }
    // email校验
    function checkEmail(){
        const s = $("#email").val();
        //定义正则 itcast@163.com
        const check = /^\w+@\w+\.\w+$/;
        const flag = check.test(s);
        if(flag){
            $("#email").css("border","");
        }else {
            $("#email").css("border","1px solid red");
        }
        return flag;
    }
    //验证验证码
    function checkCode(){
        const s = $("#vaildateCode").val();
        let flag = false;
        if(s!=null){
            $("#vaildateCode").css("border","");
            flag = true;
        }else {
            $("#vaildateCode").css("border","1px solid red");
        }
        //todo  在数据库是否存在  鼠标焦点丢失 使用ajax验证在数据库是否存在相同的邮箱  
        return flag;
    }




        $(function () {
        // 当表单提交时调用所有的校验方法
        $("#registerForm").submit(function () {
            // 1.发送数据到服务器
            if (
                checkUsername() &&			// 用户名校验
                checkPassword() &&			// 密码校验
                checkEmail() &&				// 邮箱校验
                checkCode()					// 验证码校验
            ) {			// 校验成功
                // 发送AJAX请求,提交表单数据	username=Alex&password=123 ...
                $.post("user/register", $(this).serialize(), function (data) {
                    // 处理响应数据 data {flag:true/false, errorMsg:"..."}
                    if (data["flag"]) {	// 注册成功
                        // 跳转成功页面
                        location.href = "register_ok.html";
                    } else {			// 注册失败
                        // 在注册页面添加提示信息
                        $("#errorMsg").html(data["errorMsg"]);
                    }
                });
            } else {	// 校验失败
            }
            // 2.跳转页面
            return false;
        });

        // 当某一个组件失去焦点时,调用对应的校验方法
        $("#username").blur(checkUsername);
        $("#password").blur(checkPassword);
        $("#email").blur(checkEmail);
        $("#name").blur(checkName);
        $("#telephone").blur(checkTelephone);
        $("#sex").blur(checkSex);
        $("#birthday").blur(checkBirthday);
        $("#check").blur(checkCode);
    })

使用ajax异步验证邮箱和用户名是否唯一

  $(function () {
            $("#username").change(function () {
                //使用ajax 做username 的异步验证 checkUsername?username=xxxx
                $.get("user.do?action=checkUserName", "username=" + this.value, function (data) {
                    if (data == 1) {
                        $("#usernameMsg").html("用户名已经存在").css("color", "red");
                        $("#registerBtn").attr("disabled", true);
                    } else {
                        $("#usernameMsg").html("用户名可用").css("color", "green");
                        $("#registerBtn").removeAttr("disabled");
                    }
                })
            });
        })
        //异步校验邮箱
        $(function () {
            $("#email").change(function () {
                //使用ajax 做username 的异步验证 checkUsername?username=xxxx
                $.get("user.do?action=checkUserEmail", "email=" + this.value, function (data) {
                    if (data == 1) {
                        $("#emailMsg").html("邮箱已经存在").css("color", "red");
                        $("#registerBtn").attr("disabled", true);
                    } else {
                        $("#emailMsg").html("邮箱可用").css("color", "green");
                        $("#registerBtn").removeAttr("disabled");
                    }
                })
            });
        })

        //验证码点击改变函数
        function changeValidateCode(img) {
            img.src = "captcha.do?d" + new Date().getTime();
        }

注册完整页面代码

数据控制层IUserDao接口定义如下

public interface IUserDao extends IBaseDao<User> {

    int findDataByUser(User user);

    int updateUserState(User user);
}

IUserDao接口实现类UserDaoImpl类的代码如下,用于完成对注册用户的信息的检查以及注册信息是否合法


public class UserDaoImpl implements IUserDao {
    private QueryRunner queryRunner = null;
    public UserDaoImpl() {
        queryRunner = new QueryRunner();
    }

    /**
     * 验证用户名和邮箱是否存在
     * @param user
     * @return
     */
    @Override
    public int findDataByUser(User user) {
        int n = -1;
        String sql = "select * from tb_user where 1=1";
        String parms = "";
        if (user.getEmail() != null && !user.getEmail().equals("")) {
            sql += " and email=? ";
            parms = user.getEmail();
        } else if (user.getUsername() != null && !user.getUsername().equals("")) {
            sql += " and username=? ";
            parms = user.getUsername();
        } else {
            return 100;
        }
        try {
            User u = queryRunner.query(DBUtils.getConn(), sql, parms, new BeanHandler<>(User.class));
            if (u != null) {
                n = 5;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return n;
    }

    /**
     * 修改用户状态
     * @param user
     * @return
     */
    @Override
    public int updateUserState(User user) {
        int n=-1;
        String sql="update tb_user set flag=? where code=? and email=?";
        try {
            n = queryRunner.update(DBUtils.getConn(), sql,user.getFlag(),user.getCode(), user.getEmail());
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return n;
    }

    /**
     * 用户数据添加
     * @param user
     * @return
     */
    @Override
    public int addData(User user) {
        int n = -1;
        String sql = "insert into tb_user(username,password,email,gender,flag,role,code) values(?,?,?,?,?,?,?)";
        try {
           n = queryRunner.update(DBUtils.getConn(), sql, user.getUsername(), user.getPassword(),
                    user.getEmail(), user.getGender(), user.getFlag(), user.getRole(), user.getCode());

        } catch (SQLException e) {
            e.printStackTrace();
        }
        return n;
    }

    @Override
    public int updateData(User user) {
        return 0;
    }

    @Override
    public int deleteById(int id) {
        return 0;
    }

    @Override
    public User findDataById(int id) {
        return null;
    }

    @Override
    public List<User> getAllDatas() {
        return null;
    }
}

业务处理层IUserService接口定义如下

public interface IUserService extends IBaseService<User>{
    boolean queryDataByUser(User user);

    boolean activate(User user);
}

该接口的实现类UserServiceImpl代码如下 用于链接视图层和数据处理层,根据数据控制层的处理结果对视图出的请求回应不同的处理结果



public class UserServiceImpl implements IUserService {
    private IUserDao userDao = new UserDaoImpl();

    @Override
    public boolean queryDataByUser(User user) {
        int n = userDao.findDataByUser(user);
        return n >= 1 ? true : false;
    }

    @Override
    public boolean activate(User user) {
        int n = userDao.updateUserState(user);
        return n >= 1 ? true : false;
    }

    /**
     * 用户注册逻辑
     *
     * @param user
     * @return
     */
    @Override
    public boolean saveData(User user) {
        boolean flag = false;
        //这里需要二次验证用户名邮箱
        User u1 = new User();
        u1.setUsername(user.getUsername());
        User u2 = new User();
        u2.setEmail(user.getEmail());
        if (!this.queryDataByUser(u1) && !this.queryDataByUser(u2)) {
            //密码md5加密
            String md5 = MD5Utils.md5(user.getPassword());
            user.setPassword(md5);
            //生成激活码
            String activeCode = RandomUtils.createActive();
            user.setCode(activeCode);
            if (userDao.addData(user) >= 1) {
                //发激活提示邮件
                EmailUtils.sendEmail(user);
                flag = true;
            }
        }
        return flag;
    }

    @Override
    public boolean editData(User user) {
        return false;
    }

    @Override
    public boolean removeData(int id) {
        return false;
    }

    @Override
    public User queryDataById(int id) {
        return null;
    }

    @Override
    public List<User> queryAllData() {
        return null;
    }
}

UserServlet类增加了对注册页面校验注册是否合法的不同验证方法


@WebServlet("/user.do")
public class UserServlet extends BaseServlet {
    private ResultData resultData = new ResultData();

    /**
     * 用户登录测试
     *
     * @param req
     * @param resp
     * @return
     * @throws ServletException
     * @throws IOException
     */
    public String login(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //http://localhost:8080/user.do?action=login
        return "TODO 这是用户登录功能";
    }

    /**
     * 验证用户名
     *
     * @param req
     * @param resp
     * @return
     * @throws ServletException
     * @throws IOException
     */
    public String checkUserName(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        IUserService userService = new UserServiceImpl();
        User user = new User();
        String username = req.getParameter("username");
        user.setUsername(username);
        boolean flag = userService.queryDataByUser(user);
        return flag == false ? "0" : "1";
    }

    /**
     * 注册功能
     *
     * @param req
     * @param resp
     * @return
     * @throws ServletException
     * @throws IOException
     */
    public String register(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        IUserService userService = new UserServiceImpl();
        User user = new User();
//        String username = req.getParameter("username");
//        user.setUsername(username);
//        String password = req.getParameter("password");
//        user.setPassword(password);
//        String email = req.getParameter("email");
//        user.setEmail(email);
//        String gender = req.getParameter("gender");
//        user.setGender(gender);
        this.analysisFromToObject(req,user);
        String code = req.getParameter("code");
        String msg = "";
        resultData.setFlag(false);
        if (code != null && !"".equals(code)) {
            //对比验证码
            String codeVd = (String) req.getSession().getAttribute("code");
            if (codeVd.equalsIgnoreCase(code)) {
                //调用业务层方法
                if (userService.saveData(user)) {
                    resultData.setFlag(true);
                } else {
                    msg = "注册失败";
                }
            } else {
                msg = "验证码错误";
            }
        } else {
            msg = "验证码不能为空";
        }
        resultData.setErrorMsg(msg);
        String json = JSON.toJSONString(resultData);
        return json;
    }

    /**
     * 验证邮箱
     *
     * @param req
     * @param resp
     * @return
     */
    public String checkUserEmail(HttpServletRequest req, HttpServletResponse resp) {
        IUserService userService = new UserServiceImpl();
        User user = new User();
        String email = req.getParameter("email");
        user.setEmail(email);
        boolean flag = userService.queryDataByUser(user);
        return flag == false ? "0" : "1";
    }

    /**
     * 邮箱激活
     * @param req
     * @param resp
     * @return
     */
    public String activate(HttpServletRequest req, HttpServletResponse resp) {
        String mesg="用户激活失败,请重试";
        String emailB64=req.getParameter("e");
        String email= Base64Utils.decode(emailB64);
        String codeB64=req.getParameter("c");
        String code=Base64Utils.decode(codeB64);

        IUserService userService=new UserServiceImpl();
        User user=new User();
        user.setEmail(email);
        user.setCode(code);
        //如果有html链接内容输出要设置响应
        resp.setContentType("text/html;charset=utf-8");
        user.setFlag(1);
        if (userService.activate(user)){
            mesg="用户激活成功,请<a href='login.html'>登录</a>";
            mesg= Constants.FORWARD+"message.html";
        }
        return mesg;
    }
}

其中还用到了一些工具类

如有需要可到gitee仓库中寻找

;
String codeB64=req.getParameter(“c”);
String code=Base64Utils.decode(codeB64);

    IUserService userService=new UserServiceImpl();
    User user=new User();
    user.setEmail(email);
    user.setCode(code);
    //如果有html链接内容输出要设置响应
    resp.setContentType("text/html;charset=utf-8");
    user.setFlag(1);
    if (userService.activate(user)){
        mesg="用户激活成功,请<a href='login.html'>登录</a>";
        mesg= Constants.FORWARD+"message.html";
    }
    return mesg;
}

}


其中还用到了一些工具类

如有需要可到我的gitee仓库中寻找

链接地址:[仿小米商场gitee仓库链接](https://gitee.com/playliwen/mi_-shop.git)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值