【途牛旅遊專案】02 - 註冊功能實現(aJax提交,正規表示式判斷,BeanUtils封裝和註冊轉換器)

2020-10-11 01:00:10

註冊功能分析圖解

在這裡插入圖片描述

實現樣式截圖

在這裡插入圖片描述

實現註冊功能

1. 建立註冊業務的測試方法

//測試註冊使用者 - 儲存使用者資訊  需要對username是否已經被註冊過進行判斷
    @Test
    public void test02() {
        UserService userService = new UserService();

        User user= new User(null,"register123","ABC123456",new Date(),"註冊暱稱","男","17878782828","9689621@qq.com","N","codeNumber");
//        user.setUsername("strive_gf");
//        user.setPassword("ABC123456");
        int code = userService.register(user);

        if(code == 1){
            System.out.println("註冊成功");
        }else if(code == 0){
            System.out.println(user.getUsername()+"已經被註冊過了,請更換使用者名稱");
        }
    }

2. 建立業務層UserService的註冊方法

public int register(User user) {

        //查詢username是否存在,存在就返回錯誤,不能註冊
        User u = userDao.findByUserName(user.getUsername());
        if(u == null){
            user.setStatus("N");//註冊成功,但是設定為未啟用,需要去啟用
            //儲存使用者註冊資料
            userDao.saveUser(user);
            return 1;//未存在,可以註冊
        }else {
            return 0;//已存在,不可註冊
        }
    }

3. 建立dao層介面方法

public interface UserDao {
    //通過usernmae查詢user是否存在
    User findByUserName(String username);

    //儲存使用者註冊資料,新增使用者
    void saveUser(User user);
}

4. 建立dao的對映檔案xml

<!--註冊時通過usernmae查詢是否被註冊過-->
    <select id="findByUserName" parameterType="string" resultType="com.xgf.bean.User">
         select uid,username,password,name,birthday,sex,telephone,email,status,code
          from tab_user
          where username = #{username}
    </select>

    <!--儲存使用者註冊資料,新增使用者-->
    <insert id="saveUser" parameterType="com.xgf.bean.User" >
        insert into tab_user values
        (null,#{username},#{password},#{name},#{birthday},#{sex},#{telephone},#{email},#{status},#{code})
    </insert>

5. 測試dao層的findByUserName方法

//對user的dao程序測試
public class TestUserDao {
    //通過工具類獲取userdao的bean
    private static UserDao userDao = GetDaoUtils.getMapper(UserDao.class);

    //測試findByUserName方法,查詢usermane是否已存在
    @Test
    public void test01(){
        User user = userDao.findByUserName("strive_gf");
        if(user == null){
            System.out.println("username未註冊,可以註冊");
        }else{
            System.out.println("username已註冊,請更換");
        }
    }
}

6. 測試註冊TestUserService.test02()

//執行結果
//第一步,查詢username是否已經被註冊
Preparing: select uid,username,password,name,birthday,sex,telephone,email,status,code from tab_user where username = ?
Parameters: register123(String)
  Total: 0

紀錄檔返回結果:0條記錄被查到,證明該username沒有被註冊,可以註冊

//第二步呼叫saveUser方法儲存註冊的使用者
Preparing: insert into tab_user values (null,?,?,?,?,?,?,?,?,?)
Parameters: register123(String), ABC123456(String), 註冊暱稱(String), 2020-10-08 09:12:12.281(Timestamp), 男(String), 17878782828(String), 9689621@qq.com(String), N(String), codeNumber(String)
  Updates: 1

紀錄檔返回結果:更新一條記錄,也就是增加成功,註冊成功。
在這裡插入圖片描述

7. 編寫前端jsp註冊介面

  這裡有用正規表示式對使用者名稱、密碼、郵箱進行正則判斷

  • 校驗使用者名稱 /^\w{8,20}$/ 單詞字元,長度8到20位
  • 校驗密碼 /^\w{8,20}$/ 單詞字元,長度8到20位
  • 校驗郵箱 = /^\w+@\w+.\w+$/ 郵箱 xxx@qq.com

7.1 前端頁面

<!--登入檔單-->
            <form id="registerForm">

                <!--提交處理請求的識別符號-->
                <input type="hidden" name="action" value="register">
                <table style="margin-top: 25px;">
                    <tr>
                        <td class="td_left">
                            <label for="username">使用者名稱</label>
                        </td>
                        <td class="td_right">
                            <input type="text" id="username" name="username" placeholder="請輸入賬號">
                        </td>
                    </tr>
                    <tr>
                        <td class="td_left">
                            <label for="password">密碼</label>
                        </td>
                        <td class="td_right">
                            <input type="text" id="password" name="password" placeholder="請輸入密碼">
                        </td>
                    </tr>
                    <tr>
                        <td class="td_left">
                            <label for="email">Email</label>
                        </td>
                        <td class="td_right">
                            <input type="text" id="email" name="email" placeholder="請輸入Email">
                        </td>
                    </tr>
                    <tr>
                        <td class="td_left">
                            <label for="name">姓名</label>
                        </td>
                        <td class="td_right">
                            <input type="text" id="name" name="name" placeholder="請輸入真實姓名">
                        </td>
                    </tr>
                    <tr>
                        <td class="td_left">
                            <label for="telephone">手機號</label>
                        </td>
                        <td class="td_right">
                            <input type="text" id="telephone" name="telephone" placeholder="請輸入您的手機號">
                        </td>
                    </tr>
                    <tr>
                        <td class="td_left">
                            <label for="sex">性別</label>
                        </td>
                        <td class="td_right gender">
                            <input type="radio" id="sex" name="sex" value="" checked><input type="radio" name="sex" value=""></td>
                    </tr>
                    <tr>
                        <td class="td_left">
                            <label for="birthday">出生日期</label>
                        </td>
                        <td class="td_right">
                            <input type="date" id="birthday" name="birthday" placeholder="年/月/日">
                        </td>
                    </tr>
                    <tr>
                        <td class="td_left">
                            <label for="check">驗證碼</label>
                        </td>
                        <td class="td_right check">
                            <input type="text" id="inputCheckCode" name="inputCheckCode" class="check">
                            <img src="checkCodeServlet" height="32px" alt="看不清?點我換一換" onclick="changeCheckCode(this)">
                            <script type="text/javascript">
                                //圖片點選事件,點選更換驗證碼
                                function changeCheckCode(img) {
                                    img.src="checkCodeServlet?"+new Date().getTime();//新增時間戳
                                }
                            </script>
                        </td>
                    </tr>
                    <tr>
                        <td class="td_left">
                        </td>
                        <td class="td_right check">
                            <input type="submit" class="submit" value="註冊">
                            <span id="msg" style="color: red;"></span>
                        </td>
                    </tr>
                </table>
            </form>

7.2 前端js指令碼,進行輸入驗證,ajax提交

這裡通過表單序列化$("#registerForm").serialize()方法,向後臺輸送表單內容。
這裡只是簡單的正規表示式驗證,以後用框架就行。

<script type="text/javascript">
        //輸入校驗
        var usernameFlag;
        var passwordFlag;
        var emailFlag;
        function checkUsername() {

            //判斷一下賬號輸入是否合法
            var username = $("#username").val();
            //8-20位字元或數位
            var reg = /^\w{8,20}$/;
            usernameFlag = reg.test(username);
            if (usernameFlag) {
                //符合條件,提示username可用,清空前面的報錯
                $("#username").css("border", "");
                $("#errorMsg").html("");
            } else {
                //修改邊框,提示不可用
                $("#username").css("border", "3px solid red");
                $("#errorMsg").html("使用者名稱必須是8-20位數位和字母組合");
            }
            return usernameFlag;
        }

        function checkPassword() {
            //判斷一下密碼輸入是否合法
            var password = $("#password").val();
            var reg = /^\w{8,20}$/;
            passwordFlag = reg.test(password);
            if (passwordFlag) {
                $("#errorMsg").html("");
                //不提示
                $("#password").css("border", "");
            } else {
                //提示
                $("#password").css("border", "3px solid red");
                if(usernameFlag){//使用者名稱輸入正確才顯示密碼錯誤
                    $("#errorMsg").html("密碼必須是8-20位數位和字母組合");
                }

            }
            return passwordFlag;
        }

        function checkEmail() {
            //判斷一下密碼輸入是否合法
            var email = $("#email").val();
            var reg = /^\w+@\w+\.\w+$/;
            emailFlag = reg.test(email);
            if (emailFlag) {
                $("#errorMsg").html("");
                //不提示,無邊框
                $("#email").css("border", "");
            } else {
                //提示
                $("#email").css("border", "3px solid red");
                if(usernameFlag && passwordFlag){//如果使用者名稱和密碼都正確才顯示郵箱錯誤,前面的優先顯示
                    $("#errorMsg").html("郵箱輸入不正確");
                }
            }
            return emailFlag;
        }

        //頁面初始化執行
        $(function () {
            //賬號密碼 手機號 郵箱 -> 通過正則判斷,是否合法
            //格式正確不作提示,如果錯誤將邊框改成紅色
            $("#username").blur(checkUsername)
            $("#password").blur(checkPassword)
            $("#email").blur(checkEmail)

            $("#registerForm").submit(function () {
                if(!usernameFlag){
                    $("#errorMsg").html("使用者名稱必須是8-20位數位和字母組合");
                }else if(!passwordFlag){
                    $("#errorMsg").html("密碼必須是8-20位數位和字母組合");
                }else if(!emailFlag){
                    $("#errorMsg").html("郵箱輸入不正確")
                }
                //ajax提交
                if (checkUsername() && checkPassword() && checkEmail()) {
                    //使用serialize()序列化方法,將整個表單序列化成json字串傳送給後臺
                    $.post("RegisterServlet", $("#registerForm").serialize(),
                        function (data) {
                            //{code:1,data:成功}
                            if (data.code == 1) {
                                window.location = "login.jsp";
                            } else {
                                //註冊失敗,錯誤提示資訊
                                $("#errorMsg").html(data.data);
                            }
                        }, "json");
                }
                return false;
            })
        });
    </script>

8. 建立註冊servlet,獲取引數通過 BeanUtils封裝物件

//登入servlet
@WebServlet("/RegisterServlet")
public class RegisterServlet extends HttpServlet {

	//beanUtils是不能自動的將String轉換為日期Date型別,通過serialize序列化方法提交表單,取出是字串形式,需要進行格式轉換,不然的話不能封裝成bean物件
    //BeanUtils不支援自動將String向Date資料型別轉換
    //BeanUtils格式轉換器,靜態程式碼塊,在載入的時候自動執行,而且只執行一次
    static {
        //ConvertUtils.register()方法,將String轉Date的轉換器註冊給beanUtils
        //一般寫在靜態程式碼塊中(只執行一次),或者在專案啟動的時候自己註冊(通過監聽器實現)
        //將轉換器註冊到BeanUtils中
        ConvertUtils.register(new Converter() {

            public Object convert(Class type, Object value) {
                //將yyyy-MM-dd格式的字串轉換為Date資料型別
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    return simpleDateFormat.parse(value.toString());
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, Date.class);
    }
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {


        UserService userService = new UserService();
        HttpSession session = request.getSession();//獲取session物件,裡面主要是驗證碼和當前user
        Msg msg = new Msg();//提示資訊

        //使用者輸入的驗證碼
        String inputCheckCode = request.getParameter("inputCheckCode");
        //從session中獲取系統當前生成的驗證碼
        String verificationCode = (String) session.getAttribute("verificationCode");
        System.out.println("RegisterServlet \t\t inputCheckCode : " + inputCheckCode + " ;\t verificationCode : " + verificationCode);

        //inputCheckCode 與 verificationCode
        //相同表示驗證碼不正確,將提示資訊寫到頁面的錯誤提示
        if (inputCheckCode == null || !inputCheckCode.equalsIgnoreCase(verificationCode)) {
            //驗證碼不看大小寫
            msg.setCode(-1);
            msg.setData("驗證碼輸入出錯,請重新輸入驗證碼");

            //將字串轉換為json資料格式返回給瀏覽器
            String json = new ObjectMapper().writeValueAsString(msg);
            response.getWriter().println(json);
            return; //返回不繼續執行
        }

        //獲取請求引數
        Map<String, String[]> map = request.getParameterMap();
        //當前登入使用者
        User registerUser = new User();
        try {
            //參1 javaBean 參2 map 封裝bean物件
            BeanUtils.populate(registerUser, map);//將map裡面所有的引數賦值給javaBean(login就是輸入的username和password)
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }

        //呼叫service處理引數,註冊業務
        int code = userService.register(registerUser);
        //響應給瀏覽器 ajax 是響應json給瀏覽器就可以
        msg.setCode(code);//設定code

        if (code == 1) {
            msg.setData("註冊成功,跳轉登入介面");
            //從session中刪除生成的驗證碼 不移除的話可能會覆蓋新的驗證碼
            session.removeAttribute("verificationCode");
        } else if(code == 0){
            msg.setData(registerUser.getUsername()+"已註冊,請更換使用者名稱");
        }else {
            msg.setData("註冊失敗");
        }

        //將字串轉成json資料格式,返回給瀏覽器顯示提示資訊msg
        String json = new ObjectMapper().writeValueAsString(msg);
        response.getWriter().println(json);
    }
}
//beanUtils不能自動的將String轉換為日期Date型別,通過serialize序列化方法進行的,取出是字串形式,需要進行格式轉換
    //BeanUtils不支援自動將String向Date資料型別轉換
    //BeanUtils格式轉換器
    static {
        //靜態程式碼塊,在載入的時候自動執行,而且只執行一次
        //ConvertUtils.register()方法,將string轉date的轉換器註冊給beanUtils
        //一般寫在靜態程式碼塊中(只執行一次),或者在專案啟動的時候自己註冊(通過監聽器實現)
        //將轉換器註冊到BeanUtils中
        ConvertUtils.register(new Converter() {

            public Object convert(Class type, Object value) {
                //將yyyy-MM-dd格式的字串轉換為Date資料型別
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    return simpleDateFormat.parse(value.toString());
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, Date.class);
    }

BeanUtils將接收String轉換為Date資料型別【***】

  BeanUtils是不能自動的將String轉換為日期Date型別,通過serialize序列化方法提交表單,取出是字串形式,需要進行格式轉換,不然的話不能封裝成bean物件。
  BeanUtils不支援自動將String向Date資料型別轉換,可以通過ConvertUtils.register()方法,將String轉Date的轉換器註冊給beanUtils,這個方法一般寫在靜態程式碼塊中(只執行一次),或者在專案啟動的時候自己註冊(通過監聽器實現)

    //BeanUtils格式轉換器,靜態程式碼塊,在載入的時候自動執行,而且只執行一次
    static {
        //將轉換器註冊到BeanUtils中
        ConvertUtils.register(new Converter() {

            public Object convert(Class type, Object value) {
                //將yyyy-MM-dd格式的字串轉換為Date資料型別
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                try {
                    return simpleDateFormat.parse(value.toString());
                } catch (ParseException e) {
                    e.printStackTrace();
                }
                return null;
            }
        }, Date.class);
    }

9. 執行結果

錯誤輸入提示:
在這裡插入圖片描述
輸入符合要求的引數進行註冊:
在這裡插入圖片描述

檢視網路引數,傳送給後臺的請求引數:

在這裡插入圖片描述
註冊成功跳轉登入介面
在這裡插入圖片描述
測試登入,顯示還未啟用,下一篇,用郵箱啟用賬戶:
在這裡插入圖片描述

10. 程式碼倉庫地址

https://github.com/strive-xgf/SSM/commit