Java web項目綜合練習(Estore)


Java web項目綜合練習(Estore

 

 

復習day18:

 

  1. ajax代碼的書寫步驟

 

 

2)json格式文本,轉js對象的方法是那個

      

 

 

  1. 項目開發流程介紹

 

這里學習的JavaWEB項目實戰,主要是把前面學習的所有的web相關的技術綜合的練習。

    

  1. 業務洽談:客戶(企業)提出需求,軟件公司派人前去洽談,第一次確認需求。
  2. 整理需求:軟件公司,不斷的和客戶進行溝通,反復的確認需求,需要美工和前端工程師制作頁面
  3. 詳細設計:技術選型和項目原型架構
  4. 編碼階段:開工啦
  5. 測試階段:測試當前的項目,解決bug
  6. 試運行,上線。

 

在開發的流程中的人員配置:

    洽談業務: 老板、項目經理、技術總監、技術總監(需求工程師團隊)

    詳細設計: 項目經理、技術總監、老員工

    編碼: 碼農開工啦

    測試階段:測試工程師,碼農開工啦

 

技術選型:選擇適合當前項目的技術

項目的原型架構:導入jar包(項目需要用到哪些技術),准備配置文件,工具類,基本的接口(業務接口)

業務接口:程序員在開發的時候,當前項目需要的大部分接口,已經開發完成(技術總監),程序員只需要根據接口寫實現類

  1. 准備工作

    1. 項目搭建

      1. 新建項目

 

  1. 拷貝項目靜態資源

將文件夾中的所有數據復制到項目WebRoot文件夾下

復制完成之后,注意要修改當前項目的編碼,設置成UTF-8

 

修改完成之后,部署項目,能看到如下界面,說明拷貝靜態資源沒有問題。

搜索功能:后期使用lucence和slor這兩個技術來完成。

 

  1. 功能分析

買家功能:

  1. 注冊
  2. Ajax校驗用戶名
  3. 登錄
  4. 記住用戶名
  5. 注銷(退出)
  6. 查看商品列表
  7. 查看商品的詳細
  8. 加入購物車
  9. 查看購物車列表
  10. 修改購買的數量
  11. 刪除購物車中的商品
  12. 三級聯動
  13. 提交訂單
  14. 查看訂單列表
  15. 查看訂單詳情
  16. 在線支付(需要公網的IP,才可以完成全部功能,只能看到支付,獲取不到支付成功的消息)
  17. 刪除訂單

 

 

賣家功能:

商品上傳

商品后台查看

 

 

系統功能:

1. 將一定時間內沒有付款的訂單,修改為過期狀態

2. 權限控制(買家不能訪問,賣家添加商品的功能)

3. 配置錯誤頁面(404和500錯誤使用統一頁面顯示)

 

 

  1. 技術選型

技術選型:選擇實現當前這個項目,需要使用那些技術

 

前台:jsp、JavaScript、css、EL、JSON、AJAX、html、JSTL

后台:Servlet、JavaBean、BeanUtils、DBUtils、C3P0、MD5、JDBC、flexjson、UUID、監聽器、過濾器

數據庫:MySQL5.6

服務器:tomcat7/ tomcat6

開發工具:MyEclipse

JDK版本:1.7/1.6

J2EE版本: J2EE6.0/ J2EE5.0

操作系統:win7/win10

  1. 定義項目開發結構

定義項目開發結構:將那些java類,放到那些包中

 

 

  1. 導入項目依賴的jar包

所有jar包

導入lib文件夾:

導入后確認效果:

 

  1. 導入工具類

工具類在資料文件夾下的工具類文件夾中:

導入后的效果:

 

  1. 配置文件

配置文件在資料文件夾下的jar包文件夾中:

復制到src路徑下:

 

 

  1. 配置全站亂碼過濾器

復制資料文件夾下全站亂碼處理文件夾中(GenericEncodingFilter.java)到項目,放入cn.itcast.filter包中

 

在web.xml中配置過濾器,效果如紅框中所示:

 

 

  1. 數據庫設計

我們在實際的開發中,不同的項目使用的數據庫也不同,同樣,我們的estore項目,也需要設計一個數據庫

 

  1. 新建數據庫

導入資料文件夾中的數據庫腳本文件夾下的estore.sql

 

效果:

 

  1. 分析數據庫表結構

使用E-R圖分析數據庫表

矩形:實體(good商品 user用戶 order訂單)

菱形:實體和實體之間的關系

橢圓:實體中的屬性

 

 

 

  1. 導入與數據庫表對應的Java類

復制資料文件夾下的java類文件夾中的所有.java文件到:cn.itcast.domain包中

效果圖:

 

 

  1. 普通用戶功能(買家)

    1. 注冊

頁面展示:

總結:

前端js驗證:提高用戶的注冊成功率,讓用戶能一次性注冊成功(給用戶很多注冊的提示信息)。

后台Servlet驗證:防止用戶提交非正常的數據。

  1. 功能分析

 

  1. 完善頁面(修改form表單)

  1. 修改表單提交的請求路徑
  2. 修改顯示用戶錯誤操作的提示信息

 

 

  1. Servlet實現

StringUtils.isBlank()介紹:

 

package cn.itcast.web;

 

import java.io.IOException;

import java.lang.reflect.InvocationTargetException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.commons.beanutils.BeanUtils;

import org.apache.commons.lang3.StringUtils;

 

import cn.itcast.domain.User;

import cn.itcast.service.UserService;

import cn.itcast.service.impl.UserServiceImpl;

 

public class RegisterServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //接受請求的參數,校驗數據

        String username = request.getParameter("username");

        //非空校驗,不能==null,不能==""

        if(StringUtils.isBlank(username)){

            //表示是null或者空字符串

            request.setAttribute("msg", "用戶名不能為空");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

        String nickname = request.getParameter("nickname");

        if(StringUtils.isBlank(nickname)|| nickname.length()>10){

            //表示是null或者空字符串

            request.setAttribute("msg", "昵稱不能為空或者昵稱超過10個字符");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

        String password = request.getParameter("password");

        if(StringUtils.isBlank(password)){

            //表示是null或者空字符串

            request.setAttribute("msg", "密碼不能為空");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

        String confirm_password = request.getParameter("confirm_password");

        if(StringUtils.isBlank(confirm_password)){

            //表示是null或者空字符串

            request.setAttribute("msg", "確認密碼不能為空");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

        String captcha = request.getParameter("captcha");

        if(StringUtils.isBlank(captcha)){

            //表示是null或者空字符串

            request.setAttribute("msg", "驗證碼不能為空");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

        //校驗兩次密碼必須一致

        if(!(password.equals(confirm_password))){

            request.setAttribute("msg", "兩次密碼必須一致");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

          

        //校驗驗證碼

        String code = (String)request.getSession().getAttribute("code");

        if(!(code.equals(captcha))){

            request.setAttribute("msg", "驗證碼錯誤");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

        //封裝數據到User對象

        User u = new User();

        try {

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

        } catch (Exception e) {

            e.printStackTrace();

        }

        //調用service方法注冊用戶

        UserService userService = new UserServiceImpl();

        int info = userService.register(u);

          

        //根據不同返回值,不同處理

        if(info == 1){

            //注冊成功

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }else if(info == -1){

            request.setAttribute("msg", "用戶已存在");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }else{

            request.setAttribute("msg", "服務器忙,請等等,也許你打個醬油我們就好了");

            request.getRequestDispatcher("/register.jsp").forward(request, response);

            return;

        }

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

  1. Service實現

接口:UserService

package cn.itcast.service;

 

import cn.itcast.domain.User;

 

public interface UserService {

 

    /**

     * 注冊的方法

     * @param u

     * @return

     */

    int register(User u);

}

 

 

實現類:UserServiceImpl

package cn.itcast.service.impl;

 

import cn.itcast.dao.UserDao;

import cn.itcast.dao.impl.UserDaoImpl;

import cn.itcast.domain.User;

import cn.itcast.service.UserService;

import cn.itcast.utils.MD5Utils;

 

public class UserServiceImpl implements UserService {

 

    private UserDao userDao = new UserDaoImpl();

    

    @Override

    public int register(User u) {

        // 查詢當前用戶是否存在

        int info = userDao.findByName(u.getUsername());

        if(info == 1){

            //表示,當前用戶不存在,可以注冊

            //對用戶的密碼進行加密

            String password = MD5Utils.getPassword(u.getPassword());

            u.setPassword(password);

            //將用戶的權限設置為user,表示普通用戶

            u.setRole("user");

            int info2 = userDao.register(u);

            return info2;

        }else{

            return info;

        }

    }

 

}

 

 

  1. DAO實現

接口:UserDao

package cn.itcast.dao;

 

import cn.itcast.domain.User;

 

public interface UserDao {

 

    /**

     * 查詢用戶名是否存在的方法

     * @param username

     * @return

     */

    int findUserByUsername(String username);

 

    /**

     * 注冊用戶的方法

     * @param u

     * @return

     */

    int register(User u);

}

 

 

實現類:UserDaoImpl

package cn.itcast.dao.impl;

 

import java.sql.SQLException;

 

import org.apache.commons.dbutils.QueryRunner;

import org.apache.commons.dbutils.handlers.BeanHandler;

 

import cn.itcast.dao.UserDao;

import cn.itcast.domain.User;

import cn.itcast.utils.DBUtils;

 

public class UserDaoImpl implements UserDao {

 

    private QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

    @Override

    public int findByName(String username) {

        String sql = "select * from user where username = ?";

        try {

            User user = qr.query(sql, new BeanHandler<User>(User.class), username);

            if(user == null){

                return 1;

            }else{

                return -1;

            }

        } catch (SQLException e) {

            e.printStackTrace();

            return -2;

        }

    }

 

    @Override

    public int register(User u) {

        String sql = "insert into user values(null,?,?,?,?)";

        try {

            int update = qr.update(sql, u.getNickname(),u.getUsername(),u.getPassword(),u.getRole());

            return update;

        } catch (SQLException e) {

            e.printStackTrace();

            return -2;

        }

    }

 

}

 

  1. 使用ajax驗證用戶名是否已被注冊

提示:前端工程師書寫javascript代碼,不要去動,但是我們自己的javascript代碼執行結果也要保留,那么最好的解決方法,就是將結果合並。

  1. 需求分析

 

  1. 頁面實現

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<c:set var="root" value="${pageContext.request.contextPath}"/>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

<title>注冊</title>

<%@include file="inc/common_head.jsp"%>

<script type="text/javascript">

    //獲取ajax核心對象

    function getXHR(){

      

        var xmlhttp;

        if (window.XMLHttpRequest){

        // code for IE7+, Firefox, Chrome, Opera, Safari

            xmlhttp=new XMLHttpRequest();

        }else{

            // code for IE6, IE5

            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

        }

        return xmlhttp;

    }

    //定一個標記,用來記住自己的函數(_checkName)執行結果

    var flag = false;

    //ajax校驗用戶名

    function _checkName(_value){

        //獲取核心對象

        var xhr = getXHR();

        //使用方法發出請求

        xhr.open("get","${root}/checkName?username="+_value,true);

        xhr.send();

          

        //設置等待服務器響應

        xhr.onreadystatechange = function(){

            if(xhr.readyState == 4 && xhr.status == 200){

                //獲取響應的數據

                var data = xhr.responseText;

                var _username_notice = document.getElementById("username_notice");

                //根據返回的響應數據,不同處理

                if(data == 1){

                    //可以使用

                    _username_notice.innerHTML = "可以注冊";

                    _username_notice.setAttribute("style","color:green");

                    flag = true;

                }else if(data == -1){

                    //重復

                    _username_notice.innerHTML = "重復";

                    _username_notice.setAttribute("style","color:red");

                    flag = false;

                }else if(data == -3){

                    //不能為空

                    _username_notice.innerHTML = "不能為空";

                    _username_notice.setAttribute("style","color:red");

                    flag = false;

                }else{

                    //服務器忙

                    _username_notice.innerHTML = "服務器忙";

                    _username_notice.setAttribute("style","color:red");

                    flag = false;

                }

                //分析:當前校驗用戶名已經完成,但是,只是填寫和驗證了用戶名,還沒有驗證其他數據,但是,表單可以提交

                //通過分析代碼,發現:在原來的表單上,onsubmit屬性,綁定了兩次函數,后一次綁定,覆蓋了前一次的效果

                //導致原來js驗證,就不起作用。

                

                //原來的js驗證需要保留,那么,對表單onsubmit屬性,就只能綁定一次函數,

                //定義了一個變量,記住自己的函數執行結果,然后將結果和原來的register函數的結果一起運算

                //只有兩個函數結果都為true的時候,那么表單才可以提交。

            }

        };

    }

</script>

 

</head>

<body>

    <%@include file="inc/header.jsp"%>

    <div class="block block1">

        <div class="blank"></div>

        <div class="usBox">

            <div class="usBox_1">

                <div class="login_tab">

                    <ul>

                        <li onclick="location.href='login.jsp';">

                            <a href="javascript:;">用戶登錄</a>

                        </li>

                        <li class="active">用戶注冊</li>

                    </ul>

                </div>

                <form id="registForm" action="${root }/register" method="post" name="formUser"

                    onsubmit="return (register() && flag);">

                    <table width="100%" border="0" align="left" cellpadding="5"

                        cellspacing="3">

                        <!-- 設置獲取用戶錯誤操作的提示信息 -->

                        <caption>${msg }</caption>

                        <tr>

                            <td width="25%" align="right">用戶名</td>

                            <td width="65%"><input name="username" type="text"

                                id="username" onblur="is_registered(this.value);_checkName(this.value);"

                                class="inputBg" /> <span id="username_notice"

                                style="color:#FF0000"> *</span></td>

                        </tr>

                        <tr>

                            <td align="right">昵稱</td>

                            <td><input name="nickname" type="text"

                                id="nickname" onblur="check_nickname(this.value);"

                                class="inputBg" /> <span id="nickname_notice"

                                style="color:#FF0000"> *</span></td>

                        </tr>

                        <tr>

                            <td align="right">密碼</td>

                            <td><input name="password" type="password" id="password1"

                                onblur="check_password(this.value);"

                                onkeyup="checkIntensity(this.value)" class="inputBg" />

                                <span style="color:#FF0000"

                                id="password_notice"> *</span></td>

                        </tr>

                        <tr>

                            <td align="right">密碼強度</td>

                            <td>

                                <table width="145" border="0" cellspacing="0" cellpadding="1">

                                    <tr align="center">

                                        <td width="33%" style="border-bottom:2px solid #ccc;" id="pwd_lower"></td>

                                        <td width="33%" style="border-bottom:2px solid #ccc;" id="pwd_middle"></td>

                                        <td width="33%" style="border-bottom:2px solid #ccc;" id="pwd_high"></td>

                                    </tr>

                                </table>

                            </td>

                        </tr>

                        <tr>

                            <td align="right">確認密碼</td>

                            <td><input name="confirm_password" type="password"

                                id="conform_password"

                                onblur="check_conform_password(this.value);" class="inputBg" />

                                <span style="color:#FF0000"

                                id="conform_password_notice"> *</span></td>

                        </tr>

                        <tr>

                            <td align="right">驗證碼</td>

                            <td><input type="text" size="8" name="captcha" id="captcha"

                                class="inputBg" onblur="check_captcha(this.value);" /> <span style="color:#FF0000"

                                id="captcha_notice"> *</span></td>

                        </tr>

                        <tr>

                            <td align="right"></td>

                            <td><img src="validatecode.jsp"

                                style="vertical-align:middle;cursor:pointer;width:130px;height:35px;margin-top:-2px;"

                                onClick="src='validatecode.jsp?'+Math.random()" /></td>

                        </tr>

                        <tr>

                            <td>&nbsp;</td>

                            <td><label> <input name="agreement" type="checkbox"

                                    value="1" checked="checked" />我已看過並接受《<a

                                    href="javascript:;" style="color:blue" target="_blank">用戶協議</a>

                            </label></td>

                        </tr>

                        <tr>

                            <td>&nbsp;</td>

                            <td align="left">

                                <input name="Submit" type="submit" value="" class="us_Submit_reg">

                            </td>

                        </tr>

                        <tr>

                            <td colspan="2">&nbsp;</td>

                        </tr>

                    </table>

                </form>

                <div class="blank"></div>

            </div>

        </div>

    </div>

    <%@include file="inc/footer.jsp"%>

</body>

</html>

 

  1. Servlet實現

package cn.itcast.web;

 

import java.io.IOException;

import java.io.PrintWriter;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.commons.lang3.StringUtils;

 

import cn.itcast.service.UserService;

import cn.itcast.service.impl.UserServiceImpl;

 

public class CheckNameServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //校驗數據

        String username = request.getParameter("username");

        PrintWriter writer = response.getWriter();

        if(StringUtils.isBlank(username)){

            //表示數據為空

            writer.write("-3");

            return;

        }else{

            //調用service方法

            UserService userService = new UserServiceImpl();

            int info = userService.findByName(username);

            //返回結果

            writer.write(info+"");

            return;

        }

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

}

 

 

  1. Service實現

接口: UserService

 

 

/**

     * 根據用戶名查詢的方法

     * @param username

     * @return

     */

    int findByName(String username);

 

實現類:UserServiceImpl

 

public int findByName(String username) {

        return userDao.findByName(username);

    }

  1. DAO實現

已實現,不再重復。

  1. 登錄

在正式的開發中,使用瀏覽器測試,火狐,谷歌,IE,搜狗,360,QQ瀏覽器,測試javascript代碼

 

頁面展示;

  1. 功能分析

 

 

  1. 完善頁面

  1. 修改請求路徑
  2. 修改用戶的操作錯誤提示信息顯示位置

  1. 顯示登錄名js

<script type="text/javascript">

    window.onload = function(){

          

        var data = "${cookie.username.value}";

        var username = decodeURI(data);

        document.getElementById("_un").value = username;

    };

 

</script>

  1. Servlect實現

package cn.itcast.web;

 

import java.io.IOException;

import java.net.URLEncoder;

 

import javax.servlet.ServletException;

import javax.servlet.http.Cookie;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.commons.lang3.StringUtils;

 

import cn.itcast.domain.User;

import cn.itcast.service.UserService;

import cn.itcast.service.impl.UserServiceImpl;

 

public class LoginServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        //接受參數,校驗(username password

        String username = request.getParameter("username");

        if(StringUtils.isBlank(username)){

            request.setAttribute("msg", "用戶名不能為空");

            request.getRequestDispatcher("/login.jsp").forward(request, response);

            return;

        }

        String password = request.getParameter("password");

        if(StringUtils.isBlank(password)){

            request.setAttribute("msg", "密碼不能為空");

            request.getRequestDispatcher("/login.jsp").forward(request, response);

            return;

        }

        //調用service方法登錄用戶

        UserService userService = new UserServiceImpl();

        User loginUser = userService.login(username,password);

        //根局不同的返回值,不同處理

        if(loginUser == null){

            request.setAttribute("msg", "用戶名或者密碼錯誤");

            request.getRequestDispatcher("/login.jsp").forward(request, response);

            return;

        }else{

            //判斷用戶是否記住用戶名

            String remember = request.getParameter("remember");

            if("on".equals(remember)){

                Cookie cookie = new Cookie("username", URLEncoder.encode(username, "utf-8"));

                cookie.setMaxAge(60*60*24*7);

                cookie.setPath("/");

                response.addCookie(cookie);

            }else{

                Cookie cookie = new Cookie("username", "");

                cookie.setMaxAge(0);

                cookie.setPath("/");

                response.addCookie(cookie);

            }

              

              

            //loginUser存入session中,返回主頁

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

            response.sendRedirect(request.getContextPath());

              

        }

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. Service實現

接口:UserService

/**

     * 用戶登錄的方法

     * @param username

     * @param password

     * @return

     */

    User login(String username, String password);

 

 

實現類:UserServiceImpl

public User login(String username, String password) {

        //先對用戶的明文密碼加密

        String password2 = MD5Utils.getPassword(password);

        return userDao.login(username,password2);

    }

 

  1. DAO實現

接口:userDao

 

/**

     * 用戶登陸

     * @param username

     * @param pwd

     * @return

     */

    User login(String username, String pwd);

實現類:UserDaoImpl

public User login(String username, String password2) {

        String sql = "select * from user where username = ? and password = ?";

        try {

            return qr.query(sql, new BeanHandler<User>(User.class), username,password2);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("用戶登錄失敗");

        }

    }

 

  1. 首頁顯示歡迎信息

用戶登錄之后,頭部頁面顯示用戶的昵稱:

 

修改inc目錄下的head.jsp

 

 

 

 

  1. 查看商品

    1. 功能分析

頁面修改:

 

Ctrl + shift + r :用來搜索文件,根據文件名

Ctrl + shift + t :用來搜索java類,根據類名

 

  1. Servlet實現

package cn.itcast.web;

 

import java.io.IOException;

import java.util.List;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Good;

import cn.itcast.service.GoodService;

import cn.itcast.service.impl.GoodServiceImpl;

 

public class FindAllGoodsServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //調用service方法獲取數據

        GoodService goodService = new GoodServiceImpl();

        List<Good> list = goodService.findAll();

        //將數據存入request容器,返回goods.jsp

        request.setAttribute("list", list);

        request.getRequestDispatcher("/goods.jsp").forward(request, response);

          

          

        //測試的步驟:

        //第一:先查看請求是否發出

        //第二:服務器是否接收請求,參數是否正確

        //第三:是否調用servicedao

        //第四:返回的數據,是否正確(跟我們預期是一致的)

        //第五:是否將數據返回給頁面

        //第六:頁面是否取出數據展示

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. Service實現

接口:GoodService

package cn.itcast.service;

 

import java.util.List;

 

import cn.itcast.domain.Goods;

 

public interface GoodService {

 

    /**

     * 獲取所有商品的方法

     * @return

     */

    List<Goods> findAllGoods();

 

}

 

 

 

實現類:GoodServiceImpl

 

package cn.itcast.service.impl;

 

import java.util.List;

 

import cn.itcast.dao.GoodDao;

import cn.itcast.dao.impl.GoodDaoImpl;

import cn.itcast.domain.Goods;

import cn.itcast.service.GoodService;

 

public class GoodServiceImpl implements GoodService {

 

    private GoodDao goodDao = new GoodDaoImpl();

    

    @Override

    public List<Goods> findAllGoods() {

        return goodDao.findAllGoods();

    }

 

}

 

 

  1. DAO實現

接口:GoodDao

 

package cn.itcast.dao;

 

import java.util.List;

 

import cn.itcast.domain.Goods;

 

public interface GoodDao {

 

    /**

     * 獲取所有商品的方法

     * @return

     */

    List<Goods> findAllGoods();

 

}

 

 

實現類:GoodDaoImpl

package cn.itcast.dao.impl;

 

import java.sql.SQLException;

import java.util.List;

 

import org.apache.commons.dbutils.QueryRunner;

import org.apache.commons.dbutils.handlers.BeanListHandler;

 

import cn.itcast.dao.GoodDao;

import cn.itcast.domain.Goods;

import cn.itcast.utils.DBUtils;

 

public class GoodDaoImpl implements GoodDao {

 

    @Override

    public List<Goods> findAllGoods() {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "select * from goods";

        try {

            return qr.query(sql, new BeanListHandler<Goods>(Goods.class));

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("獲取商品列表數據失敗");

        }

    }

 

}

 

 

 

  1. 商品列表頁面實現

  1. 有商品的情況下遍歷循環商品列表
  2. 顯示商品圖片
  3. 顯示商品名稱
  4. 顯示市場價格和本店價格

 

 

  1. 商品詳情

    1. 功能分析

 

  1. Goods.jsp頁面完善

 

 

  1. Servlet實現

 

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Good;

import cn.itcast.service.GoodService;

import cn.itcast.service.impl.GoodServiceImpl;

 

public class FindGoodByIdServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        //獲取參數

        String parameter = request.getParameter("gid");

        //注意,這里是有問題的

        int gid = 0;

        try {

             gid = Integer.parseInt(parameter);

        } catch (Exception e) {

            //雖然處理了異常,還是要知道具體的異常信息

            e.printStackTrace();

            response.sendRedirect(request.getContextPath());

            return;

        }

        //調用service方法獲取數據

        GoodService goodService = new GoodServiceImpl();

        Good good = goodService.findById(gid);

        //將數據轉發到頁面

        request.setAttribute("good", good);

        request.getRequestDispatcher("/goods_detail.jsp").forward(request, response);

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

 

  1. Service實現

接口:GoodService

 

/**

     * 獲取商品數據

     * @param gid

     * @return

     */

    Good findById(int gid);

 

實現類:GoodServiceImpl

 

public Good findById(int gid) {

        return goodDao.findById(gid);

    }

 

  1. DAO實現

接口:GoodDao

 

/**

     * 獲取商品數據

     * @param gid

     * @return

     */

    Good findById(int gid);

 

實現類:GoodDaoImpl

 

public Good findById(int gid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "select * from goods where id = ?";

        try {

            return qr.query(sql, new BeanHandler<Good>(Good.class),gid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("獲取商品詳細失敗");

        }

    }

 

  1. 頁面實現

  1. 修改大圖連接
  2. 圖片資源路徑
  3. 修改小圖列表資源路徑
  4. 顯示商品名稱
  5. 市場價格
  6. 商城價格
  7. 庫存
  8. 商品分類
  9. 商品描述

 

  1. 購物車

    1. 添加購物車

      1. 功能分析

 

 

  1. 頁面修改

1)修改添加商品到購物車的按鈕的連接

 

 

效果:

  1. Servlet實現

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.User;

import cn.itcast.service.CartService;

import cn.itcast.service.impl.CartServiceImpl;

 

public class AddGoodTOCartServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        //校驗登錄

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            //================跳轉之前頁面修改======================

            //記住以前的地址

            String header = request.getHeader("Referer");

            //http://localhost:8080/estore

            String str = "http://localhost:8080/estore";

            header = header.substring(str.length());

            request.getSession().setAttribute("url", header);

            //================跳轉之前頁面修改======================

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

        //獲取參數(uid gid

        String parameter = request.getParameter("gid");

        Integer gid = null;

        try {

            gid = Integer.parseInt(parameter);

        } catch (Exception e) {

            e.printStackTrace();

            response.sendRedirect(request.getContextPath());

            return;

        }

        int uid = loginUser.getId();

        //調用service方法添加商品到購物車

        CartService cartService = new CartServiceImpl();

        cartService.addGoodTOCart(uid ,gid);

        //跳轉buyorcart.jsp,讓用戶自己選擇繼續購物或者付款

        response.sendRedirect(request.getContextPath()+"/buyorcart.jsp");

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. Service實現

接口:CartService

 

/**

     * 添加商品到購物車

     * @param gid

     * @param uid

     */

    void addGoodToCart(int gid, int uid);

 

實現類:CartServiceImpl

 

private CartDao cartDao = new CartDaoImpl();

    

    @Override

    public void addGoodToCart(int gid, int uid) {

        // 查詢是否購買過

        Cart cart = cartDao.findByGidAndUid(gid,uid);

        if(cart == null){

            //沒買過,添加新的

            Cart c = new Cart();

            c.setBuynum(1);

            c.setGid(gid);

            c.setUid(uid);

            cartDao.add(c);

        }else{

            //買過了,修改數量加一

            int buynum = cart.getBuynum();

            buynum = buynum + 1;

            cart.setBuynum(buynum);

            cartDao.update(cart);

        }

    }

 

  1. DAO實現

 

接口:CartDao

 

/**

     * 根據用戶id和商品id查詢數據的方法

     * @param gid

     * @param uid

     * @return

     */

    Cart findByGidAndUid(int gid, int uid);

 

    /**

     * 添加購物車數據

     * @param c

     */

    void add(Cart c);

 

    /**

     * 修改購物車數據

     * @param cart

     */

    void update(Cart cart);

 

實現類:CartDaoImpl

 

public Cart findByGidAndUid(int gid, int uid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "select * from cart where uid = ? and gid = ?";

         try {

            return qr.query(sql, new BeanHandler<Cart>(Cart.class), uid,gid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("獲取指定的用戶和商品的購物車數據失敗");

        }

    }

 

    @Override

    public void add(Cart c) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "insert into cart values(?,?,?)";

         try {

            qr.update(sql, c.getUid(),c.getGid(),c.getBuynum());

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("添加購物車數據失敗");

        }

    }

 

    @Override

    public void update(Cart cart) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "update cart set buynum = ? where uid = ? and gid = ?";

         try {

            qr.update(sql, cart.getBuynum(),cart.getUid(),cart.getGid());

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("添加購物車數據失敗");

        }

    }

 

 

  1. 修改buyorcart.jsp頁面鏈接

1)完善繼續購物和去購物車結算的鏈接

 

 

 

補充:登陸完成之后,直接跳轉之前瀏覽的頁面

 

  1. AddGoodToCartServlet獲取當前商品詳細頁面的路徑——查詢商品詳情的路徑,通過請求頭:Referer 獲取

  1. 將商品詳情的路徑保存,保存到session中,為了保證后期也可以使用
  2. loginServlet先獲取session中的商品詳情的路徑,判斷是否存在,存在,跳轉商品詳情的路徑,不存在,跳轉首頁

 

  1. 查看購物車

    1. 功能分析

 

  1. 在購物車對象中添加商品對象

1)修改購物車類,添加一個商品對象做屬性,方便在購物車頁面中,顯示商品信息

 

 

注意:還要生成getter和setter方法,重新生成toString方法

  1. Servlet實現

package cn.itcast.web;

 

import java.io.IOException;

import java.util.List;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Cart;

import cn.itcast.domain.User;

import cn.itcast.service.CartService;

import cn.itcast.service.impl.CartServiceImpl;

 

public class FindAllCartServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //校驗登陸

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

        //獲取數據

        int uid = loginUser.getId();

        //調用service

        CartService cartService = new CartServiceImpl();

        List<Cart> list = cartService.findAllCart(uid);

          

        //返回數據

        request.setAttribute("list", list);

        request.getRequestDispatcher("/cart.jsp").forward(request, response);

      

          

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

 

  1. Service實現

接口: CartService

 

/**

     * 查詢當前用戶購物車商品數據的方法

     * @param uid

     * @return

     */

    List<Cart> findAllCart(int uid);

 

實現類; CartServiceImpl

 

private GoodDao goodDao = new GoodDaoImpl();

    @Override

    public List<Cart> findAllCart(int uid) {

        //第一步:獲取所有的購物車數據cart

        List<Cart> list = cartDao.findAllCart(uid);

        //第二步:獲取購物車相對應商品信息

        for (Cart cart : list) {

              

            Good good = goodDao.findById(cart.getGid());

            cart.setGood(good);

        }

          

        return list;

    }

 

  1. DAO實現

接口:CartDao

 

/**

     * 查詢當前用戶購物車商品數據的方法

     * @param uid

     * @return

     */

    List<Cart> findAllCart(int uid);

 

實現類:CartDaoImpl

 

public List<Cart> findAllCart(int uid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "select * from cart where uid = ?";

         try {

            return qr.query(sql, new BeanListHandler<Cart>(Cart.class), uid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("獲取指定的用戶的購物車數據失敗");

        }

    }

 

 

 

  1. 頁面實現

1)遍歷循環購物車集合顯示購物車中的商品信息

2)計算購物車中商品的總計

3)計算購物車中商品一共節省的金額

 

 

 

額外補充:大數據相關概念

 

  1. 修改購物車中商品的購買數量

    1. 功能分析

 

 

  1. 頁面實現

  1. 設置onblur事件,啟動js函數,函數中的參數購買數量和商品id

 

2)在js函數中,先驗證當前用戶輸入的數據,是否是數字(使用parseInt()方法,如果是整數返回true),且大於等於1

  1. 數據驗證完成之后,發送修改數量的請求,請求參數有購買的數量和商品的id

 

代碼:

<script type="text/javascript">

    function _updateBuynum(buynum,gid){

        //判斷當前用戶輸入的內容,這個內容,必須是數字,是正整數

        //是不是數字

        if(parseInt(buynum)){

            //是不是正數    

            if(buynum > 0){

                //發送請求

                location.href='${root }/updateBuynum?gid='+gid+'&buynum='+buynum;

            }else{

                alert("數字不合法");

            }

        }else{

          

            alert("數字不合法");

        }

        

    }

 

</script>

 

 

  1. Servlet實現

 

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Cart;

import cn.itcast.domain.User;

import cn.itcast.service.CartService;

import cn.itcast.service.impl.CartServiceImpl;

 

public class UpdateBuynumServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //校驗登陸

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

        //接受參數

        String parameter = request.getParameter("gid");

        String parameter2 = request.getParameter("buynum");

        int gid = 0;

        int buynum = 0;

        try {

            gid = Integer.parseInt(parameter);

            buynum = Integer.parseInt(parameter2);

        } catch (Exception e) {

            e.printStackTrace();

            response.sendRedirect(request.getContextPath());

            return;

        }

        int uid = loginUser.getId();

        Cart c = new Cart();

        c.setBuynum(buynum);

        c.setGid(gid);

        c.setUid(uid);

        //調用service方法

        CartService cartService = new CartServiceImpl();

        cartService.updateBuynum(c);

          

        //重新獲取所有的購物車數據,findAllCartServlet

        response.sendRedirect(request.getContextPath()+"/findAllCart");

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

Service接口:

/**

     * 修改數量的方法

     * @param c

     */

    void updateBuynum(Cart c);

 

實現類:

public void updateBuynum(Cart c) {

          

        cartDao.update(c);

    }

 

注意: dao已經實現過了,不再重復

 

  1. 刪除購物車中的商品

    1. 功能分析

  1. 頁面實現

完善刪除鏈接,發送要被刪除的商品的gid

 

  1. Servlet實現

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.User;

import cn.itcast.service.CartService;

import cn.itcast.service.impl.CartServiceImpl;

 

public class DeleteCartServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //校驗登錄

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

          

        //獲取參數(gid uid

        String parameter = request.getParameter("gid");

        int gid = 0;

        try {

            gid = Integer.parseInt(parameter);

        } catch (Exception e) {

            e.printStackTrace();

            response.sendRedirect(request.getContextPath());

            return;

        }

        int uid= loginUser.getId();

        //調用service方法,刪除數據

        CartService cartService = new CartServiceImpl();

        cartService.delete(uid , gid);

        //重新獲取所有的購物車信息

        response.sendRedirect(request.getContextPath()+"/findAllCart");

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. Service實現

接口:CartService

 

/**

     * 刪除購物車商品

     * @param uid

     * @param gid

     */

    void delete(int uid, int gid);

 

實現類:CartServiceImpl

 

public void delete(int uid, int gid) {

          

        cartDao.delete(uid,gid);

    }

 

  1. DAO實現

 

接口:CartDao

 

/**

     * 刪除購物車商品

     * @param uid

     * @param gid

     */

    void delete(int uid, int gid);

 

 

實現類:CartDaoImpl

 

public void delete(int uid, int gid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "delete from cart where uid = ? and gid = ?";

        try {

            qr.update(sql, uid,gid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("刪除購物車失敗");

        }

        

    }

 

Nosql數據庫:redis:緩存 mongdb :存儲大量文本 ,資金流

 

提示:如果購物車數據,存在session中,如何通過測試確認?換瀏覽器,查看購物車數據是否不一致。

如果購物車數據,存在數據庫中,如果如何測試確認?每次登錄購物車中數據都不會變化。

購物車存數據庫,第一:占用空間,第二,大量的增刪改查操作,不斷與數據庫交互,性能慢

 

如果購物車數據,存在緩存中,如果如何測試確認?在服務器維護之后,購物車數據消失,就存在緩存中。

緩存:在內存中開辟的空間,存取數據的。

 

備份服務器:平時運行的服務器A,在A停機維護的時候,B服務器對外提供服務。

 

  1. 訂單

    1. 提交訂單(重點、難點)

  1. 頁面顯示購物車商品清單

1)修改查看購物車列表的servlet,將數據保存到session,方便在同一個會話中使用,在訂單頁面再次展示購物車數據不需要再從數據庫中獲取

 

 

  1. 在訂單的提交頁面顯示用戶要購買的商品數據

     

    遍歷商品集合,計算商品的總價

 

 

 

  1. Ajax實現省市縣三級聯動

功能分析:

第一步:頁面加載完成之后,顯示省一級地區的數據

第二步:選擇省的時候,加載相對應的市的數據

第三步:選擇市的時候,加載相對應的縣的數據

 

流程圖:

 

  1. Ajax代碼

<script type="text/javascript">

        //獲取核心對象的方法

        function getXHR(){

            var xmlhttp;

            if (window.XMLHttpRequest){

                // code for IE7+, Firefox, Chrome, Opera, Safari

                xmlhttp=new XMLHttpRequest();

            }else{

                // code for IE6, IE5

                xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

            }

            return xmlhttp;

        }

 

        //書寫ajax代碼步驟:

        //第一步:獲取核心對象

        //第二步:發送請求open方法 send方法

        //第三步:設置等待響應

        //第四步:獲取響應數據,根據業務處理數據

          

        window.onload = function(){

            var xhr = getXHR();

              

            xhr.open("GET","${root}/getData?pid=0",true);

            xhr.send();

              

            xhr.onreadystatechange = function(){

              

                if(xhr.readyState == 4 && xhr.status == 200){

                    //data是字符串數據,將他轉換成javascript對象

                    var data = xhr.responseText;

                    //eval 這個函數是將字符串,轉換成javascript代碼,

                    //JSON.parse()出來之后,eval就開始淘汰

                    var arr = JSON.parse(data);

                    var _province = document.getElementById("province");

                    for ( var i = 0; i < arr.length; i++) {

                        //不斷創建option,添加到省一級地區的select標簽中

                        var _option = document.createElement("option");

                        _option.setAttribute("value", arr[i].id);

                        _option.innerHTML = arr[i].name;

                          

                        _province.appendChild(_option);

                    }

                }

            };        

        };

          

        function _getCity(value){

            var _city = document.getElementById("city");

            //清空數據

            _city.length = 1;

                var _district = document.getElementById("district");

            //清空數據

            _district.length = 1;

            var xhr = getXHR();

              

            xhr.open("GET","${root}/getData?pid="+value,true);

            xhr.send();

              

            xhr.onreadystatechange = function(){

              

                if(xhr.readyState == 4 && xhr.status == 200){

                    var data = xhr.responseText;

                    var arr = JSON.parse(data);

                  

                    for ( var i = 0; i < arr.length; i++) {

                        //不斷創建option,添加到省一級地區的select標簽中

                        var _option = document.createElement("option");

                        _option.setAttribute("value", arr[i].id);

                        _option.innerHTML = arr[i].name;

                          

                        _city.appendChild(_option);

                    }

                }

            };        

          

        }

        function _getDistrict(value){

            var _district = document.getElementById("district");

            //清空數據

            _district.length = 1;

            var xhr = getXHR();

              

            xhr.open("GET","${root}/getData?pid="+value,true);

            xhr.send();

              

            xhr.onreadystatechange = function(){

              

                if(xhr.readyState == 4 && xhr.status == 200){

                    var data = xhr.responseText;

                    var arr = JSON.parse(data);

                  

                    for ( var i = 0; i < arr.length; i++) {

                        //不斷創建option,添加到省一級地區的select標簽中

                        var _option = document.createElement("option");

                        _option.setAttribute("value", arr[i].id);

                        _option.innerHTML = arr[i].name;

                          

                        _district.appendChild(_option);

                    }

                }

            };        

        }

 

 

</script>

  1. Servlet代碼實現

 

package cn.itcast.web;

 

import java.io.IOException;

import java.util.List;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.PCD;

import cn.itcast.service.PCDService;

import cn.itcast.service.impl.PCDServiceImpl;

import flexjson.JSONSerializer;

 

public class GetDataServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //獲取pid

        String parameter = request.getParameter("pid");

        int pid = 0;

        try {

            pid = Integer.parseInt(parameter);

        } catch (Exception e) {

            e.printStackTrace();

            response.sendRedirect(request.getContextPath());

            return;

        }

          

        //調用service方法

        PCDService pcdService = new PCDServiceImpl();

        List<PCD> list = pcdService.getData(pid);

          

        //將數據轉換成json格式

        JSONSerializer serializer = new JSONSerializer();

        String serialize = serializer.serialize(list);

          

        //發出響應

        response.getWriter().write(serialize);

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

  1. 省市聯動Service實現

接口:ProvinceService

package cn.itcast.service;

 

import java.util.List;

 

import cn.itcast.domain.PCD;

 

public interface PCDService {

 

    /**

     * 獲取地區數據的方法

     * @param pid

     * @return

     */

    List<PCD> getData(int pid);

 

}

 

實現類:ProvinceServiceImpl

package cn.itcast.service.impl;

 

import java.util.List;

 

import cn.itcast.dao.PCDDao;

import cn.itcast.dao.impl.PCDDaoImpl;

import cn.itcast.domain.PCD;

import cn.itcast.service.PCDService;

 

public class PCDServiceImpl implements PCDService {

 

    private PCDDao pcdDao = new PCDDaoImpl();

    @Override

    public List<PCD> getData(int pid) {

        return pcdDao.getData(pid);

    }

 

}

 

 

  1. 省市聯動Dao實現

接口: ProvinceDao

package cn.itcast.dao;

 

import java.util.List;

 

import cn.itcast.domain.PCD;

 

public interface PCDDao {

 

    List<PCD> getData(int pid);

 

}

 

實現類:ProvinceDaoImpl

package cn.itcast.dao.impl;

 

import java.sql.SQLException;

import java.util.List;

 

import org.apache.commons.dbutils.QueryRunner;

import org.apache.commons.dbutils.handlers.BeanListHandler;

 

import cn.itcast.dao.PCDDao;

import cn.itcast.domain.PCD;

import cn.itcast.utils.DBUtils;

 

public class PCDDaoImpl implements PCDDao {

 

    @Override

    public List<PCD> getData(int pid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "select * from province_city_district where pid = ?";

        try {

            return qr.query(sql, new BeanListHandler<PCD>(PCD.class), pid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("獲取地區數據失敗");

        }

    }

 

}

 

 

  1. 訂單生成頁面修改

  1. 修改表單請求路徑

  1. 將被選中的省市縣數據存入隱藏域中

 

  1. 訂單生成頁面流程分析

 

 

  1. 訂單生成Servlet實現

 

package cn.itcast.web;

 

import java.io.IOException;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Cart;

import cn.itcast.domain.Order;

import cn.itcast.domain.OrderItems;

import cn.itcast.domain.User;

import cn.itcast.service.OrderService;

import cn.itcast.service.impl.OrderServiceImpl;

import cn.itcast.utils.UUIDUtils;

 

public class AddOrderServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        //校驗登錄

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

          

        //獲取和封裝數據

        //封裝訂單的數據

        String oid = UUIDUtils.getUUID();

        int uid = loginUser.getId();

        double totalprice = 0;

        //獲取session中的購物車數據,來計算總金額

        List<Cart> list = (List<Cart>)request.getSession().getAttribute("list");

        //准備一個集合,用來保存OrderItems

        List<OrderItems> oiList = new ArrayList<OrderItems>();

          

        for (Cart cart : list) {

            totalprice = totalprice + cart.getBuynum() * cart.getGood().getEstoreprice();

            //獲取所有商品的信息,將數據存入OrderItems,然后,再存入List集合

            OrderItems oi = new OrderItems();

            //訂單編號

            oi.setOid(oid);

            //商品的編號

            oi.setGid(cart.getGood().getId());

            oi.setBuynum(cart.getBuynum());

              

            oiList.add(oi);

        }

        //設置支付狀態:1 待付款

        int status = 1;

        Date createtime = new Date();

        //省市縣

        String province = request.getParameter("province");

        String city = request.getParameter("city");

        String district = request.getParameter("district");

        //詳細地址,郵編姓名電話

        String detailAddress = request.getParameter("detailAddress");

        String zipcode = request.getParameter("zipcode");

        String name = request.getParameter("name");

        String telephone = request.getParameter("telephone");

          

        String address = province +"(省/市)"+city+"(市/區)"+district+"(縣/鎮)"+

        detailAddress+"郵編:"+zipcode+"姓名:"+name+"電話:"+telephone;

          

        Order o = new Order();

        o.setAddress(address);

        o.setCreatetime(createtime);

        o.setId(oid);

        o.setStatus(status);

        o.setTotalprice(totalprice);

        o.setUid(uid);

        o.setOiList(oiList);

          

        //調用service方法添加訂單

        OrderService orderService = new OrderServiceImpl();

        orderService.add(o);

        //調用查詢全部訂單Servlet,查看效果

        response.sendRedirect(request.getContextPath()+"/orders.jsp");

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. 訂單生成Service實現

接口:OrderService

package cn.itcast.service;

 

import cn.itcast.domain.Order;

 

public interface OrderService {

 

    /**

     * 添加訂單的方法

     * @param o

     */

    void add(Order o);

 

}

 

實現類:OrderServiceImpl

package cn.itcast.service.impl;

 

import java.sql.Connection;

import java.sql.SQLException;

 

import cn.itcast.dao.CartDao;

import cn.itcast.dao.OrderDao;

import cn.itcast.dao.impl.CartDaoImpl;

import cn.itcast.dao.impl.OrderDaoImpl;

import cn.itcast.domain.Order;

import cn.itcast.service.OrderService;

import cn.itcast.utils.DBUtils;

 

public class OrderServiceImpl implements OrderService {

 

    private OrderDao orderDao = new OrderDaoImpl();

    private CartDao cartDao = new CartDaoImpl();

    @Override

    public void add(Order o) {

        //獲取數據庫連接

        Connection conn = null;

        try {

            conn = DBUtils.getConnection();

            //開啟事務

            conn.setAutoCommit(false);

            //添加訂單

            orderDao.add(o,conn);

            //添加訂單明細

            orderDao.addOrderItems(o.getOiList(),conn);

              

            //清空購物車

            cartDao.clear(o.getUid(),conn);

            //提交事務

            conn.commit();

            //異常回滾

              

        } catch (Exception e) {

            e.printStackTrace();

            try {

                conn.rollback();

            } catch (SQLException e1) {

                e1.printStackTrace();

            }

        }

          

 

    }

 

}

 

  1. 訂單生成DAO實現

接口:OrderDao

 

package cn.itcast.dao;

 

import java.sql.Connection;

import java.util.List;

 

import cn.itcast.domain.Order;

import cn.itcast.domain.OrderItems;

 

public interface OrderDao {

 

    /**

     * 添加訂單

     * @param o

     * @param conn

     */

    void add(Order o, Connection conn);

 

    /**

     * 添加訂單明細

     * @param oiList

     * @param conn

     */

    void addOrderItems(List<OrderItems> oiList, Connection conn);

 

}

 

 

實現類:OrderDaoImpl

 

package cn.itcast.dao.impl;

 

import java.sql.Connection;

import java.sql.SQLException;

import java.util.List;

 

import org.apache.commons.dbutils.QueryRunner;

 

import cn.itcast.dao.OrderDao;

import cn.itcast.domain.Order;

import cn.itcast.domain.OrderItems;

 

public class OrderDaoImpl implements OrderDao {

 

    @Override

    public void add(Order o, Connection conn) {

        //QueryRunner():創建一個與數據庫無關的QueryRunner對象,后期在使用增刪改查的方法的時候,手動提供一個連接

        QueryRunner qr = new QueryRunner();

        String sql = "insert into orders values(?,?,?,?,?,?)";

        try {

            qr.update(conn, sql, o.getId(),o.getUid(),o.getTotalprice(),o.getAddress(),o.getStatus(),o.getCreatetime());

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("添加訂單失敗");

        }

    }

 

    @Override

    public void addOrderItems(List<OrderItems> oiList, Connection conn) {

        QueryRunner qr = new QueryRunner();

        String sql = "insert into orderitems values(?,?,?)";

        for (OrderItems oi : oiList) {

            try {

                qr.update(conn, sql, oi.getOid(),oi.getGid(),oi.getBuynum());

            } catch (SQLException e) {

                e.printStackTrace();

                throw new RuntimeException("添加訂單明細失敗");

            }

              

        }

    }

 

}

 

 

接口:CartDao

/**

     * 清空購物車

     * @param uid

     * @param conn

     */

    void clear(int uid, Connection conn);

 

實現類:CartDaoImpl

public void clear(int uid, Connection conn) {

        QueryRunner qr = new QueryRunner();

        String sql = "delete from cart where uid = ?";

        try {

            qr.update(conn, sql, uid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("清空購物車失敗");

        }

        

    }

 

  1. 查看訂單列表

    1. 功能分析

 

 

  1. Servlet實現

 

package cn.itcast.web;

 

import java.io.IOException;

import java.util.List;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Order;

import cn.itcast.domain.User;

import cn.itcast.service.OrderService;

import cn.itcast.service.impl.OrderServiceImpl;

 

public class FindAllOrdersServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        //校驗登錄

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

        //獲取參數

        int uid= loginUser.getId();

        //調用service方法

        OrderService orderService = new OrderServiceImpl();

        List<Order> oList = orderService.findAll(uid);

        //轉發數據到orders.jsp展示數據

        request.setAttribute("oList", oList);

        request.getRequestDispatcher("/orders.jsp").forward(request, response);

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. Service實現

接口:OrderService

 

/**

     * 查詢指定用戶的所有的訂單

     * @param uid

     * @return

     */

    List<Order> findAll(int uid);

 

實現類:OrderServiceImpl

public List<Order> findAll(int uid) {

        return orderDao.findAll(uid);

    }

  1. DAO實現

接口:OrderDao

 

/**

     * 查詢指定用戶的訂單

     * @param uid

     * @return

     */

    List<Order> findAll(int uid);

 

 

實現類: OrderDaoImpl

 

public List<Order> findAll(int uid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql= "select * from orders where uid = ?";

        try {

            return qr.query(sql, new BeanListHandler<Order>(Order.class), uid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("查詢指定的用戶訂單失敗");

        }

    }

 

  1. 頁面實現

  1. 顯示訂單相關信息
  2. 根據訂單的狀態顯示不同效果,status==1未支付——在線支付、取消訂單,status==2,已支付——查看詳細,status==3已過期——查看詳細

  1. 查看訂單詳情

    1. 功能分析

  1. Servlet實現

 

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Order;

import cn.itcast.domain.User;

import cn.itcast.service.OrderService;

import cn.itcast.service.impl.OrderServiceImpl;

 

public class FindOrderByIdServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //校驗登錄

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

          

        //獲取參數oid

        String oid = request.getParameter("oid");

        //調用service獲取數據

        OrderService orderService = new OrderServiceImpl();

        Order o = orderService.findById(oid);

          

        //轉發數據到orders_detail.jsp

        request.setAttribute("order", o);

        request.getRequestDispatcher("/orders_detail.jsp").forward(request, response);

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. Service實現

接口:OrderService

 

/**

     * 根據訂單id獲取數據的方法

     * @param oid

     * @return

     */

    Order findById(String oid);

 

實現類:OrderServiceImpl

 

private GoodDao goodDao = new GoodDaoImpl();

    @Override

    public Order findById(String oid) {

        // 獲取訂單數據

        Order o = orderDao.findById(oid);

          

        //獲取訂單明細

        List<OrderItems> oiList = orderDao.findOrderItemsByOid(oid);

        for (OrderItems oi : oiList) {

            //獲取商品信息

            Good good = goodDao.findById(oi.getGid());

            oi.setGood(good);

        }

          

        //封裝數據返回給調用者

        o.setOiList(oiList);

        return o;

    }

 

 

  1. Dao實現

接口:OrderDao

 

/**

     * 根據id查詢訂單

     * @param oid

     * @return

     */

    Order findById(String oid);

 

    /**

     * 根據oid獲取訂單明細

     * @param oid

     * @return

     */

    List<OrderItems> findOrderItemsByOid(String oid);

 

實現類: OrderDaoImpl

 

@Override

    public Order findById(String oid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql="select * from orders where id = ?";

        try {

            return qr.query(sql,new BeanHandler<Order>(Order.class), oid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("查詢指定的訂單失敗");

        }

    }

 

    @Override

    public List<OrderItems> findOrderItemsByOid(String oid) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "select * from orderitems where oid = ?";

        try {

            return qr.query(sql, new BeanListHandler<OrderItems>(OrderItems.class), oid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("查詢指定的訂單明細失敗");

        }

    }

 

 

  1. 頁面修改

  1. 在訂單編號上添加a標簽,鏈接指向訂單詳情
  2. 同樣也修改后面的訂單的查看詳情鏈接
  3. 顯示訂單的信息和相關的商品信息
  4. 要顯示訂單的總價

 

 

 

  1. 取消訂單

    1. 功能分析

 

  1. 編輯取消訂單的鏈接

1)設置取消訂單的鏈接

 

 

  1. Servlet實現

 

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.User;

import cn.itcast.service.OrderService;

import cn.itcast.service.impl.OrderServiceImpl;

 

public class DeleteOrderServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        //校驗登錄

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

          

        //獲取參數

        String oid = request.getParameter("oid");

          

        //調用service方法,刪除數據

        OrderService orderService = new OrderServiceImpl();

        orderService.delete(oid);

          

        //重定向訪問,findAllOrdersServlet

        response.sendRedirect(request.getContextPath()+"/findAllOrders");

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

  1. Service實現

接口:OrderService

 

/**

     * 刪除訂單的方法

     * @param oid

     */

    void delete(String oid);

 

實現類:

public void delete(String oid) {

          

        //獲取連接

        Connection conn = null;

        try {

            conn = DBUtils.getConnection();

            //開啟事務

            conn.setAutoCommit(false);

            //刪除訂單明細

            orderDao.deleteOrderItemsByOid(oid,conn);

            //刪除訂單

            orderDao.delete(oid,conn);

              

            //提交事務

            conn.commit();

            //異常回滾

              

        } catch (Exception e) {

            e.printStackTrace();

            try {

                conn.rollback();

            } catch (SQLException e1) {

                e1.printStackTrace();

            }

        }

    }

 

  1. DAO實現

接口:OrderDao

 

/**

     * 刪除訂單明細

     * @param oid

     * @param conn

     */

    void deleteOrderItemsByOid(String oid, Connection conn);

 

    /**

     * 刪除訂單

     * @param oid

     * @param conn

     */

    void delete(String oid, Connection conn);

 

 

實現類:OrderDaoImpl

 

@Override

    public void deleteOrderItemsByOid(String oid, Connection conn) {

        QueryRunner qr = new QueryRunner();

        String sql = "delete from orderitems where oid = ?";

        try {

            qr.update(conn, sql, oid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("刪除指定的訂單明細失敗");

        }

        

    }

 

    @Override

    public void delete(String oid, Connection conn) {

        QueryRunner qr = new QueryRunner();

        String sql="delete from orders where id = ?";

        try {

            qr.update(conn, sql, oid);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("刪除指定的訂單失敗");

        }

    }

 

  1. 管理員功能(賣家)

    1. 添加商品

      1. 功能分析

 

頁面修改:

  1. 修改表單請求路徑

 

 

 

  1. Servlet實現

package cn.itcast.web;

 

import java.io.File;

import java.io.IOException;

import java.lang.reflect.InvocationTargetException;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import org.apache.commons.beanutils.BeanUtils;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileUploadException;

import org.apache.commons.fileupload.disk.DiskFileItemFactory;

import org.apache.commons.fileupload.servlet.ServletFileUpload;

 

import cn.itcast.domain.Good;

import cn.itcast.domain.User;

import cn.itcast.service.GoodService;

import cn.itcast.service.impl.GoodServiceImpl;

import cn.itcast.utils.DirUtils;

import cn.itcast.utils.UUIDUtils;

 

public class AddGoodServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

          

        //校驗登錄

        User loginUser = (User)request.getSession().getAttribute("loginUser");

        if(loginUser == null){

            response.sendRedirect(request.getContextPath()+"/login.jsp");

            return;

        }

          

        //保證圖片上傳成功

          

        //fileUpload技術,核心對象,DiskFileItemFactory ServletFileUpload FileItem

        //DiskFileItemFactory:輔助作用,幫助解析request,將數據解析成一個一個的FileItem

        //ServletFileUpload:解析的核心對象,需要綁定DiskFileItemFactory

        //FileItem:封裝了所有input輸入框的數據的對象

          

        DiskFileItemFactory factory = new DiskFileItemFactory();

        //DiskFileItemFactory綁定到ServletFileUpload

        ServletFileUpload fileUpload = new ServletFileUpload(factory);

        //創建一個map集合用來存儲good相關數據

        Map<String ,Object> map = new HashMap<String ,Object>();

        try {

            //解析request對象

            List<FileItem> list = fileUpload.parseRequest(request);

              

            //針對集合進行遍歷,判斷當前fileItem是否是一個普通字段,還是文件上傳

            for (FileItem item : list) {

                //判斷當前是否是普通字段

                if(item.isFormField()){

                    //表示,我是普通字段

                    //獲取inputname

                    String fieldName = item.getFieldName();

                    //獲取inputvalue

                    String value = item.getString("utf-8");

                      

                    //將數據保存到一個map集合

                    map.put(fieldName, value);

                }else{

                    //我是文件上傳

                    //確定upload文件夾的位置,要保存圖片在這個文件家中

                    //String realPath = this.getServletContext().getRealPath("/upload");

                    //要輸出一個文件,要獲取文件名

                    String fileName = item.getName();

                    //為了防止重復,需要使用UUID,重寫文件名

                    String uuid = UUIDUtils.getUUID();

                    fileName = uuid + fileName;

                    //目錄打散,在upload文件路徑后,再加幾層目錄,

                    String dir = DirUtils.getDir(fileName);

                    //這個文件目錄,可能不存在,需要判斷,如果不存在,創建

                    //輸出指定位置,要在指定位置下,目錄打散

                    File file = new File("c:/picture",dir);

                    if(file.exists()){

                        //存在,什么都不做

                    }else{

                        file.mkdirs();

                    }

                    //向指定位置輸出文件

                    try {

                        item.write(new File("c:/picture"+dir,fileName));

                    } catch (Exception e) {

                        e.printStackTrace();

                    }

                    //保存圖片上傳地址,后期才能通過路徑找到圖

                    // /upload/11/9/f913990ee3f04e029dd34f7d55a60fb1.jpg

                    // /upload/14/13/c39e4f0266b745a3b91d2697b9d6c544WIN_20151231_16_46_42_Pro.jpg

                    map.put("imgurl", "/picture"+dir+"/"+fileName);

                }

            }

              

        } catch (FileUploadException e) {

            e.printStackTrace();

        }

          

          

        //封裝數據到good對象

        Good g = new Good();

        try {

            BeanUtils.populate(g, map);

        } catch (Exception e) {

            e.printStackTrace();

        }

        //調用service方法添加商品

        GoodService goodService = new GoodServiceImpl();

        goodService.addGood(g);

          

        //查看所有商品

        response.sendRedirect(request.getContextPath()+"/goods_admin.jsp");

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

 

 

  1. Service實現

接口:GoodService

/**

     * 添加商品

     * @param g

     */

    void addGood(Good g);

 

實現類:GoodServiceImpl

 

public void addGood(Good g) {

        goodDao.addGood(g);

    }

 

  1. DAO實現

接口:GoodDao

 

/**

     * 添加商品

     * @param g

     */

    void addGood(Good g);

 

實現類:GoodDaoImpl

 

public void addGood(Good g) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "insert into goods values(null,?,?,?,?,?,?,?)";

        try {

            qr.update(sql, g.getName(), g.getMarketprice(), g.getEstoreprice(),

                    g.getCategory(), g.getNum(), g.getImgurl(),

                    g.getDescription());

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("添加商品失敗");

        }

    }

 

補充內容:

根據演示效果——重新部署服務器之后,會丟失商品圖片

 

解決方案:將圖片保存與項目和服務器無關的位置

思路:

1:保證圖片上傳的時候,一定將圖片保存到指定位置(c:/picture)

2: 保存圖片的url的時候,路徑,一定/picture/11/12/1.jpg。

3:專門設計一個Servlet,接受處理圖片請求,在Servlet中,讀取圖片資源,

使用IO技術,然后使用response對象發出響應


修改請求地址(例如,在商品列表頁面):/estore2/pic?imgurl=/picture/8/15/774595f7c5b44fefa7b08b9cc5969e9f.jpg

PictureServlet:

package cn.itcast.web;

 

import java.io.File;

import java.io.FileInputStream;

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.ServletOutputStream;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

public class PictureServlet extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        //1)瀏覽器發送請求給服務器(商品需要圖片名稱)

        // /picture/14/1/85a3510c83ef4fc98afbb4a4a0095e2e2.jpg

        String imgurl = request.getParameter("imgurl");

        //2)讀取服務器硬盤上的圖片數據

        FileInputStream in = new FileInputStream(new File("c:"+imgurl));

          

        //3)使用IO技術,將數據發送(使用response對象發送數據)

        ServletOutputStream out = response.getOutputStream();

        byte[] buf =new byte[1024];

        int len = 0;

        while((len = in.read(buf)) != -1){

            out.write(buf, 0, len);

        }

        

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

  1. 查看商品(管理員)

為什么,已經存在商品列表功能,還要在后台制作一個商品列表給管理員?

注意:設計一個項目,分角色,角色下有權限,那么不同角色有不同權限,

 

作為買家,普通用戶,無法使用管理員功能

同理,作為管理員,無法使用普通用戶功能,只能重新制作一個讓管理員使用。

 

 

添加完成商品后,從數據庫中重新查詢所有商品,展示在goods_admin.jsp頁面上

Servlet實現:

 

package cn.itcast.web;

 

import java.io.IOException;

import java.util.List;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.Good;

import cn.itcast.service.GoodService;

import cn.itcast.service.impl.GoodServiceImpl;

 

public class QueryAllGoodsAdminServelt extends HttpServlet {

 

    public void doGet(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

 

        // 調用service方法獲取數據

        GoodService goodService = new GoodServiceImpl();

        List<Good> list = goodService.findAll();

        // 將數據存入request容器,返回goods.jsp

        request.setAttribute("list", list);

        request.getRequestDispatcher("/goods_admin.jsp").forward(request, response);

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response)

            throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

  1. 權限管理

為什么要做權限管理?

 

商品上傳,只有賣家可以使用,買家是不能使用的,需要做權限的控制

 

如何實現權限管理?

 

我們要解決,誰,是什么角色,能做哪些操作?

 

兩種權限數據解決方案:

    

第一種:使用數據庫表,來控制用戶的權限,一般需要5張表(用戶表 角色表 權限表 用戶角色表 角色權限表)

 

5張表之間的關系:

 

    第二種:使用配置文件管理權限

在用戶表中直接設置用戶的角色,將角色的權限設置在配置文件中,后期用戶訪問的時候,將用戶的請求路徑和角色權限配置文件中的內容比較,如果一致表示用戶擁有該權限。

 

在用戶表中直接設置用戶的角色——用戶和角色都在一張表。

將角色的權限設置在配置文件中——使用一個txt文件,保存角色對應的權限

將用戶的請求路徑和角色權限配置文件中的內容比較——request獲取請求路徑,要與配置文件的中內容一致,有權限

 

    如何定義配置角色權限配置文件?

普通用戶權限,存放在user.txt

管理員權限,存在admin.txt

 

普通用戶權限user.txt:

 

管理員權限admin.txt:

第二種解決方案代碼實現:

 

使用什么技術做權限的控制?

過濾器。

 

實現步驟:

第一步:創建兩個集合,准備加載權限的數據

第二步:在過濾器初始化的時候,加載權限的數據

第三步:獲取用戶的請求

第四步:開始比對,用戶的請求和用戶所具有的權限是否一致

第五步:一致,放行,不一致,拋出異常

 

代碼實現:

package cn.itcast.filter;

 

import java.io.BufferedReader;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileReader;

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

 

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.domain.User;

 

public class PrivilegeFilter implements Filter{

    //第一步:創建兩個集合,准備加載權限的數據

    //創建集合存放user的權限

    private List<String> userList = new ArrayList<String>();

    //創建集合存放admin的權限

    private List<String> adminList = new ArrayList<String>();

    

    @Override

    public void init(FilterConfig config) throws ServletException {

        System.out.println("==================權限數據開始加載==============");

        //第二步:在過濾器初始化的時候,加載權限的數據

          

        //如何確定user.txt文件的位置。WEB-INF/classes

          

        //先獲取servletContext對象,通過他來調用getRealPath(),獲取到的是配置文件路徑

        String realPath = config.getServletContext().getRealPath("WEB-INF/classes/user.txt");

        //服務器上路徑:C:\apache-tomcat-7.0.52\webapps\estore2\WEB-INF\classes/user.txt

        // C:\apache-tomcat-7.0.52\webapps\estore2\WEB-INF\classes/user.txt

        //System.out.println(realPath);

        try {

            //可以通過BufferedReader讀取配置文件,一行一行的讀取

            BufferedReader reader = new BufferedReader(new FileReader(new File(realPath)));

            String line = null;

            while( (line = reader.readLine()) != null){

                //將數據存入集合

                userList.add(line);

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

        System.out.println(userList);

          

        String realPath2 = config.getServletContext().getRealPath("WEB-INF/classes/admin.txt");

          

        try {

            BufferedReader reader = new BufferedReader(new FileReader(new File(realPath2)));

            String line = null;

            while((line = reader.readLine()) != null){

                adminList.add(line);

            }

              

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

        System.out.println(adminList);

          

        System.out.println("==================權限數據加載完成 ==============");

    }

 

    @Override

    public void doFilter(ServletRequest request, ServletResponse response,

            FilterChain chain) throws IOException, ServletException {

        HttpServletRequest req = (HttpServletRequest)request;

        HttpServletResponse res = (HttpServletResponse)response;

          

        //第三步:獲取用戶的請求,將請求和配置文件中權限進行比對,如果一致,放行,不一致,拋出異常

          

        //獲取用戶的請求

        String requestURI = req.getRequestURI();

        //requestURI——————/estore2/findAllGoods

        requestURI = requestURI.substring(req.getContextPath().length());

        // /findAllGoods

        System.out.println(requestURI);

          

        //有一些頁面和Servlet請求,不需要管理

        //需要知道,那些請求需要被關管理,發現,只有請求,包含在集合中,就需要被管理

        boolean isUser = userList.contains(requestURI);

        boolean isAdmin = adminList.contains(requestURI);

          

        if(isUser || isAdmin){

            //表示這個請求,是一個需要被管理的權限

            //第四步:開始比對,用戶的請求和用戶所具有的權限是否一致

              

            //獲取用戶的登錄信息loginUser role :記錄用戶的角色,這個角色對應的權限配置文件

            User loginUser = (User)req.getSession().getAttribute("loginUser");

            if(loginUser == null){

                res.sendRedirect(req.getContextPath()+"/login.jsp");

                return;

            }else{

                //可以獲取角色,可以進行比對

                if("user".equals(loginUser.getRole()) && isUser){

                    //"user".equals(loginUser.getRole())

                    //判斷你的角色是否是一個普通用戶

                    //isUser==true:用戶請求,是請求了一個普通用戶權限

                    //isUser==false:用戶請求,是請求了一個管理員用戶權限

                      

                    //當前用戶是一個普通用戶,而且,請求的權限是普通用戶權限

                    //放行

                    chain.doFilter(req, res);

                }else if("admin".equals(loginUser.getRole()) && isAdmin){

                    //當前用戶是一個管理員用戶,他請求的權限也是管理員權限

                    //放行

                    chain.doFilter(req, res);

                }else{

                    //表示當前用戶的角色和權限不一致

                    throw new RuntimeException("權限不足,請聯系超級管理員!");

                }

            }

              

        }else{

            //不需要管理的權限

            chain.doFilter(req, res);

        }

    }

 

    @Override

    public void destroy() {

        

    }

 

}

 

  1. 配置網站錯誤頁面

軟件在運行時,會出現各種錯誤,這些錯誤不希望用戶看到,這時需要配置一個統一的錯誤頁面,當系統出錯時,就會跳轉到這個錯誤頁面,這個錯誤頁面一般比較友好

在web.xml中添加如下配置即可

<!-- 配置全站錯誤頁面 -->

<error-page>

    <error-code>404</error-code>

    <location>/404.jsp</location>

</error-page>

<error-page>

    <error-code>500</error-code>

    <location>/500.jsp</location>

</error-page>

 

 

 

  1. 定時器掃描過期訂單

    1. 定時任務介紹

  1. Timer回顧

 

 

 

 

  1. 定時掃描過期訂單並設置為過期

    1. 創建監聽器,監聽ServletContext啟動

 

需求:定時掃描過期訂單並設置為過期

 

1定時掃描,需要用到Timer TimeTask 類,在哪里使用這兩個類?

需要在項目啟動的時候,掃描訂單。

 

2:什么對象可以監控到項目啟動

    ServletContextListener,可以監聽項目啟動和關閉

 

3:定時器中的任務是什么?

 

    獲取狀態為1的訂單,比對創建時間,如果時間超出兩個小時,就設置過期(狀態:3)

 

 

注冊監聽器

package cn.itcast.listener;

 

import java.util.Timer;

import java.util.TimerTask;

 

import javax.servlet.ServletContextEvent;

import javax.servlet.ServletContextListener;

 

import cn.itcast.service.OrderService;

import cn.itcast.service.impl.OrderServiceImpl;

 

public class SaoMiaoListener implements ServletContextListener{

 

    @Override

    public void contextInitialized(ServletContextEvent sce) {

        //開啟定時掃描任務

        //創建定時器

        Timer timer = new Timer();

        timer.schedule(new TimerTask() {

              

            @Override

            public void run() {

                System.out.println("===================定時掃描過期訂單啟動================");

                //調用service方法,執行定時任務

                OrderService orderService = new OrderServiceImpl();

                orderService.saomiao();

                System.out.println("===================定時掃描過期訂單完成================");

            }

            //0:立即執行

            //1000*60*60*2:兩個小時執行一次

        }, 0 ,1000*60*60*2);

          

        //2:00:00 定時器啟動 2:20:00,創建了訂單 4:00:00 定時器啟動 6:00:00 定時器啟動,訂單早已經過期

        //每一個訂單,都設置一個定時器。

        //每一個訂單創建,都會在內存中創建一個定時器對象,而且這個定時器對象一定要兩個小時之后才關閉

        //在線支付,判斷,只要訂單過期了,直接設置狀態為3

    }

    

    @Override

    public void contextDestroyed(ServletContextEvent sce) {

    }

 

}

 

配置文件:

 

  1. Service實現

接口:OrderService

 

/**

     * 掃描過期訂單的方法

     */

    void saomiao();

 

 

實現類:OrderServiceImpl

public void saomiao() {

        // 定時任務:獲取所有狀態為1訂單,然后,如果超出時間(2個小時),修改狀態:3

        //第一步:獲取所有狀態為1訂單

        List<Order> list = orderDao.findByStatus(1);

        //第二步:循環遍歷,做判斷

        for (Order order : list) {

            //第三步:比較時間,現在的時間減去提交訂單的時間,大於兩個小時,狀態改為3

              

            long now = new Date().getTime();

            long time = order.getCreatetime().getTime();

            if(now - time >= 1000*60*60*2){

                //第四步:修改狀態為3

                orderDao.updateStatus(3,order.getId());

            }

        }

    }

 

  1. Dao實現

接口:OrderDao

 

/**

     * 獲取指定狀態的訂單

     * @param i :指定狀態

     * @return

     */

    List<Order> findByStatus(int i);

 

    /**

     * 修改指定的訂單狀態

     * @param i

     * @param id

     */

    void updateStatus(int i, String id);

 

實現類:OrderDaoImpl

 

@Override

    public List<Order> findByStatus(int i) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "select * from orders where status = ?";

        try {

            return qr.query(sql, new BeanListHandler<Order>(Order.class), i);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("查詢指定狀態的訂單失敗");

        }

    }

 

    @Override

    public void updateStatus(int i, String id) {

        QueryRunner qr = new QueryRunner(DBUtils.getDataSource());

        String sql = "update orders set status = ? where id = ?";

        try {

            qr.update(sql, i,id);

        } catch (SQLException e) {

            e.printStackTrace();

            throw new RuntimeException("修改指定的訂單狀態失敗");

        }

    }

 

  1. 在線支付

    1. 在線支付介紹

ICBC 工商銀行

 

在線支付流程一:

總結:商城通過第三方平台和所有銀行交易

在線支付流程二:

 

 

  1. 易付寶支付介紹

易寶支付官網:https://www.yeepay.com/

 

易寶會給商家提供對應的支付接口以及文檔,開發人員在開發支付功能的時候,

只需要按照文檔中的說明直接完成對應的代碼即可。

 

支付接口及文檔下載:

 

  1. 編寫orders.jsp頁面上的支付鏈接

1)在訂單明細頁面上添加支付按鈕(未支付的訂單才有,發送訂單編號和金額)

效果:

 

  1. 編寫pay.jsp

  1. 修改表單提交請求路徑
  2. 將訂單編號和金額寫入隱藏域
  3. 給用戶顯示訂單編號和金額

 

  1. 支付的Servlet實現

 

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.utils.PaymentUtil;

 

/*

* 支付的Servlet程序

*/

public class PayServlet extends HttpServlet {

 

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

        // 獲取訂單號、金額、銀行編碼

        String orderid = request.getParameter("orderid"); // 訂單號

          

        String money = request.getParameter("money"); // 金額

        String pd_FrpId = request.getParameter("pd_FrpId"); // 銀行編碼

 

        // 根據易寶接口准備參數

        String p0_Cmd = "Buy";

        String p1_MerId = "10001126856"; // 商家編號 10001126856

        String p2_Order = orderid; // 訂單號

        String p3_Amt = "0.01"; // 金額,單位是元

        String p4_Cur = "CNY";

 

        String p5_Pid = "";

        String p6_Pcat = "";

        String p7_Pdesc = "";

        // 支付成功回調地址 ---- 第三方支付公司會訪問、用戶訪問

        // 第三方支付可以訪問網址

        // 需要獨立外網網卡

        String p8_Url = "http://127.0.0.1:8080/estore2/callback"; // 回調地址

        String p9_SAF = "";

        String pa_MP = "";

        String pr_NeedResponse = "1";

 

        // 將所有數據,進行數字簽名,加密算法由支付公司提供:注冊時,第三方支付平台提供給商家的加密算法的摘要

        String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl"; // 密鑰

        String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt, p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP, pd_FrpId, pr_NeedResponse, keyValue);

 

        // 將所有數據發送易寶指定地址

        request.setAttribute("pd_FrpId", pd_FrpId);

        request.setAttribute("p0_Cmd", p0_Cmd);

        request.setAttribute("p1_MerId", p1_MerId);

        request.setAttribute("p2_Order", p2_Order);

        request.setAttribute("p3_Amt", p3_Amt);

        request.setAttribute("p4_Cur", p4_Cur);

        request.setAttribute("p5_Pid", p5_Pid);

        request.setAttribute("p6_Pcat", p6_Pcat);

        request.setAttribute("p7_Pdesc", p7_Pdesc);

        request.setAttribute("p8_Url", p8_Url);

        request.setAttribute("p9_SAF", p9_SAF);

        request.setAttribute("pa_MP", pa_MP);

        request.setAttribute("pr_NeedResponse", pr_NeedResponse);

        request.setAttribute("hmac", hmac);

 

        // 跳轉確認支付頁面

        request.getRequestDispatcher("/confirm.jsp").forward(request, response);

 

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        doGet(request, response);

    }

 

 

}

 

 

  1. 支付確認頁面confirm.jsp

  1. 顯示訂單編號和訂單金額
  2. 隱藏域中都是servlet中封裝給易寶的數據

 

  1. 回調函數Servlet

package cn.itcast.web;

 

import java.io.IOException;

 

import javax.servlet.ServletException;

import javax.servlet.http.HttpServlet;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

 

import cn.itcast.utils.PaymentUtil;

 

@SuppressWarnings({"serial","unused"})

public class CallbackServlet extends HttpServlet {

 

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

        // 校驗,易寶數字簽名

        String p1_MerId = request.getParameter("p1_MerId");

        String r0_Cmd = request.getParameter("r0_Cmd");

        String r1_Code = request.getParameter("r1_Code");

        String r2_TrxId = request.getParameter("r2_TrxId");

        String r3_Amt = request.getParameter("r3_Amt");

        String r4_Cur = request.getParameter("r4_Cur");

        String r5_Pid = request.getParameter("r5_Pid");

        String r6_Order = request.getParameter("r6_Order");

        String r7_Uid = request.getParameter("r7_Uid");

        String r8_MP = request.getParameter("r8_MP");

        String r9_BType = request.getParameter("r9_BType");

        String rb_BankId = request.getParameter("rb_BankId");

        String ro_BankOrderId = request.getParameter("ro_BankOrderId");

        String rp_PayDate = request.getParameter("rp_PayDate");

        String rq_CardNo = request.getParameter("rq_CardNo");

        String ru_Trxtime = request.getParameter("ru_Trxtime");

        String hmac = request.getParameter("hmac");

 

        // 將響應所有數據加密,比較hmac

        String keyValue = "69cl522AV6q613Ii4W6u8K6XuW8vM1N6bFgyv769220IuYe9u37N4y7rI4Pl";

        boolean isvalid = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd, r1_Code, r2_TrxId, r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType, keyValue);

        if (isvalid) {

            // 區分兩次通知處理方式

            if (r9_BType.equals("1")) {

                // 給用戶提示付款成功,查看付款結果

                System.out.println("收到1提示用戶,已經付款");

                response.setContentType("text/html;charset=utf-8");

                response.sendRedirect(request.getContextPath() + "/pay_success.jsp");

            } else if (r9_BType.equals("2")) {

                // 收到易寶到款通知,修改訂單狀態

                System.out.println("收到2 修改訂單狀態....");

                  

            }

        } else {

            throw new RuntimeException("數字簽名錯誤,假冒易寶!");

        }

    }

 

    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        doGet(request, response);

    }

 

}

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM