JavaWeb階段婚禮匯項目Demo練習,一個將婚禮簡單化的平臺Demo,正處於學習階段的你再合適不過!

前言

此項目可以作爲正在學習階段處於JavaWeb階段的小夥伴,綜合了JavaWeb階段的所有知識。
注意: 該項目只實現了部分功能,並非成熟項目。如果處於學習階段的你,正合適不過。我將婚禮匯的項目資源放在GitHub上,供大家參考!還請多多指教!

👉GitHub地址: 婚禮匯項目資源下載

一、項目介紹

項目聲明: 本項目作爲JavaWeb學習階段的綜合練習,不屬於成熟項目。所以在此項目中主要雜揉了Web階段學過的知識,提供HTML頁面和CSS樣式,此次練習只需要完成指定功能即可(某些功能我沒有寫,大家有興趣自行完成)!

項目名稱: 婚禮匯

項目介紹: 基於JavaEE平臺的系統,用於解決結婚、宴請、聚會、婚車、酒店預訂、化妝等一系列服務。

二、需求分析

技術架構:

  1. 前端技術棧: HTML、CSS、JavaScript、jQuery、BoootStrap、Json等
  2. 後端技術棧: JDBC、Filter、Servlet、JSP、反射等
  3. 服務器: Tomact8.5
  4. 數據庫: MySQL5.7

功能架構:

  1. 前端架構: 登錄、註冊、首頁、酒店列表、酒店詳情、套餐詳情、加入購物車、購物車列表、商品結算
  2. 後端架構: 用戶管理、購物車、酒店列表、酒店詳情、套餐、酒店、場地詳情等服務管理

項目架構: 使用基於MVC的三層架構設計、Servlet+JSP技術結構

三、數據模型分析與建立

數據關係模型分析:

用戶與購物車一對多的關係,指的是一個用戶可以在購物車中添加多個商品。

  1. 用戶與購物車(一對多)
  2. 酒店與房間(一對多)
  3. 酒店與套餐(一對多)
  4. 酒店與詳細信息(一對一)
  5. 圖片與酒店、房間和套餐(分別爲一對多)

數據庫模型建立:

該數據庫模型爲物理數據模型。使用Navicet建立!

酒店、房間、套餐、酒店信息、圖片數據的關係

image-20200524163949931

用戶、購物車關係

image-20200524164154051

四、頁面與功能

頁面流程:

所需完成功能的如下:

image-20200524170124310

功能描述:

  • 會員註冊
    • 手機號、密碼、短信驗證碼格式校驗
    • 阿里雲短信服務實現手機號接收驗證碼並校驗
    • 將註冊信息存儲到數據庫
    • 註冊成功跳轉會員登錄頁面
    • 註冊失敗返回註冊失敗的相關信息,跳轉本註冊頁面
  • 會員登錄
    • 手機號、密碼、驗證碼格式校驗
    • 生成隨機4位驗證碼並添加登錄校驗
    • 查詢數據庫中會員信息進行會員登陸
    • 登陸成功跳轉首頁
    • 登錄失敗返回登錄失敗的相關信息提示,跳轉登錄頁面
  • 自動登錄
    • 登陸後默認7天內自動登錄
  • 酒店列表
    • 使用分頁查詢動態顯示酒店列表信息
  • 酒店詳情
    • 動態顯示點擊後的酒店詳情信息
  • 套餐
    • 點擊套餐跳轉套餐列表
    • 可以根據套餐的類型、場地選擇相應的套餐加入購物車
    • 此處加入購物車操作的信息存儲到數據庫中對應表內
  • 我的購物車
    • 購物車內產生32位訂單號並顯示
    • 顯示當前加入購物車的服務器時間
    • 單選、全選選中購物車內商品單選框實現總價變化
    • 加減商品數量對數據庫的商品數量做修改並動態顯示總價

五、項目結構

項目所需第三方資源和jar包

下載地址:

  • 阿里雲短信服務
    • aliyun-java-sdk-core-4.1.1
    • aliyun-java-sdk-dysmsapi-1.1.0
    • gson-2.8.6
  • c3p0連接池
    • c3p0-0.9.5.4
    • mchange-commons-java-0.2.16
  • BeanUtils
    • commons-beanutils-1.9.4
    • commons-collections-3.2.2
    • commons-logging-1.2
  • dbUtils
    • commons-dbutils-1.6
  • 文件上傳與下載
    • commons-fileupload-1.4
    • commons-io-2.6
  • Json轉換工具Jackson
    • jackson-annotations-2.9.8
    • jackson-core-2.9.8
    • jackson-databind-2.9.8
  • JSTL標籤庫
    • jstl
    • standard
  • IDEA Lombok插件
    • lombok-1.18.10
  • MySQL
    • mysql-connector-java-5.1.25-bin
  • bootstrapValidator
  • bootstrap-3.3.7
  • jquery-3.2.1.min

項目結構圖

image-20200524174548912

六、部分頁面展示

image-20200524175132068

image-20200524174814922

image-20200524174847365

image-20200524174929338

image-20200524174956456image-20200524175055946

七、核心代碼與詳解

該代碼只是部分代碼,也沒有涉及到Service層與Dao層代碼。如果有興趣可以來下載此項目資源!

7.1 註冊功能

註冊頁面使用bootstrapValidator的js校驗

<script type="text/javascript">
        var interval;

        function sendSMS() {
            /**
             * 校驗手機號,觸發bootstrapValidator對手機號的校驗
             */
                //初始化bootstrapValidator對象
            var validator = $("#myForm").data("bootstrapValidator");
            validator.validateField("user_tel");
            var flag = validator.isValidField("user_tel");
            if (flag) {
                interval = setInterval("showCount()", 1000);
                $(".qrcode").attr("disabled", true);
                /**
                 * 請求服務器發送驗證碼
                 */
                $.post("${pageContext.request.contextPath}/sms", {
                    "methodName": "sendSMS",
                    "phoneNum": $("#user_tel").val()
                }, function (data) {
                    console.log(data);
                }, "json");
            }
        }

        var count = 30;

        function showCount() {
            $(".qrcode").text(count + " s");
            count--;
            if (count < -1) {
                clearInterval(interval);
                $(".qrcode").text("發送驗證碼");
                count = 30;
                $(".qrcode").attr("disabled", false);
            }
        }

        $(function () {
            $("#myForm").bootstrapValidator({
                message: "this is no a valiad field",
                fields: {
                    user_tel: {
                        message: "您輸入的手機號有誤",
                        validators: {
                            notEmpty: {
                                message: "手機號不能爲空"
                            },
                            regexp: {
                                message: "您輸入的手機號有誤",
                                regexp: /^[1]{1}[1356789]{1}[0-9]{9}$/
                            }
                        }
                    },
                    user_password: {
                        message: "密碼錯誤",
                        validators: {
                            notEmpty: {
                                message: "密碼不能爲空"
                            },
                            regexp: {
                                message: "密碼長度爲6~9位,由小寫字母、數字組成",
                                regexp: /^[a-z0-9]{6,9}$/
                            },
                            different: {
                                message: "密碼不能與手機號一致",
                                field: "user_tel"
                            }
                        }
                    },
                    qrCode: {
                        message: "驗證碼錯誤",
                        validators: {
                            notEmpty: {
                                message: "驗證碼不能爲空"
                            },
                            stringLength: {
                                message: "驗證碼錯誤",
                                min: 4,
                                max: 4
                            }
                        }
                    }
                }
            });
        })
    </script>

    <style type="text/css">
        .qrcode {
            background-color: white;
        }

        .user-form-wraps {
            width: 380px;
        }

        .user-form-button {
            width: 300px;
        }
    </style>

                <div class="user-form-item"><strong class="user-form-title">會員註冊</strong></div>
                <form id="myForm" action="${pageContext.request.contextPath}/user">
                    <input type="hidden" name="methodName" value="register"/>
                    <div class="user-form-item form-group">
                        <input id="user_tel" name="user_tel" class="user-input" type="text" placeholder="手機號">
                    </div>
                    <div class="user-form-item form-group">
                        <input name="user_password" class="user-input" type="password"
                               placeholder="密碼">
                    </div>
                    <div class="user-form-item form-group">
                        <input name="phoneCode" class="user-input user-input-adjust" type="text"
                               placeholder="短信驗證碼">
                        <button type="button" class="qrcode" onclick="sendSMS()">發送驗證碼</button>
                    </div>
                    <div class="user-form-item">
                        <label>
                            <input class="user-check" type="checkbox" checked="false" value="yes">
                            <span class="cos_span">
                                	登錄即表示同意<a class="keyword-blue-pale">《119婚慶網用戶協議》</a>
                                </span>
                        </label>
                    </div>
                    <div class="user-form-item form-group">
                        <button type="submit" class="user-form-button" style="font-weight: bold;">立即註冊</button>
                    </div>
                </form>
                <font color="red">${errorMsg}</font>
                <div class="user-form-item us_text_right">
                    <span class="cos_span"><a href="${pageContext.request.contextPath}/center?methodName=toLogin">已有賬戶?立即登錄</a></span>
                </div>

註冊頁面Servlet代碼

public String register(HttpServletRequest request, HttpServletResponse response) {
        try {

            /*
             * 1.使用BeanUtils封裝表單參數至User實體類(封裝表單user_tel和user_password參數)
             * 2.獲取表單參數(表單驗證碼)
             * 3.獲取Session使用阿里雲短信服務平臺的所發手機號驗證碼
             * 4.表單驗證碼與Session中驗證碼進行校驗
             */
            User user = new User();

            BeanUtils.populate(user, request.getParameterMap());

            String phoneCode      = request.getParameter("phoneCode");
            Object existPhoneCode = request.getSession().getAttribute("existPhoneCode");

            /*
             * 校驗成功,則進行註冊操作並重定向至登錄頁面
             * 校驗失敗,則記錄返回錯誤信息並請求轉發至註冊頁面
             */
            if (existPhoneCode.equals(phoneCode)) {
                userService.register(user);

                return "redirect:center?methodName=toLogin";
            } else {
                request.setAttribute("errorMsg", "驗證碼錯誤");

                return "register.jsp";
            }
        } catch (IllegalAccessException | InvocationTargetException | SQLException e) {
            e.printStackTrace();
        }

        /*
         * 捕獲用戶名已存在數據庫插入異常等,則返回錯誤信息
         */
        request.setAttribute("errorMsg", "註冊失敗 用戶名已存在");

        return "register.jsp";
    }

7.2 手機短信服務

  • 手機驗證碼是由阿里雲短信平臺提供。
  • 在阿里雲短信平臺開通服務
    • 獲取權限碼(AccessKey)
    • 獲取短信服務簽名
    • 獲取短信模板
  • 導入jar包
  • 使用SMSUtils工具類
  • 配置sms.properties配置文件

SMSUtils工具類

package com.mylifes1110.java.utils;

import java.io.IOException;
import java.io.InputStream;

import java.util.Properties;
import java.util.Random;

import javax.servlet.http.HttpSession;

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;

public class SmsUtil {

    // 產品名稱:雲通信短信API產品,開發者無需替換
    static final String product = "Dysmsapi";

    // 產品域名,開發者無需替換
    static final String domain = "dysmsapi.aliyuncs.com";
    static final String accessKeyId;
    static final String accessKeySecret;

    static {
        InputStream inputStream = SmsUtil.class.getClassLoader().getResourceAsStream("sms.properties");
        Properties  properties  = new Properties();

        try {
            properties.load(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }

        accessKeyId     = properties.getProperty("accessKeyId");
        accessKeySecret = properties.getProperty("accessKeySecret");
    }

    /**
     * 發送驗證碼
     *
     * @param session
     * @return
     * @throws ClientException
     */
    public static SendSmsResponse sendSms(HttpSession session, String phoneNum) throws ClientException {

        // 可自助調整超時時間
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");

        // 初始化acsClient,暫不支持region化
        IClientProfile profile = DefaultProfile.getProfile("cn-hangzhou", accessKeyId, accessKeySecret);

        DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);

        IAcsClient acsClient = new DefaultAcsClient(profile);

        // 組裝請求對象-具體描述見控制檯-文檔部分內容
        SendSmsRequest request = new SendSmsRequest();

        // 必填:待發送手機號
        request.setPhoneNumbers(phoneNum);

        // 必填:短信簽名-可在短信控制檯中找到
        request.setSignName("Ziph");

        // 必填:短信模板-可在短信控制檯中找到
        request.setTemplateCode("SMS_190786715");

        // 產生四位隨機驗證碼
        StringBuffer randomNum = new StringBuffer();

        for (int i = 0; i < 4; i++) {
            randomNum.append(new Random().nextInt(10));
        }

        request.setTemplateParam("{'code':" + randomNum + "}");

        // 四位隨機驗證碼存儲到session
        session.setAttribute("existPhoneCode", randomNum.toString());

        // hint 此處可能會拋出異常,注意catch
        SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

        return sendSmsResponse;
    }
}

sms.properties

accessKeyId與ccessKeySecret填寫自己的!

accessKeyId=LTAA4SDjx6A4FYdTBftaH2SS
accessKeySecret=yblECZFJHLW3Rti40UBNUXAleFftyWN

7.2 登錄功能

該頁面代碼沒有重要信息,貼出來好查看大概

<div class="user-form-item"><strong class="user-form-title">會員登錄</strong></div>
                <form action="${pageContext.request.contextPath}/user" method="post">
                    <input type="hidden" name="methodName" value="login">
                    <div class="user-form-item">
                        <input name="user_tel" class="user-input" type="text" max="15" maxlength="15" placeholder="手機號">
                    </div>
                    <div class="user-form-item">
                        <input name="user_password" class="user-input" type="password" max="15" maxlength="15"
                               placeholder="密碼">
                    </div>
                    <div class="user-form-item">
                        <input name="qrCode" class="user-input user-input-adjust" type="text" max="4" placeholder="驗證碼"><img
                            onclick="$('.qrcode').attr('src', '${pageContext.request.contextPath}/center?methodName=validateCode&' + Math.random())"
                            class="qrcode" style="cursor:pointer"
                            src="${pageContext.request.contextPath}/center?methodName=validateCode">
                    </div>
                    <font color="red">${errorMsg}</font>
                    <div class="user-form-item">
                        <label>
                            <input class="user-check" type="checkbox" checked="false" value="yes">
                            <span class="cos_span">
                                	登錄即表示同意<a class="keyword-blue-pale">《119婚慶網用戶協議》</a>
                                </span>
                        </label>
                    </div>
                    <div class="user-form-item">
                        <button type="submit" class="user-form-button" style="font-weight: bold;">&nbsp;&nbsp;</button>
                    </div>
                    <div class="user-form-item us_text_right">
                        <span class="cos_span"><a>忘記密碼?</a></span>&nbsp;&nbsp;<span
                            class="cos_span_empty"><a href="${pageContext.request.contextPath}/center?methodName=toRegister">註冊賬號</a></span>
                    </div>

登錄功能Servlet代碼

public String login(HttpServletRequest request, HttpServletResponse response) throws SQLException {
        try {
            User user = new User();

            BeanUtils.populate(user, request.getParameterMap());

            // 獲取表單內輸入的驗證碼
            String qrCode = request.getParameter("qrCode");

            // 獲取Session中的驗證碼
            Object existQrCode = request.getSession().getAttribute("key");

            /*
             * 校驗驗證碼
             * 成功,則跳轉首頁
             * 失敗,則跳轉登錄頁面
             */
            if (existQrCode != null) {
                if (existQrCode.equals(qrCode)) {
                    User existUser = userService.login(user);

                    /*
                     * 校驗數據庫查詢結果是否爲空數據
                     * 不爲空,則證明登錄成功!將用戶數據存入Session中並重定向至首頁
                     * 爲空,則證明登陸失敗!將錯誤信息保存至request中並默認轉發至登錄頁面
                     */
                    if (existUser != null) {
                        Cookie cookie = new Cookie("autoLogin", user.getUser_tel() + "-" + user.getUser_password());
                        cookie.setPath("/");
                        cookie.setMaxAge(60 * 60 * 24 * 7);
                        response.addCookie(cookie);

                        request.getSession().setAttribute("existUser", existUser);

                        return "redirect:center?methodName=toIndex";
                    } else {
                        request.setAttribute("errorMsg", "手機號或密碼錯誤");

                        return "login.jsp";
                    }
                } else {
                    request.setAttribute("errorMsg", "驗證碼錯誤");

                    return "login.jsp";
                }
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        // 拋出異常後登錄失敗
        request.setAttribute("errorMsg", "手機號或密碼錯誤");

        return "login.jsp";
    }

7.3 酒店列表

酒店列表後臺代碼

<c:forEach items="${pageBean.list}" var="hotel">
                    <li>
                        <div class="gdx-lists-wrap layout_clear">
                            <div class="gdx-lists-img layout_fl">
                                <a href="${pageContext.request.contextPath}/hotel?methodName=selectHotelDetailsByHotelId&hotelId=${hotel.hotel_id}"><img
                                        src="${pageContext.request.contextPath}/${hotel.img.img_add}"
                                        style="display:block"></a>
                            </div>
                            <div class="gdx-lists-data">
                                <h2>
                                    <a href="${pageContext.request.contextPath}/center?methodName=toHotelDetails" style="font-size: 20px">${hotel.hotel_name}</a>
                                </h2>
                                <div class="gdx-lists-local">
                                    <span class="page_icon in_local_icon"></span>${hotel.hotel_address}
                                </div>
                                <div class="gdx-lists-heart">
                                	<span class="page_icon add-heart-out">
                                    	<span class="page_icon add-heart-in" style="${hotel.hotel_star}"></span>
                                    </span>
                                    推薦指數
                                </div>
                                <div class="gdx-lists-info">
                                    <div class="gdx-lists-icon">
                                        <a href="field.html"><i class="page_icon in-data-Icon0"></i></a><a
                                            href="field.html"><i class="page_icon in-data-Icon1"></i></a><a
                                            href="field.html"><i class="page_icon in-data-Icon2"></i></a>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </li>
                </c:forEach>

酒店列表後臺代碼

public String selectHotelListByPage(HttpServletRequest request, HttpServletResponse response)
            throws IllegalAccessException, SQLException, InvocationTargetException {
        Integer currentPage = getCurrentPage(request.getParameter("currentPage"));

        /*
         * 分頁查詢酒店列表
         *
         */
        PageBean<Hotel> pageBean = hotelService.selectHotelListByPage(currentPage);

        request.setAttribute("pageBean", pageBean);

        return "hotelList.jsp";
    }

    public Integer getCurrentPage(String currentPageStr) {
        if (currentPageStr == null) {
            return 1;
        }

        return Integer.parseInt(currentPageStr);
    }

7.4 酒店詳情

酒店詳情前端代碼

<c:forEach items="${rooms}" var="room">
        <ul>
            <li>
                <div class="room-div1">
                    <div class="room-div2">
                        <div class="room-div3">
                            <img style="margin-left: 10px" alt="${room.room_name}"
                                 src="${pageContext.request.contextPath}/${room.img.img_add}">
                        </div>
                        <div class="room-div4">
                            <table border="1">
                                <tr>
                                    <td style="font-size: 25px" colspan="6" align="center">${room.room_name}</td>
                                </tr>
                                <tr align="center">
                                    <td class="room-td1">空高</td>
                                    <td class="room-td2">${room.room_height}</td>
                                    <td class="room-td1">低消</td>
                                    <td class="room-td3">${room.room_min_fee}</td>
                                    <td class="room-td1">形狀</td>
                                    <td class="room-td4">${room.room_form}</td>
                                </tr>
                                <tr align="center">
                                    <td class="room-td1">柱子</td>
                                    <td class="room-td2">${room.room_pillar}</td>
                                    <td class="room-td1">晚餐</td>
                                    <td class="room-td3">${room.room_dinner}</td>
                                    <td class="room-td1">電費</td>
                                    <td class="room-td4">${room.room_electric_fee}</td>
                                </tr>
                                <tr align="center">
                                    <td class="room-td1">拆分</td>
                                    <td class="room-td2">${room.room_split}</td>
                                    <td class="room-td1">面積</td>
                                    <td class="room-td3">${room.room_area}</td>
                                    <td class="room-td1">燈光</td>
                                    <td class="room-td4">${room.room_lamplight}</td>
                                </tr>
                                <tr align="center">
                                    <td class="room-td1">LED</td>
                                    <td class="room-td2">${room.room_LED}</td>
                                    <td class="room-td1">桌數</td>
                                    <td class="room-td3">${room.room_tables}</td>
                                    <td colspan="2"></td>
                                </tr>
                            </table>
                        </div>
                    </div>
                </div>
            </li>
        </ul>
    </c:forEach>
</div>

<div class="layout_center" style="margin-top: 50px">
    <table border="1" class="info-table">
        <tr>
            <td>星級</td>
            <td>${information.info_star_level}</td>
            <td>裝修時間</td>
            <td>${information.info_decorate_time}</td>
        </tr>
        <tr>
            <td>服務費</td>
            <td>${information.info_service_fee}</td>
            <td>定金</td>
            <td>${information.info_subscription}</td>
        </tr>
        <tr>
            <td>進場費</td>
            <td>${information.info_enter_fee}</td>
            <td>婚房化妝間</td>
            <td>${information.info_dressing_room}</td>
        </tr>
        <tr>
            <td>麥克風</td>
            <td>${information.info_microphone}</td>
            <td>投影儀</td>
            <td>${information.info_projector}</td>
        </tr>
        <tr>
            <td>桌布</td>
            <td>${information.info_tablecloth}</td>
            <td>電費</td>
            <td>${information.info_electric_charge}</td>
        </tr>
        <tr>
            <td>公交路線</td>
            <td colspan="3">${information.info_bus}</td>
        </tr>
        <tr>
            <td>棋牌娛樂</td>
            <td>${information.info_amusement}</td>
            <td colspan="2"></td>
        </tr>
    </table>
</div>

酒店詳情後端代碼

public String selectHotelDetailsByHotelId(HttpServletRequest request, HttpServletResponse response) throws SQLException, InvocationTargetException, IllegalAccessException {
        Integer hotelId = Integer.parseInt(request.getParameter("hotelId"));
        //查詢酒店信息
        Hotel hotel = hotelService.selectHotelById(hotelId);
        request.setAttribute("hotel", hotel);
        //查詢酒店房間列表
        List<Room> room = roomService.selectRoomListByHotelId(hotelId);
        request.setAttribute("rooms", room);
        //查詢酒店詳細信息
        Information information = informationService.selectInformationByHotelId(hotelId);
        request.setAttribute("information", information);
        //查詢套餐列表
        List<Package> packages = packageService.selectPackageListByHotelId(hotelId);
        request.setAttribute("packages", packages);
        return "hotelDetails.jsp";
    }

7.5 套餐詳情

套餐詳情前端代碼

	<script type="text/javascript">
	function menuClick(id) {
            //選中點擊的選項
            var check = $("#" + id).attr("class");
            if (check != "check") {
                $("#menu li").each(function (index) {
                    $(this).attr("class", "");
                });
                $("#" + id).attr("class", "check");
            }
        }

        function roomClick(roomId) {
            console.log("roomClick" + roomId);
            var check = $("#" + roomId).attr("class");
            if (check != "check") {
                $("#room li").each(function (index) {
                    $(this).attr("class", "");
                });
                $("#" + roomId).attr("class", "check");
            }
        }

        function plus() {
            var count = $("#count").val();
            if (count >= 0 && count < 99) {
                count++;
                $("#count").val(count);
            }
        }

        function reduce() {
            var count = $("#count").val();
            if (count > 1 && count <= 99) {
                count--;
                $("#count").val(count);
            }
        }

        function addCart() {
            var shoppingcart_time = getTime();
            var shoppingcart_type = $("#menu li[class='check']").text();
            var shoppingcart_place = $("#room li[class='check']").text();
            var shoppingcart_count = $("#count").val();
            $.post("${pageContext.request.contextPath}/cart", {
                "methodName": "addCart",
                "shoppingcart_time": shoppingcart_time,
                "shoppingcart_name": "${packages.package_name}",
                "shoppingcart_type": shoppingcart_type,
                "shoppingcart_place": shoppingcart_place,
                "shoppingcart_price": "${packages.package_price}",
                "shoppingcart_count": shoppingcart_count,
                "shoppingcart_img": "${packages.img.img_add}",
                "shoppingcart_hotelname": "${hotel.hotel_name}"
            }, function (data) {
                console.log(data);
                if (data.flag) {
                    //加入購物車成功,跳轉購物車頁面
                    location.href = "${pageContext.request.contextPath}/cart?methodName=selectCartList";
                } else {
                    //加入購物車失敗,彈窗提示加入購物車失敗
                    alert("添加購物車失敗");
                }
            }, "json");
        }

        function getTime() {
            var date = new Date();
            var year = date.getFullYear();
            var month = date.getMonth();
            var day = date.getDate();
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var seconds = date.getSeconds();
            var arr1 = [year, month, day];
            var arr2 = [hours, minutes, seconds];
            var timeStr = arr1.join("/") + " " + arr2.join(":");
            return timeStr;
        }
    </script>

<div id="page-godMx">
    <div class="layout_center">
        <div class="path">
            <span><a>婚禮匯</a></span>
            <em>></em>
            <span><a>婚宴場地</a></span>
            <em>></em>
            <span><a>特色套餐</a></span>
            <em>></em>
            <a class="cur">${packages.package_name}</a>
        </div>
        <div id="gods-header" class="gods-header layout_clear" style="margin-top:0px;">
            <h2 class="gods-header-tit">${hotel.hotel_name}</h2>
            <div class="gods-header-fl layout_fl">
                <div id="gods-display-img">
                    <img src="${pageContext.request.contextPath}/${packages.img.img_add}">
                </div>
                <div id="gods-display-list">
                    <ul class="layout_clear fl_li">
                        <li class="win_current">
                            <img src="${pageContext.request.contextPath}/${packages.img.img_add}">
                        </li>
                    </ul>
                </div>
                <div class="gods-attrid">
                    <span class="fl">商品編號:${packages.package_id}</span>
                    <span class="fr">
                        	<span class="gods-share"><i class="page_icon"></i>分享</span>
                            <span class="gods-follow" style="cursor:pointer"><i class="page_icon"></i>收藏商品</span>
                        </span>
                </div>
            </div>
            <div class="gods-header-cn layout_fl">
                <div class="gods-uhbasic">
                    <p class="gods-uhbasic-tit">${packages.package_name}</p>
                    <p class="gods-uhbasic-stat">${packages.package_content}</p>
                </div>
                <div class="gods-uhsale layout_clear">
                    <div class="gods-uhsale-fl layout_fl">
                        <div class="gods-uhprice-item">
                            <span class="gods-uhprice-label">原價</span>
                            <%--原價數據庫中沒有--%>
                            <h4>¥2999.00</h4>
                        </div>
                        <div class="gods-uhprice-item">
                            <span class="gods-uhprice-label">平臺價</span>
                            <h2><em class="gods-uhprice-str"></em>${packages.package_price}</h2>
                        </div>
                    </div>
                    <div class="gods-uhsale-fr layout_fl">
                        <span>累計評價</span>
                        <h3>0</h3>
                    </div>
                </div>
                <div class="gods-pro">
                    <dl class="gods-pro-item layout_clear">
                        <dt class="gods-pro-label">聯繫地址</dt>
                        <dd class="gods-pro-param gods-pro-primary layout_fl">${hotel.hotel_address}</dd>
                    </dl>
                    <dl class="gods-pro-item layout_clear">
                        <dt class="gods-pro-label">服務</dt>
                        <dd class="gods-pro-param gods-pro-primary layout_fl"><a class="gods-pro-key1">${hotel.hotel_name}</a>提供售後服務<a class="gods-pro-key0">聯繫賣家</a>
                        </dd>
                    </dl>
                    <dl class="gods-pro-item layout_clear">
                        <dt class="gods-pro-label gods-pro-clear0">套餐類型</dt>
                        <dd class="gods-pro-param gods-pro-primary layout_fl">
                            <ul class="gods-pro-list gods-pro-list0" id="menu">
                                <c:if test="${packages.package_menuA != null && packages.package_menuB !=null}">
                                    <li id="menuA" class="check" onclick="menuClick('menuA')"><a><span>A款</span></a></li>
                                    <li id="menuB" onclick="menuClick('menuB')"><a><span>B款</span></a></li>
                                </c:if>
                                <c:if test="${packages.package_menuA != null && packages.package_menuB == null}">
                                    <li id="menuA" class="check"><a><span>A款</span></a></li>
                                </c:if>
                                <c:if test="${packages.package_menuA == null && packages.package_menuB != null}">
                                    <li id="menuB" class="check"><a><span>B款</span></a></li>
                                </c:if>
                                <c:if test="${packages.package_menuA == null && packages.package_menuB == null}">
                                    <li class="check"><a><span></span></a></li>
                                </c:if>
                            </ul>
                        </dd>
                    </dl>
                    <dl class="gods-pro-item layout_clear">
                        <dt class="gods-pro-label gods-pro-clear0">婚宴場地</dt>
                        <dd class="gods-pro-param gods-pro-primary layout_fl">
                            <ul class="gods-pro-list gods-pro-list0" id="room">
                                <c:forEach items="${rooms}" var="room" varStatus="status">
                                    <c:if test="${status.index == 0}">
                                        <li id="${room.room_id}" class="check" onclick="roomClick('${room.room_id}')"><a><span>${room.room_name}</span></a></li>
                                    </c:if>
                                    <c:if test="${status.index != 0}">
                                        <li id="${room.room_id}" onclick="roomClick('${room.room_id}')"><a><span>${room.room_name}</span></a></li>
                                    </c:if>
                                </c:forEach>
                            </ul>
                        </dd>
                    </dl>
                    <dl class="gods-pro-item layout_clear">
                        <dt class="gods-pro-label gods-pro-clear2">數量</dt>
                        <dd class="gods-pro-param gods-pro-primary layout_fl">
                            	<span class="gods-counter">
                                	<input id="count" type="text" class="gods-counter-text" name="BuyCarNum" value="1"
                                           maxlength="3" min="1">
                                    <span class="gods-counter-btn">
                                    	<span class="gods-counter-push page_icon" title=""
                                              onclick="plus()"></span>
                                        <span class="gods-counter-reduce page_icon" title=""
                                              onclick="reduce()"></span>
                                    </span>
                                    <span class="gods-counter-outs"></span>
                                    <span class="gods-counter-num" id="stock">(庫存99件)</span>
                                </span>
                        </dd>
                    </dl>
                    <dl class="gods-pro-item layout_clear">
                        <dt class="gods-pro-label">服務承諾</dt>
                        <dd class="gods-pro-param gods-pro-middle layout_fl">正品保障 溝通預訂 資金管理 滿意後付款</dd>
                    </dl>
                    <dl class="gods-pro-item layout_clear">
                        <dd class="gods-pro-item layout_clear">
                            <a class="gods-pro-payfor">立即購買</a><a onclick="addCart()" class="gods-pro-payfor"
                               href="javascript:void(0);">加入購物車</a>
                        </dd>
                    </dl>
                </div>
            </div>
            <div class="gods-header-fr layout_fl">
                <div class="gods-shop">
                    <div class="gods-shop-tit">重慶南溫泉麗筠酒店</div>
                    <div class="gods-shop-logo"><img src="${pageContext.request.contextPath}/img/msF58469607Jg.jpg"
                                                     style="width:100%;height: 100%;"></div>
                    <div class="gods-shop-go"><a class="cur">進入店鋪</a> <a>收藏店鋪</a></div>
                </div>
                <div class="gods-aside-inset"><img src="${pageContext.request.contextPath}/img/qER49920125Kw.jpg"
                                                   style="margin:auto"></div>
                <ul class="gods-other-list">
                    <li>
                        <a>
                            <div>
                                <img src="${pageContext.request.contextPath}/img/LSN54767537nb.jpg" style="width:100%">
                                <span class="gods-inc"><span class="gods-inc-text" title="湘域中餐廳">湘域中餐廳</span></span>
                            </div>
                        </a>
                    </li>
                    <li>
                        <a>
                            <div>
                                <img src="${pageContext.request.contextPath}/img/Hbp54860401oB.jpg" style="width:100%">
                                <span class="gods-inc"><span class="gods-inc-text" title="中天大酒樓">中天大酒樓</span></span>
                            </div>
                        </a>
                    </li>
                </ul>
            </div>
        </div>
        <div id="gods-section" class="gods-section layout_clear">
            <div class="gods-grids-fl layout_fl">
                <div class="gods-aside-hd">相似產品<a class="layout_fr">更多</a></div>
                <ul class="gods-aside-list">
                    <li>
                        <a>
                            <div class="gods-aside-img">
                                <img src="${pageContext.request.contextPath}/img/iQP54584096YB.jpg"
                                     style="width: 100%; display: block;">
                            </div>
                            <div class="gods-aside-dis">
                                <p class="gods-aside-price"><span>¥0.00</span></p>
                                <p class="gods-aside-text">大廳</p>
                            </div>
                        </a>
                    </li>
                    <li>
                        <a>
                            <div class="gods-aside-img">
                                <img src="${pageContext.request.contextPath}/img/iQP54584096YB.jpg"
                                     style="width: 100%; display: block;">
                            </div>
                            <div class="gods-aside-dis">
                                <p class="gods-aside-price"><span>¥0.00</span></p>
                                <p class="gods-aside-text">大廳</p>
                            </div>
                        </a>
                    </li>
                    <li>
                        <a>
                            <div class="gods-aside-img">
                                <img src="${pageContext.request.contextPath}/img/iQP54584096YB.jpg"
                                     style="width: 100%; display: block;">
                            </div>
                            <div class="gods-aside-dis">
                                <p class="gods-aside-price"><span>¥0.00</span></p>
                                <p class="gods-aside-text">大廳</p>
                            </div>
                        </a>
                    </li>
                    <li>
                        <a>
                            <div class="gods-aside-img">
                                <img src="${pageContext.request.contextPath}/img/iQP54584096YB.jpg"
                                     style="width: 100%; display: block;">
                            </div>
                            <div class="gods-aside-dis">
                                <p class="gods-aside-price"><span>¥0.00</span></p>
                                <p class="gods-aside-text">大廳</p>
                            </div>
                        </a>
                    </li>
                    <li>
                        <a>
                            <div class="gods-aside-img">
                                <img src="${pageContext.request.contextPath}/img/iQP54584096YB.jpg"
                                     style="width: 100%; display: block;">
                            </div>
                            <div class="gods-aside-dis">
                                <p class="gods-aside-price"><span>¥0.00</span></p>
                                <p class="gods-aside-text">大廳</p>
                            </div>
                        </a>
                    </li>
                </ul>
            </div>
            <div class="gods-grids-fr layout_fl">
                <div class="gods-grids-swit">
                    <ul class="layout_clear fl_li">
                        <li class="current">
                            <a>商品介紹</a>
                        </li>
                        <li>
                            <a>評價(0)</a>
                        </li>
                    </ul>
                </div>
                <div class="gods-swit-coloum">
                    <div style="display:block">
                        <div class="gods-gdx-img">
                            <p>
                                <img src="${pageContext.request.contextPath}/img/BJl58409211yq.jpg"
                                     style="height:1280px; width:904px">
                            </p>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

套餐詳情後端代碼

public String selectPackageById(HttpServletRequest request, HttpServletResponse response)
            throws SQLException, InvocationTargetException, IllegalAccessException {
        Integer packageId = Integer.parseInt(request.getParameter("packageId"));
        Package aPackage  = packageService.selectPackageById(packageId);
        Integer hotelId   = Integer.parseInt(request.getParameter("hotelId"));
        Hotel   hotel     = hotelService.selectHotelById(hotelId);

        request.setAttribute("hotel", hotel);

        List<Room> rooms = roomService.selectRoomListByHotelId(hotelId);

        request.setAttribute("packages", aPackage);
        request.setAttribute("hotel", hotel);
        request.setAttribute("rooms", rooms);

        return "packageDetails.jsp";
    }

7.6 購物車

購物車前端代碼

<script type="text/javascript">
        function reduce(cardId) {
            var count = $("#" + cardId + "_count").text();
            if (count > 1) {
                count--;
                $("#" + cardId + "_count").text(count);

                updateCart(cardId, count);
            }
        }

        function plus(cardId) {
            var count = $("#" + cardId + "_count").text();
            count++;
            $("#" + cardId + "_count").text(count);

            updateCart(cardId, count);
        }

        function totalPrice(cardId, count) {
            var price = $("#" + cardId + "_price").text();
            var totalPrice = count * price;
            $("#" + cardId + "_totalPrice").text(totalPrice);
        }

        /**
         * 設置選中的框的總價
         */
        function setTotalPrice() {
            var totalPrice = 0.00;
            $(".ids:checked").each(function (index) {
                var cartId = $(this).val();
                //選中的總價(字符串)
                var price = $("#" + cartId + "_totalPrice").text();
                //將字符串轉換爲數值Number()
                totalPrice += Number(price);
            });
            $("#total").text("¥" + totalPrice);
        }

        /**
         * 全選
         */
        function selectAll() {
            var all = $("#all");
            var check = all.prop("checked");
            $(".ids").each(function (index) {
                $(this).prop("checked", check);
            });
            setTotalPrice();
        }

        function updateCart(cardId, count) {
            //更新數據庫
            $.post("${pageContext.request.contextPath}/cart?methodName=updateCart", {
                "shoppingcart_id": cardId,
                "shoppingcart_count": count
            }, function (data) {
                if (data.flag) {
                    totalPrice(cardId, count);
                    setTotalPrice();
                }
            }, "json");
        }
    </script>

<c:forEach items="${carts}" var="cart">
                            <li>
                                <div class="layout_clear">
                                    <div class="us_buycar_check layout_fl">
                                        <input type="checkbox" class="ids" value="${cart.shoppingcart_id}"
                                               onchange="setTotalPrice()">
                                    </div>
                                    <div class="us_unit_table layout_fl">
                                        <div class="us_order_line">
                                            <span>${cart.shoppingcart_time}</span><span>訂單號:${cart.shoppingcart_id}</span><span></span>
                                        </div>
                                        <table>
                                            <tbody>
                                            <tr>
                                                <td><span class="cos_span">商品信息</span></td>
                                                <td><span class="cos_span">套餐類型/婚宴場地</span></td>
                                                <td><span class="cos_span">單價</span></td>
                                                <td><span class="cos_span">數量</span></td>
                                                <td><span class="cos_span">總金額</span></td>
                                                <td><span class="cos_span">操作</span></td>
                                            </tr>
                                            <tr>
                                                <td>
                                                    <div class="img"><img
                                                            src="${pageContext.request.contextPath}/${cart.shoppingcart_img}"
                                                            style="width:100px;"><span>${cart.shoppingcart_name}</span>
                                                    </div>
                                                </td>
                                                <td><span class="cos_span">套餐類型:${cart.shoppingcart_type}</span><span
                                                        class="cos_span">婚宴場地:${cart.shoppingcart_place}</span></td>
                                                <td><span class="cos_span" style="display:block"><ins></ins></span><span
                                                        class="cos_span"
                                                        id="${cart.shoppingcart_id}_price">${cart.shoppingcart_price}</span>
                                                </td>
                                                <td>
                                                        <span class="cos_span">
                                                            <span class="amont_line">
                                                                <span class="amont_line_btn amont_line_reduce"
                                                                      onclick="reduce('${cart.shoppingcart_id}')">-</span>
                                                                <span id="${cart.shoppingcart_id}_count"
                                                                      class="amont_line_text">${cart.shoppingcart_count}</span>
                                                                <span class="amont_line_btn amont_line_push"
                                                                      onclick="plus('${cart.shoppingcart_id}')">+</span>
                                                            </span>
                                                        </span>
                                                </td>
                                                <td><span class="cos_span"><em
                                                        class="keyword-pink"
                                                        id="${cart.shoppingcart_id}_totalPrice">${cart.shoppingcart_count * cart.shoppingcart_price}</em></span>
                                                </td>
                                                <td><span class="cos_span"><a>移入收藏夾</a>/<a>刪除</a></span></td>
                                            </tr>
                                            </tbody>
                                        </table>
                                    </div>
                                </div>
                            </li>
                        </c:forEach>
                    </ul>
                </div>
                <div class="us_bottom_bar layout_clear">
                    <div class="us_buycar_check layout_fl"><input id="all" type="checkbox" onchange="selectAll()"></div>
                    <div class="us_buycar_state layout_fl">
                        <span class="cos_span"><a>全選</a></span>
                        <span class="cos_span"><a>清空購物車</a></span>
                    </div>
                    <div class="us_buycar_buy layout_fr">
                        <span class="cos_span">已選擇<span></span>件商品</span>
                        <span class="cos_span">總價:<em class="keyword-pink" id="total">¥0.00</em></span>
                        <a class="us_button" href="${pageContext.request.contextPath}/center?methodName=toPayPage">去結算</a>
                    </div>
                </div>
            </div>

購物車後端代碼

@ResponseBody
    public Map<String, Object> addCart(HttpServletRequest request, HttpServletResponse response)
            throws InvocationTargetException, IllegalAccessException, SQLException {
        Map<String, Object> map = new HashMap<>();
        boolean             flag;
        Shoppingcart        cart = new Shoppingcart();

        BeanUtils.populate(cart, request.getParameterMap());

        User user = (User) request.getSession().getAttribute("existUser");

        cart.setShoppingcart_id(CommonUtils.uuid());
        cart.setTb_user_user_tel(user.getUser_tel());

        String msg = cartService.addCart(cart);

        if ("添加成功".equals(msg)) {
            flag = true;
        } else {
            flag = false;
        }

        map.put("flag", flag);
        map.put("msg", msg);

        return map;
    }

    public String selectCartList(HttpServletRequest request, HttpServletResponse response) throws SQLException {
        User               user     = (User) request.getSession().getAttribute("existUser");
        List<Shoppingcart> cartList = cartService.selectCartList(user.getUser_tel());

        request.setAttribute("carts", cartList);

        return "shoppingCart.jsp";
    }

    @ResponseBody
    public Map<String, Object> updateCart(HttpServletRequest request, HttpServletResponse response)
            throws InvocationTargetException, IllegalAccessException, SQLException {
        Map<String, Object> map = new HashMap<>();
        boolean             flag;
        Shoppingcart        cart = new Shoppingcart();

        BeanUtils.populate(cart, request.getParameterMap());

        String msg = cartService.updateCart(cart);

        if ("更新成功".equals(msg)) {
            flag = true;
        } else {
            flag = false;
        }

        map.put("flag", flag);
        map.put("msg", msg);

        return map;
    }

八、項目注意事項

8.1 解決Servlcet創建過多

爲了解決項目中使用的Servlet創建過多,我們使用反射技術來解決此問題。解決思想即是,把項目中的模塊細分成各個模塊整體,這時候只需要創建各個模塊對應的Servlet即可。那麼問題來了,重定向或請求轉發路徑怎麼解決呢?解決這個問題我們需要爲各個模塊的Servlet需要跳轉的路徑使用反射技術來處理請求。這樣業務就會精簡很多!

package com.mylifes1110.java.controller;

import java.io.File;
import java.io.IOException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mylifes1110.java.annotation.ResponseBody;
import com.mylifes1110.java.utils.JsonUtils;

@WebServlet(
        name = "BaseServlet",
        value = "/base"
)
public class BaseServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String methodName = request.getParameter("methodName");

        try {
            Method method = this.getClass().getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);

            /*
             * 判斷是否有該方法名稱的方法,有則執行該方法
             */
            if (method != null) {
                Object returnValue = method.invoke(this, request, response);

                /*
                 * 判斷是否有返回值
                 * 有,則判斷在方法上是否有註解
                 * 無,不做任何處理
                 */
                if (returnValue != null) {

                    /*
                     * 判斷標記註解是否存在
                     * 有,則返回json字符串
                     * 無,則處理返回資源路徑
                     */
                    boolean present = method.isAnnotationPresent(ResponseBody.class);

                    if (present) {

                        /*
                         * 判斷返回值是否爲json字符串
                         * 是,則直接返回json字符串,將json字符串作響應正文響應給瀏覽器
                         * 否,則直接返回Java對象,將Java對象轉換爲json字符串,將json字符串作響應正文響應給瀏覽器
                         */
                        if (returnValue.getClass() == String.class) {
                            response.setContentType("application/json; charset=UTF-8");
                            response.getWriter().write(returnValue + "");
                        } else {
                            JsonUtils.writeJsonStr(response, returnValue);
                        }
                    } else {

                        /*
                         * 處理資源路徑
                         * 1.將返回值對象強轉爲資源路徑字符串
                         * 2.判斷並獲取資源路徑“:”的索引位置
                         * 3.根據":"後的第一位開始進行拆分、獲取真正的資源路徑
                         */
                        String value = (String) returnValue;
                        int index = value.lastIndexOf(":");
                        String path = value.substring(index + 1);

                        /*
                         * 判斷是否包含":"
                         * 包含,則判斷資源路徑的重定向和轉發
                         * 不包含,則默認資源路徑爲請求轉發
                         */
                        if (index != -1) {
                            if (value.startsWith("redirect")) {
                                response.sendRedirect(request.getContextPath() + File.separator + path);
                            } else if (value.startsWith("forward")) {
                                request.getRequestDispatcher("/WEB-INF/jsp/" + path).forward(request, response);
                            }
                        } else {
                            request.getRequestDispatcher("WEB-INF/jsp/" + value).forward(request, response);
                        }
                    }
                }
            }
        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}

需要做的就是繼承上面的BaseServlet,然後根據業務需求寫自己的方法即可,乍一看像SpringMVC,但是要注意這裏的方法名和返回值,方法名決定了請求時的method參數的值,返回值由於是資源路徑或JSON,所以用的是String。這裏用UserServlet來做的例子!

package com.mylifes1110.java.controller;

import java.lang.reflect.InvocationTargetException;

import java.sql.SQLException;

import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.beanutils.BeanUtils;

import com.mylifes1110.java.bean.User;
import com.mylifes1110.java.service.UserService;
import com.mylifes1110.java.service.impl.UserServiceImpl;

@WebServlet(
    name  = "UserServlet",
    value = "/user"
)
public class UserServlet extends BaseServlet {
    private UserService userService = new UserServiceImpl();

    public String login(HttpServletRequest request, HttpServletResponse response) throws SQLException {
        try {
            User user = new User();

            BeanUtils.populate(user, request.getParameterMap());

            // 獲取表單內輸入的驗證碼
            String qrCode = request.getParameter("qrCode");

            // 獲取Session中的驗證碼
            Object existQrCode = request.getSession().getAttribute("key");

            /*
             * 校驗驗證碼
             * 成功,則跳轉首頁
             * 失敗,則跳轉登錄頁面
             */
            if (existQrCode != null) {
                if (existQrCode.equals(qrCode)) {
                    User existUser = userService.login(user);

                    /*
                     * 校驗數據庫查詢結果是否爲空數據
                     * 不爲空,則證明登錄成功!將用戶數據存入Session中並重定向至首頁
                     * 爲空,則證明登陸失敗!將錯誤信息保存至request中並默認轉發至登錄頁面
                     */
                    if (existUser != null) {
                        Cookie cookie = new Cookie("autoLogin", user.getUser_tel() + "-" + user.getUser_password());
                        cookie.setPath("/");
                        cookie.setMaxAge(60 * 60 * 24 * 7);
                        response.addCookie(cookie);

                        request.getSession().setAttribute("existUser", existUser);

                        return "redirect:center?methodName=toIndex";
                    } else {
                        request.setAttribute("errorMsg", "手機號或密碼錯誤");

                        return "login.jsp";
                    }
                } else {
                    request.setAttribute("errorMsg", "驗證碼錯誤");

                    return "login.jsp";
                }
            }
        } catch (IllegalAccessException | InvocationTargetException e) {
            e.printStackTrace();
        }

        // 拋出異常後登錄失敗
        request.setAttribute("errorMsg", "手機號或密碼錯誤");

        return "login.jsp";
    }

    public String register(HttpServletRequest request, HttpServletResponse response) {
        try {

            /*
             * 1.使用BeanUtils封裝表單參數至User實體類(封裝表單user_tel和user_password參數)
             * 2.獲取表單參數(表單驗證碼)
             * 3.獲取Session使用阿里雲短信服務平臺的所發手機號驗證碼
             * 4.表單驗證碼與Session中驗證碼進行校驗
             */
            User user = new User();

            BeanUtils.populate(user, request.getParameterMap());

            String phoneCode      = request.getParameter("phoneCode");
            Object existPhoneCode = request.getSession().getAttribute("existPhoneCode");

            /*
             * 校驗成功,則進行註冊操作並重定向至登錄頁面
             * 校驗失敗,則記錄返回錯誤信息並請求轉發至註冊頁面
             */
            if (existPhoneCode.equals(phoneCode)) {
                userService.register(user);

                return "redirect:center?methodName=toLogin";
            } else {
                request.setAttribute("errorMsg", "驗證碼錯誤");

                return "register.jsp";
            }
        } catch (IllegalAccessException | InvocationTargetException | SQLException e) {
            e.printStackTrace();
        }

        /*
         * 捕獲用戶名已存在數據庫插入異常等,則返回錯誤信息
         */
        request.setAttribute("errorMsg", "註冊失敗 用戶名已存在");

        return "register.jsp";
    }
}

8.2 解決頁面放在web中不安全問題

我們知道IDEA中web是放JSP或HTML頁面資源的。但是我們實際做項目中,是有一個安全隱患的存在。因爲在web文件夾中,我們可以任意輸入地址欄中的路徑訪問資源。這就導致了一種訪問安全問題。爲了解決此問題,我們需要知道的資源放在WEB-INF文件夾中是不可以外界訪問的,而我們在資源跳轉的時候,可以藉助CenterServlet與BaseServlet聯合跳轉。這裏解釋一下,CenterServlet裏僅做資源跳轉。代碼如下:

package com.mylifes1110.java.controller;

import java.io.IOException;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(
    name  = "CenterServlet",
    value = "/center"
)
public class CenterServlet extends BaseServlet {

    /**
     * 轉發酒店詳情頁面
     * @return 返回酒店詳情頁面資源路徑
     */
    public String toHotelDetails(HttpServletRequest request, HttpServletResponse response) {
        return "hotelDetails.jsp";
    }

    /**
     * 轉發婚宴場地頁面
     * @return 返回婚宴場地頁面資源路徑
     */
    public String toHotelList(HttpServletRequest request, HttpServletResponse response) {
        return "hotelList.jsp";
    }

    /**
     * 轉發首頁
     * @return 返回首頁資源路徑
     */
    public String toIndex(HttpServletRequest request, HttpServletResponse response) {
        return "index.jsp";
    }

    /**
     * 轉發登錄頁面
     *
     * @return 返回登錄頁面資源路徑
     */
    public String toLogin(HttpServletRequest request, HttpServletResponse response) {
        return "login.jsp";
    }

    /**
     * 轉發註冊頁面
     * @return 返回註冊頁面資源路徑
     */
    public String toRegister(HttpServletRequest request, HttpServletResponse response) {
        return "register.jsp";
    }

    /**
     * 轉發購物車頁面
     * @return 返回購物車頁面資源路徑
     */
    public String toShoppingCart(HttpServletRequest request, HttpServletResponse response) {
        return "shoppingCart.jsp";
    }

    /**
     * 轉發生成驗證碼
     * @return 返回生成驗證碼資源路徑
     */
    public String validateCode(HttpServletRequest request, HttpServletResponse response) {
        return "validatecode.jsp";
    }

    /**
     * 轉發支付頁面
     * @return 返回支付頁面資源路徑
     */
    public String toPayPage(HttpServletRequest request, HttpServletResponse response) {
        return "payPage.jsp";
    }
}

8.3 Filter實現自動登錄

理論與現實中可以說明,我們在訪問京東、淘寶等電商平臺的時候,不用登錄就可以訪問首頁等瀏覽,但是當我們在沒有登錄的時候,點擊查看購物車或者加入購物車時,他會自動頁面跳轉到登錄頁面讓你進行登錄。實現此功能我們就需要藉助Filter過濾器來實現,我們可以把不要登錄就可以訪問的資源放在一起。需要登錄才能訪問的資源再放在一起。在Filter中設置攔截所有Servlet,把不要登錄就可以訪問的資源放行掉。其他的資源需要進行強制登錄纔可以訪問。這裏所說的強制登錄,就是跳轉登錄頁面了!還有自動登錄就是,生活中發現我們登錄過一次淘寶,下一次就不需要登錄就發現已經在登錄狀態,也是Filter的作用!接下載看Filter的神操作!代碼如下:

Filter代碼

package com.mylifes1110.java.filter;

import java.io.IOException;

import java.sql.SQLException;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.mylifes1110.java.bean.User;
import com.mylifes1110.java.service.UserService;
import com.mylifes1110.java.service.impl.UserServiceImpl;
import com.mylifes1110.java.utils.CookieUtils;

@WebFilter(
    filterName = "LoginFilter",
    value      = "/*"
)
public class LoginFilter implements Filter {
    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
            throws ServletException, IOException {
        HttpServletRequest  request    = (HttpServletRequest) req;
        HttpServletResponse response   = (HttpServletResponse) resp;
        String              methodName = request.getParameter("methodName");

        /*
         * 判斷請求路徑是否包含登錄相關資源和是否爲不需要登錄就可以訪問的資源
         * 是,則放行
         * 否,則繼續處理判斷是否在登錄狀態
         */
        if (((methodName != null) && methodName.contains("login"))
                || ((methodName != null) && methodName.contains("toLogin"))
                || ((methodName != null) && methodName.contains("validateCode"))
                || ((methodName != null) && methodName.contains("toRegister"))
                || ((methodName != null) && methodName.contains("register"))
                || ((methodName != null) && methodName.contains("toIndex"))) {
            chain.doFilter(request, response);
        } else {
            User user = (User) request.getSession().getAttribute("existUser");

            /*
             * 判斷是否在登錄狀態
             * 是,則放行
             * 否,則獲取Cookie進行自動登錄
             */
            if (user != null) {
                chain.doFilter(request, response);
            } else {
                Cookie cookie = CookieUtils.getCookie(request.getCookies(), "autoLogin");

                /*
                 * 判斷Cookie是否爲空
                 * 爲空,則Cookie在瀏覽器中被清理,則轉發登錄頁面
                 * 不爲空,則獲取Cookie中存儲的賬號與密碼進行自動登錄
                 */
                if (cookie == null) {
                    request.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(request, response);
                } else {
                    String   cookieValue = cookie.getValue();
                    String[] split       = cookieValue.split("-");
                    String   username    = split[0];
                    String   password    = split[1];
                    User     loginUser   = new User();

                    loginUser.setUser_tel(username);
                    loginUser.setUser_password(password);

                    UserService userService = new UserServiceImpl();

                    try {
                        User existUser = userService.login(loginUser);

                        /*
                         * 校驗數據庫中是否存在該賬號密碼
                         * 存在,則修改登錄狀態,重新存在Session中
                         * 不存在,意爲中途修改了密碼,則轉發登錄頁面
                         */
                        if (existUser != null) {
                            request.getSession().setAttribute("existUser", existUser);
                            chain.doFilter(request, response);
                        } else {
                            request.getRequestDispatcher("WEB-INF/jsp/login.jsp").forward(request, response);
                        }
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    @Override
    public void init(FilterConfig config) throws ServletException {}
}

登錄頁面核心代碼

Cookie cookie = new Cookie("autoLogin", user.getUser_tel() + "-" + user.getUser_password());
cookie.setPath("/");
cookie.setMaxAge(60 * 60 * 24 * 7);
response.addCookie(cookie);

request.getSession().setAttribute("existUser", existUser);

return "redirect:center?methodName=toIndex";

九、本項目注意事項

9.1 如何將HTML頁面改爲JSP頁面

本項目的頁面資源初始爲HTML頁面,而我們的技術是使用JSP技術來完成頁面的。所以我們需要修改HTML頁面爲JSP頁面,至於如何修改呢?很簡單,將JSP中最上方的一行page指令替換掉HTML頁面的<!doctype html>標籤,然後將html後綴改爲jsp即可!

9.2 解決資源損壞導致樣式亂掉

在將HTML頁面修改完JSP頁面時,HTML的默認資源路徑會變爲…/…/xxx。而導致資源的訪問路徑失效,顯示會出現問題。在此,我們可以將…/…/統一修改爲${pageContext.request.contextPath}/。修改後即可恢復頁面加載!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章