【JavaWeb】客戶關(guān)系管理系統(tǒng)

前言

為了鞏固開(kāi)發(fā)的流程巴刻,我們?cè)倌靡粋€(gè)客戶關(guān)系管理系統(tǒng)來(lái)練手...赤屋!

成果圖

我們完成的就是下面的項(xiàng)目肤京!

image

搭建配置環(huán)境

  • 配置Tomcat
  • 導(dǎo)入開(kāi)發(fā)包
  • 建立開(kāi)發(fā)用到的程序包
image
  • 在數(shù)據(jù)庫(kù)創(chuàng)建相對(duì)應(yīng)的表

    CREATE TABLE customer (

      id          VARCHAR(40) PRIMARY KEY,
      name        VARCHAR(20) NOT NULL,
      gender      VARCHAR(10) NOT NULL,
      birthday    DATE,
      cellphone   VARCHAR(30) NOT NULL,
      email       VARCHAR(30),
      preference  VARCHAR(200),
      type        VARCHAR(20),
      description VARCHAR(255)

    );


開(kāi)發(fā)實(shí)體

開(kāi)發(fā)實(shí)體十分簡(jiǎn)單抗斤,對(duì)照著數(shù)據(jù)庫(kù)的表就行了蹈垢!


    private String id;
    private String name ;
    private String gender ;
    private Date birthday ;
    private String cellphone ;
    private String eamil ;
    private String preference ;
    private String type ;
    private String description;

    //....各種setter、getter

開(kāi)發(fā)獲取數(shù)據(jù)庫(kù)連接池的Utils

導(dǎo)入配置文件


    <?xml version="1.0" encoding="UTF-8"?>
    <c3p0-config>
        <default-config>
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/zhongfucheng</property>
            <property name="user">root</property>
            <property name="password">root</property>

            <property name="acquireIncrement">5</property>
            <property name="initialPoolSize">10</property>
            <property name="minPoolSize">5</property>
            <property name="maxPoolSize">20</property>
        </default-config>

        <named-config name="mysql">
            <property name="driverClass">com.mysql.jdbc.Driver</property>
            <property name="jdbcUrl">jdbc:mysql://localhost:3306/zhongfucheng</property>
            <property name="user">root</property>
            <property name="password">root</property>

            <property name="acquireIncrement">5</property>
            <property name="initialPoolSize">10</property>
            <property name="minPoolSize">5</property>
            <property name="maxPoolSize">20</property>
        </named-config>

        <named-config name="oracle">
            <property name="driverClass">oracle.jdbc.driver.OracleDriver</property>
            <property name="jdbcUrl">jdbc:oracle:thin:@//localhost:1521/事例名...</property>
            <property name="user">用戶名</property>
            <property name="password">密碼</property>

            <property name="acquireIncrement">5</property>
            <property name="initialPoolSize">10</property>
            <property name="minPoolSize">5</property>
            <property name="maxPoolSize">20</property>
        </named-config>
    </c3p0-config>

開(kāi)發(fā)提供數(shù)據(jù)連接池的工具類


    public class Utils2DB {

        private static ComboPooledDataSource comboPooledDataSource = null;

            static {

                //它會(huì)自動(dòng)尋找配置文件吗讶,節(jié)點(diǎn)為mysql的數(shù)據(jù)庫(kù)(默認(rèn)就是Mysql)
                comboPooledDataSource = new ComboPooledDataSource();
            }

        public static DataSource getDataSource() {
            return comboPooledDataSource ;
        }

        public static Connection connection() {
            try {
                return comboPooledDataSource.getConnection();
            } catch (SQLException e) {
                e.printStackTrace();
                throw new RuntimeException("數(shù)據(jù)庫(kù)初始化失敗了燎猛!");
            }
        }
    }

開(kāi)發(fā)UUID工具類


    public class WebUtils {

        public static String makeId() {
            return UUID.randomUUID().toString();
        }
    }

開(kāi)發(fā)DAO

DAO應(yīng)該提供增加客戶和查詢用戶的功能

增加用戶


    public void addCustomer(Customer customer)  {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "INSERT INTO customer (id,name, gender, birthday, cellphone, preference, type, description) VALUES (?, ?, ?, ?, ?, ?, ?, ?,?)";

        //得到用戶傳遞進(jìn)來(lái)的數(shù)據(jù)
        String id = customer.getId();
        String name = customer.getName();
        String gender = customer.getGender();
        String cellphone = customer.getCellphone();
        String email = customer.getEmail();
        String preference = customer.getPreference();
        String type = customer.getType();
        String description = customer.getDescription();

        //對(duì)于日期,要轉(zhuǎn)換一下
        Date date = customer.getBirthday();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String birthday = simpleDateFormat.format(date);

        try {
            //向數(shù)據(jù)庫(kù)插入數(shù)據(jù)
            queryRunner.update(sql, new Object[]{id, name, gender, birthday, cellphone, email, preference, type, description});

            //插入記錄成功照皆!
        } catch (SQLException e) {

            //如果出現(xiàn)了異常重绷,就拋出Dao異常吧(自定義的異常)
            e.printStackTrace();

            throw new DaoException("添加用戶出錯(cuò)了!");
        }
    }

測(cè)試增加用戶

寫(xiě)完一個(gè)功能纵寝,不要急著去寫(xiě)其他的功能论寨,先測(cè)試一下星立!


    @Test
    public void add() {

        //為了測(cè)試的方便,直接使用構(gòu)造函數(shù)了葬凳!
        Customer customer = new Customer("1", "zhongfucheng", "男", new Date(), "1234", "aa@sina.com", "打代碼", "高貴的用戶", "我是個(gè)好人");

        CustomerDao customerDao = new CustomerDao();
        customerDao.addCustomer(customer);

    }
  • 好的绰垂,沒(méi)有報(bào)錯(cuò)!再看看數(shù)據(jù)庫(kù)-----------只要是中文的數(shù)據(jù)火焰,都亂碼了劲装!
image

解決的辦法,看我另外一篇博文:https://zhongfucheng.bitcron.com/post/jie-jue-cuo-wu/mysqlzhong-wen-luan-ma


查詢用戶

將所有的客戶查詢出來(lái)就行了昌简!


    //得到所有的用戶
    public List<Customer> getAll() {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM customer";
        try {
            List<Customer> customers = (List<Customer>) queryRunner.query(sql, new BeanListHandler(Customer.class));

            //如果集合大于個(gè)數(shù)大于0占业,就返回集合,不大于0纯赎,就返回null
            return customers.size() > 0 ? customers : null;

        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("獲取所有的用戶出錯(cuò)了谦疾!");
        }

    }

測(cè)試查詢用戶


    @Test
    public void find() {

        CustomerDao customerDao = new CustomerDao();
        List<Customer> customers = customerDao.getAll();

        for (Customer customer : customers) {

            System.out.println(customer.getName());
        }
    }
image

修改用戶信息

修改用戶信息首先要知道用戶的信息,在web端犬金,只有id能唯一標(biāo)識(shí)用戶念恍,我們需要通過(guò)id,獲取用戶全部信息(也就是Customer對(duì)象)


    public Customer find(String id) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM customer WHERE id = ?";

        try {
            Customer customer = (Customer) queryRunner.query(sql, new BeanHandler(Customer.class), new Object[]{id});

            return customer;

        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("查找用戶失敗了");
        }

    }

修改用戶都是外邊傳遞個(gè)對(duì)象進(jìn)來(lái)晚顷,Dao層取出對(duì)象的數(shù)據(jù)峰伙,從而對(duì)數(shù)據(jù)庫(kù)的數(shù)據(jù)進(jìn)行修改!


    public void update(Customer customer) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "UPDATE customer set name=?,gender=?,birthday=?,cellphone=?,email=?,preference=?,type=?,description=?  WHERE id = ?";

        try {
            queryRunner.update(sql, new Object[]{customer.getName(), customer.getGender(), customer.getBirthday(),customer.getCellphone(), customer.getEmail(), customer.getPreference(), customer.getType(), customer.getDescription(), customer.getId()});

        } catch (SQLException e) {

            e.printStackTrace();
            throw new DaoException("更新失敗");
        }
    }

測(cè)試修改用戶


    @Test
    public void update() {

        CustomerDao customerDao = new CustomerDao();

        //我們已經(jīng)知道了某id该默,通過(guò)id獲取得到用戶信息(Customer)
        String id = "043f7cce-c6f1-4155-b688-ba386cae1636";
        Customer customer = customerDao.find(id);

        //修改用戶信息
        customer.setName("看完博客要點(diǎn)贊");
        customerDao.update(customer);
    }
  • 原來(lái)該用戶的名字是d
image
  • 測(cè)試完之后:
image

刪除用戶

  • 通過(guò)外界傳遞進(jìn)來(lái)的id瞳氓,就可以刪除數(shù)據(jù)庫(kù)表中的記錄了

    public void delete(String id) {
        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "DELETE from  customer WHERE id = ?";
        try {
            queryRunner.update(sql, new Object[]{id});
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("刪除用戶失敗了");
        }
    }

測(cè)試刪除用戶


    @Test
    public void delete() {

        CustomerDao customerDao = new CustomerDao();

        //我們已經(jīng)知道了某id,通過(guò)id刪除數(shù)據(jù)庫(kù)中的記錄
        String id = "043f7cce-c6f1-4155-b688-ba386cae1636";

        customerDao.delete(id);
    }

數(shù)據(jù)庫(kù)已經(jīng)查詢不到id為043f7cce-c6f1-4155-b688-ba386cae1636的記錄了栓袖!

開(kāi)發(fā)service


    public class BusinessService {

        CustomerDao customerDao = new CustomerDao();

        public List<Customer> getAll() {

            return customerDao.getAll();
        }

        public void addCustomer(Customer customer) {

            customerDao.addCustomer(customer);
        }

        public void deleteCustomer(String id) {
            customerDao.delete(id); 
        }

        public void updateCustomer(Customer customer) {
            customerDao.update(customer);
        }

        public Customer findCustomer(String id) {
            return customerDao.find(id);
        }
    }

開(kāi)發(fā)web 的增加和查詢

提供UI匣摘,增加客戶的Servlet


        //直接跳轉(zhuǎn)到顯示增加用戶頁(yè)面的jsp
        request.getRequestDispatcher("/WEB-INF/addCustomer.jsp").forward(request, response);

開(kāi)發(fā)顯示添加客戶頁(yè)面


<form action="${pageContext.request.contextPath}/addCustomerController">
    <table border="1px">
        <tr>
            <td>用戶名:</td>
            <td><input type="text" name="name"></td>
        </tr>
        <tr>
            <td>性別:</td>
            <td>
                <input type="radio" name="gender" value="female">女
                <input type="radio" name="gender" value="male">男
            </td>
        </tr>
        <tr>
            <td>生日:</td>
            <td>
                <select id="year">
                    <option value="1900">1900</option>
                </select>
                <select id="month">
                    <option value="01">01</option>
                </select>
                <select id="day">
                    <option value="01">01</option>
                </select>
            </td>
        </tr>
        <tr>
            <td>電話號(hào)碼:</td>
            <td><input type="text" name="cellphone"></td>
        </tr>
        <tr>
            <td>郵箱:</td>
            <td><input type="text" name="email"></td>
        </tr>
        <tr>
            <td>愛(ài)好:</td>
            <td>
                <input type="checkbox" name="hobbies" value="唱歌">唱歌
                <input type="checkbox" name="hobbies" value="跳舞">跳舞
                <input type="checkbox" name="hobbies" value="打代碼">打代碼
            </td>
        </tr>
        <tr>
            <td>客戶類型</td>
            <td>
                <input type="radio" name="type" value="VIP">VIP
                <input type="radio" name="type" value="普通客戶">普通客戶
                <input type="radio" name="type" value="黑名單客戶">黑名單客戶
            </td>
        </tr>
        <tr>
            <td>描述</td>
            <td>
                <textarea name="description" cols="30" rows="10"></textarea>
            </td>
        </tr>
        <tr>
            <td><input type="submit" value="增添客戶"></td>
            <td><input type="reset" value="重置"></td>
        </tr>

    </table>
</form>
  • 效果是這樣子的
image

我們發(fā)現(xiàn),在日期的下拉框中裹刮,只有一個(gè)數(shù)據(jù)(因?yàn)槲覀冊(cè)趘alue中只寫(xiě)了一個(gè)數(shù)據(jù))

要想在下拉框中可以選擇很多的數(shù)據(jù)恋沃,那么value的值就不能單單只有一個(gè)。當(dāng)然了必指,也不可能在JSP頁(yè)面中寫(xiě)下面的代碼


                    <option value="1900">1900</option>
                    <option value="1901">1900</option>
                    <option value="1902">1900</option>
                    <option value="1903">1900</option>

我們用javaScript生成下拉框的數(shù)據(jù)就行了!恕洲!

  • 獲取年份塔橡!

    function makeYear() {

        //得到下拉框的控件
        var year = document.getElementById("year");

        //要想下拉框有更多的數(shù)據(jù),就需要有更多的option控件
        //js獲取得到年份是getFullYear()霜第,單單的getYear()只是獲取兩位數(shù)
        for (var i=1901; i<= new Date().getFullYear(); i++) {

            //生成option控件
            var option = document.createElement("option");

            //option控件的值和文本內(nèi)容為循環(huán)生成的年分葛家!
            option.value = i;
            option.innerText = i;

            //將生成option控件綁定到select控件上
            year.appendChild(option);
        }

    }
  • 獲取月份和日也類似

    function makeMonth() {
        var month = document.getElementById("month");
        for (var i = 2; i <= 12; i++) {
            var option = document.createElement("option");
            if (i < 10) {
                option.value = '0' + i;
                option.innerText = '0' + i;
            } else {
                option.value = i;
                option.innerText = i;
            }
            month.appendChild(option);
        }
    }

    function makeDay()
    {
        var day = document.getElementById("day");
        for(var i=2;i<=12;i++)
        {
            var option = document.createElement("option");
            if(i<10)
            {
                option.value = '0' + i;
                option.innerText = '0' + i;
            }else{
                option.value = i;
                option.innerText = i;
            }
            day.appendChild(option);
        }
    }
  • 在JSP頁(yè)面中導(dǎo)入javascript文件

  • 注意:javasrcipt文件不能放在WEB-INF下面!C诶唷q恕!否則是獲取不到的!5狻双仍!


    <script type="text/javascript" src="${pageContext.request.contextPath}/customer.js" ></script>
  • 這三個(gè)函數(shù)都是在頁(yè)面加載時(shí)就應(yīng)該被初始化了,所以在body上綁定onload時(shí)間即可W莱浴朱沃!

    function pageInit() {
        makeYear();
        makeMonth();
        makeDay();
    }

    <body onload="pageInit()">
  • 效果:
image

JavaScript拼湊數(shù)據(jù)

表單的數(shù)據(jù)非常多,毫無(wú)疑問(wèn)茅诱,我們會(huì)使用BeanUtils來(lái)將數(shù)據(jù)封裝到Bean對(duì)象中逗物!

對(duì)于表單的數(shù)據(jù),還是有些雜亂的瑟俭。表單中日期的年月日是分開(kāi)的翎卓,我們要么在客戶端將年月日的數(shù)據(jù)拼湊起來(lái),要么在服務(wù)器端將年月日拼湊起來(lái)摆寄!同理失暴,客戶的喜好可能不單單有一個(gè),但在Customer對(duì)象中椭迎,喜好單單用一個(gè)String類型來(lái)表示的锐帜。我們也要把客戶的喜好拼湊起來(lái)。

顯然畜号,在客戶端用javaScript做拼湊是非常方便的缴阎!


    function makeBirthday() {

        //獲取下拉框的數(shù)據(jù),把數(shù)據(jù)拼湊成日期字符串
        var year = document.getElementById("year");
        var month = document.getElementById("month");
        var day = document.getElementById("day");
        var birthday = year + "-" + month + "-" + day;

        //想要將拼湊完的字符串提交給服務(wù)器简软,用隱藏域就行了
        var input = document.createElement("input");
        input.type = "hidden";
        input.value = birthday;
        input.name = "birthday";

        //將隱藏域綁定在form下【為了方便蛮拔,在form中設(shè)置id,id名字為form】
        document.getElementById("form").appendChild(input);

    }

    function makePreference() {

        //獲取喜好的控件
        var hobbies = document.getElementsByName("hobbies");

        //定義變量痹升,記住用戶選中的選項(xiàng)
        var preference = "";

        //遍歷喜好的控件建炫,看用戶選上了什么!
        for (var i = 0; i < hobbies.length; i++) {

            if (hobbies[i].checked == true) {
                preference += hobbies[i].value + ",";
            }
        }

        //剛才拼湊的時(shí)候疼蛾,最后一個(gè)逗號(hào)是多余的肛跌,我們要把它去掉
        preference = preference.substr(0, preference.length - 1);

        //也是用隱藏域?qū)?shù)據(jù)帶過(guò)去給服務(wù)器
        var input = document.createElement("input");
        input.type = "hidden";
        input.value = preference;
        input.name = "preference";

        //將隱藏域綁定到form表單上
        document.getElementById("form").appendChild(input);

    }
  • 當(dāng)表單提交的時(shí)候,觸發(fā)上面兩個(gè)函數(shù)就行了察郁!所以在form表單上綁定onsumit事件衍慎!

    function makeForm() {

        makeBirthday();
        makePreference();
        return true;

    }

    <form action="${pageContext.request.contextPath}/addCustomerController" id="form" onsubmit=" return makeForm()" method="post">

開(kāi)發(fā)處理表單數(shù)據(jù)的Servlet

  • 將表單的數(shù)據(jù)封裝到Bean對(duì)象中,要開(kāi)發(fā)工具類

    public static <T> T request2Bean(HttpServletRequest httpServletRequest, Class<T> aClass) {

        try {

            //獲取Bean的對(duì)象
            T bean = aClass.newInstance();

            //獲取表單中所有的名字
            Enumeration enumeration = httpServletRequest.getParameterNames();

            //遍歷表單提交過(guò)來(lái)的名字
            while (enumeration.hasMoreElements()) {

                //每個(gè)名字
                String name = (String) enumeration.nextElement();

                //獲取得到值
                String value = httpServletRequest.getParameter(name);

                //如果用戶提交的數(shù)據(jù)不為空皮钠,那么將數(shù)據(jù)封裝到Bean中
                if (!value.equals("") && value != null) {
                    BeanUtils.setProperty(bean, name, value);
                }

            }
              return bean;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("封裝數(shù)據(jù)到Bean中稳捆,失敗了!");
        }

    }
  • 處理表單數(shù)據(jù)的Servlet代碼:

        //將表單的數(shù)據(jù)弄到Bean對(duì)象中
        Customer customer = WebUtils.request2Bean(request, Customer.class);

        try {
            //調(diào)用BusinessService層的方法麦轰,添加客戶
            BusinessService businessService = new BusinessService();
            businessService.addCustomer(customer);

            //如果執(zhí)行到這里乔夯,說(shuō)明成功了砖织,如果被catch了,說(shuō)明失敗了末荐。
            request.setAttribute("message", "添加成功侧纯!");

        } catch (Exception e) {
            e.printStackTrace();
            request.setAttribute("message", "添加失敗");
        }
        request.getRequestDispatcher("/message.jsp").forward(request, response);

  • 效果:
image

提供查詢客戶界面的Servlet


        //跳轉(zhuǎn)到顯示客戶界面信息的jsp
        request.getRequestDispatcher("/WEB-INF/lookCustomer.jsp").forward(request, response);

開(kāi)發(fā)顯示客戶信息的頁(yè)面


    <c:if test="${empty(list)}">
        對(duì)不起,還沒(méi)有任何客戶的信息鞠评!
    </c:if>

    <c:if test="${!empty(list)}">
        <table border="1px">
            <tr>
                <td>用戶名:</td>
                <td>密碼:</td>
                <td>性別:</td>
                <td>生日:</td>
                <td>電話號(hào)碼:</td>
                <td>郵箱:</td>
                <td>類型:</td>
                <td>描述:</td>
            </tr>

            <c:forEach items="${list}" var="customer">
                <tr>
                    <td>${customer.name}</td>
                    <td>${customer.gender}</td>
                    <td>${customer.birthday}</td>
                    <td>${customer.cellphone}</td>
                    <td>${customer.email}</td>
                    <td>${customer.preference}</td>
                    <td>${customer.type}</td>
                    <td>${customer.description}</td>
                </tr>
            </c:forEach>
        </table>
    </c:if>
  • 效果:
image

將功能拼接在首頁(yè)上

采用分貞技術(shù)茂蚓,讓界面更加好看!

index頁(yè)面:


  <frameset rows="25%,*">
      <frame src="${pageContext.request.contextPath }/head.jsp" name="head">
      <frame src="${pageContext.request.contextPath }/body.jsp" name="body">
  </frameset>

head頁(yè)面:


    <body style="text-align: center;">

    <h1>客戶管理系統(tǒng)剃幌!</h1>

    <a href="${pageContext.request.contextPath}/AddCustomer" target="body">增添客戶</a>
    <a href="${pageContext.request.contextPath}/LookCustomer" target="body">查看客戶</a>
    </body>

body頁(yè)面:


    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <html>
    <head>
        <title>Title</title>
    </head>
    <body>
    </body>
    </html>
  • 效果:
效果圖

改善顯示頁(yè)面

現(xiàn)在問(wèn)題來(lái)了聋涨,如果我們客戶信息有非常非常地多,我們不可能把客戶信息全部都擠在同一個(gè)頁(yè)面上负乡,如果我們這樣做的話牍白,網(wǎng)頁(yè)的長(zhǎng)度就會(huì)非常的長(zhǎng)!

于是乎抖棘,我們就需要用到了分頁(yè)的技術(shù)茂腥,對(duì)于分頁(yè)技術(shù)基礎(chǔ)的講解,在我另一篇博文中有介紹:https://zhongfucheng.bitcron.com/post/jdbc/jdbcdi-si-pian-shu-ju-ku-lian-jie-chi-dbutilskuang-jia-fen-ye

看完上篇博文切省,我們知道最岗,首先要做的就是:明確分頁(yè)技術(shù)中需要用到的4個(gè)變量的值!

查詢總記錄數(shù)

查詢總記錄數(shù)也就是查詢數(shù)據(jù)庫(kù)表的記錄有多少條朝捆,這是關(guān)于對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)的操作般渡,所以肯定是在dao層做!


    public Long getTotalRecord() {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM customer";

        try {
            //獲取查詢的結(jié)果
            Long l = (Long) queryRunner.query(sql, new ScalarHandler());
            return l;

        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查詢總記錄數(shù)失敗了芙盘!");
        }

    }

查詢分頁(yè)的數(shù)據(jù)

獲取分頁(yè)的數(shù)據(jù)也是查詢數(shù)據(jù)庫(kù)的記錄驯用,這也是關(guān)于對(duì)數(shù)據(jù)庫(kù)的操作,所以也是在Dao層做的儒老!


    /*查詢分頁(yè)數(shù)據(jù)*/
    //獲取分頁(yè)的數(shù)據(jù)是需要start和end兩個(gè)變量的【從哪條開(kāi)始取蝴乔,取到哪一條】
    public List<Customer> getPageData(int start, int end) {

        QueryRunner queryRunner = new QueryRunner(Utils2DB.getDataSource());

        String sql = "SELECT * FROM customer LIMIT ?,?";

        try {
            List<Customer> customers = (List<Customer>) queryRunner.query(sql, new BeanListHandler(Customer.class), new Object[]{start, end});

            return customers;

        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("獲取分頁(yè)數(shù)據(jù)失敗了!");
        }
    }

分析

現(xiàn)在我們已經(jīng)可以知道總記錄數(shù)了驮樊,對(duì)于其他3個(gè)變量(每頁(yè)顯示記錄數(shù)【由程序員來(lái)指定】薇正,當(dāng)前是多少頁(yè)【由用戶來(lái)指定】,總頁(yè)數(shù)【由總記錄數(shù)和每頁(yè)顯示記錄數(shù)來(lái)算數(shù)來(lái)的】)

現(xiàn)在要分析的是囚衔,這些變量應(yīng)該放在哪里呢铝穷??佳魔?全部放在Dao層?晦炊?全部放在Dao層是可以實(shí)現(xiàn)功能的鞠鲜,但是宁脊,這樣MVC結(jié)構(gòu)就被破壞掉了(Dao層只用來(lái)對(duì)數(shù)據(jù)進(jìn)行CRUD操作,4個(gè)變量存在Dao層贤姆,是不合理的)

最好的做法是這樣的:創(chuàng)建一個(gè)實(shí)體Page榆苞,將分頁(yè)用到的信息全部封裝在Page中實(shí)現(xiàn)!Page就代表著分頁(yè)的數(shù)據(jù)這樣就非常符合面向?qū)ο蟮乃枷肓耍?/p>

將數(shù)據(jù)封裝到Page中并在頁(yè)面上顯示分頁(yè)的數(shù)據(jù)

①:創(chuàng)建Page類


    //保存著分頁(yè)的數(shù)據(jù)
    private List<Customer> list;

    //總記錄數(shù)
    private long totalRecord;

    //每頁(yè)顯示記錄數(shù)霞捡,這里我規(guī)定每頁(yè)顯示3條
    private int linesize = 3;

    //總頁(yè)數(shù)
    private int totalPageCount;

    //當(dāng)前顯示的頁(yè)數(shù)
    private long currentPageCount;

    //...各種的setter坐漏、getter

②:BusinessService應(yīng)該提供獲取分頁(yè)數(shù)據(jù)的服務(wù)


    //既然Page對(duì)象代表是分頁(yè)數(shù)據(jù),那么返回Page對(duì)象即可碧信!
    //web層應(yīng)該傳入想要看哪一頁(yè)數(shù)據(jù)的參數(shù)赊琳!
    public Page getPageData(String currentPageCount) {

        Page page = new Page();

        //獲取數(shù)據(jù)庫(kù)中有多少條記錄,并封裝到Page對(duì)象中
        Long totalRecord = customerDao.getTotalRecord();
        page.setTotalRecord(totalRecord);

        //算出總頁(yè)數(shù)砰碴,并封裝到Page對(duì)象中
        int totalPagecount = (int) (totalRecord % page.getLinesize() == 0 ? totalRecord / page.getLinesize() : totalRecord / page.getLinesize() + 1);
        page.setTotalPageCount(totalPagecount);

        int start ;
        int end = page.getLinesize();

        //現(xiàn)在又分兩種情況了躏筏,如果傳遞進(jìn)來(lái)的參數(shù)是null的,那么說(shuō)明外界是第一次查詢的
        if (currentPageCount == null) {

            //第一次查詢呈枉,就應(yīng)該設(shè)置當(dāng)前頁(yè)數(shù)是第一頁(yè)
            page.setCurrentPageCount(1);

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);
        } else {

            //如果不是第一次趁尼,就把外界傳遞進(jìn)來(lái)的頁(yè)數(shù)封裝到Page對(duì)象中
            page.setCurrentPageCount(Long.parseLong(currentPageCount));

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);

        }
        return page;

    }

③:web層調(diào)用BusinessService層的功能,獲取得到Page對(duì)象


        //獲取用戶想要看的頁(yè)數(shù)猖辫,如果是第一次酥泞,那肯定為null
        String currentPageCount = request.getParameter("currentPageCount");

        //調(diào)用BusinessService的方法,獲取得到所有客戶信息
        BusinessService businessService = new BusinessService();
        Page page  = businessService.getPageData(currentPageCount);

        //把客戶信息帶過(guò)去給jsp頁(yè)面
        request.setAttribute("page", page);

        //跳轉(zhuǎn)到顯示客戶界面信息的jsp
        request.getRequestDispatcher("/WEB-INF/lookCustomer.jsp").forward(request, response);

④:在JSP頁(yè)面中啃憎,使用EL表達(dá)式獲取到Page對(duì)象芝囤,從而輸出數(shù)據(jù)


        <c:forEach items="${page.list}" var="customer">
            <tr>
                <td>${customer.name}</td>
                <td>${customer.gender}</td>
                <td>${customer.birthday}</td>
                <td>${customer.cellphone}</td>
                <td>${customer.email}</td>
                <td>${customer.preference}</td>
                <td>${customer.type}</td>
                <td>${customer.description}</td>
            </tr>
        </c:forEach>

⑤:在JSP頁(yè)面中顯示頁(yè)碼,同時(shí)把碼數(shù)綁定到超鏈接去荧飞!


    <%--提供頁(yè)數(shù)的界面--%>
    <c:forEach var="pageNum" begin="1" end="${page.totalPageCount}">
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${pageNum}">
            ${pageNum}
        </a>
    </c:forEach>

  • 效果:

[圖片上傳失敗...(image-a531b0-1519565666244)]


讓分頁(yè)的功能更加完善

增加上一步和下一步

一般的分頁(yè)不僅僅只有頁(yè)碼給你凡人,還有上一步和下一步。我們?cè)贘SP頁(yè)面上也能添加這樣的功能叹阔,其實(shí)這是非常簡(jiǎn)單的挠轴!


    <%--如果當(dāng)前的頁(yè)碼大于1,才顯示上一步--%>
    <c:if test="${page.currentPageCount>1}">

        <%--把傳遞過(guò)去的頁(yè)碼-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount-1}">
            上一步
        </a>
    </c:if>

    <%--如果當(dāng)前的頁(yè)碼小于總頁(yè)數(shù)耳幢,才顯示下一步--%>
    <c:if test="${page.currentPageCount<page.totalPageCount}">

        <%--把傳遞過(guò)去的頁(yè)碼-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}">
            下一步
        </a>
    </c:if>

  • 效果:
image

顯示當(dāng)前頁(yè)數(shù)岸晦,總頁(yè)數(shù),總記錄數(shù)


    當(dāng)前頁(yè)數(shù)是:[${page.currentPageCount}]&nbsp;&nbsp;&nbsp;

    總頁(yè)數(shù)是:${page.totalPageCount}&nbsp;&nbsp;

    總記錄數(shù)是:${page.totalRecord}
  • 效果:
image

跳轉(zhuǎn)到某頁(yè)上


    <input type="text" id="currentPageCount">
    <input type="button" value="跳轉(zhuǎn)">
  • 頁(yè)面效果:
image

我們現(xiàn)在要做的就是:怎么樣才能輸入框輸入內(nèi)容睛藻,然后點(diǎn)擊跳轉(zhuǎn)按鈕启上,將輸入框的數(shù)據(jù)發(fā)送到Servlet上,然后實(shí)現(xiàn)跳轉(zhuǎn)到某頁(yè)上功能

明顯地店印,我們肯定要使用JavaScript代碼冈在!


<script type="text/javascript">

    /*既然寫(xiě)上了JavaScript代碼了,就順便驗(yàn)證輸入框輸入的數(shù)據(jù)是否合法吧*/
    function goPage() {

        /*獲取輸入框控件*/
        var input = document.getElementById("currentPageCount");

        /*獲取輸入框的數(shù)據(jù)*/
        var value = input.value;

        if(value==null || value==""){
            alert("請(qǐng)輸入頁(yè)碼");
            return false;
        }

        if(!value.match("\\d+")){
            alert("請(qǐng)輸入數(shù)字");
            return false;
        }

        if(value<1 || value>${page.totalPageCount}){
            alert("請(qǐng)輸入合法數(shù)據(jù)");
            return false ;
        }

        window.location.href="${pageContext.request.contextPath}/LookCustomer?currentPageCount="+value;
    }

</script>

  • 效果:
image

記錄JSP頁(yè)面的開(kāi)始頁(yè)和結(jié)束頁(yè)

為什么我們要記錄JSP頁(yè)面的開(kāi)始頁(yè)和結(jié)束頁(yè)呢按摘?經(jīng)過(guò)上面層層地優(yōu)化包券,我們感覺(jué)不出有什么問(wèn)題了纫谅。那是因?yàn)閿?shù)據(jù)量太少!

我們?cè)囍嗵砑狱c(diǎn)記錄進(jìn)數(shù)據(jù)庫(kù)溅固,再回來(lái)看看付秕!

image

從上面的圖我們可以發(fā)現(xiàn)頁(yè)數(shù)有多少,JSP頁(yè)面就顯示多少侍郭!這明顯不合理的询吴,如果有100頁(yè)也顯示100頁(yè)嗎?

我們做一個(gè)規(guī)定亮元,一次只能顯示10頁(yè)的數(shù)據(jù)猛计。那么顯示哪10頁(yè)呢?這又是一個(gè)問(wèn)題了苹粟,如果我們?cè)诳吹?1頁(yè)的數(shù)據(jù)有滑,應(yīng)該顯示的是第7到第16頁(yè)的數(shù)據(jù)(顯示11附近的頁(yè)數(shù)),我們?cè)诳吹?頁(yè)的數(shù)據(jù)嵌削,應(yīng)該顯示第1到第10頁(yè)的數(shù)據(jù)毛好。用戶想要看的頁(yè)數(shù)是不明確的,我們顯示附近的頁(yè)數(shù)也是不明確的苛秕!肌访。我們應(yīng)該把用戶想要看的頁(yè)數(shù)記錄下來(lái),然后根據(jù)邏輯判斷艇劫,顯示附近的頁(yè)數(shù)

我們顯示頁(yè)數(shù)的代碼是這樣的:

image

很明顯吼驶,我們只要控制了begin和end中的數(shù)據(jù),就控制顯示哪10頁(yè)了店煞!

①在Page類中多定義兩個(gè)成員變量


    //記錄JSP頁(yè)面開(kāi)始的頁(yè)數(shù)和結(jié)束的頁(yè)數(shù)
    private int startPage;
    private int endPage;

    //Setter,Getter方法

②開(kāi)始頁(yè)數(shù)和結(jié)束頁(yè)數(shù)受用戶想看的頁(yè)數(shù)影響蟹演,在BusinessService的getPageData()加入下面的邏輯


            //第一次訪問(wèn)
            page.setStartPage(1);
            page.setEndPage(10);

            //不是第一次訪問(wèn)
            if (page.getCurrentPageCount() <= 10) {
                page.setStartPage(1);
                page.setEndPage(10);
            } else {
                page.setStartPage((int) (page.getCurrentPageCount() - 4));
                page.setEndPage((int) (page.getCurrentPageCount() + 5));

                //如果因?yàn)榧訙p角標(biāo)越界了,那么就設(shè)置最前10頁(yè)顷蟀,或者最后10頁(yè)
                if (page.getStartPage() < 1) {
                    page.setStartPage(1);
                    page.setEndPage(10);
                }
                if (page.getEndPage() > page.getTotalPageCount()) {
                    page.setEndPage(page.getTotalPageCount());
                    page.setStartPage(page.getTotalPageCount() - 9);
                }
            }

③:在JSP顯示頁(yè)數(shù)時(shí)酒请,獲取得到開(kāi)始頁(yè)和結(jié)束頁(yè)就行了


    <%--提供頁(yè)數(shù)的界面--%>
    <c:forEach var="pageNum" begin="${page.startPage}" end="${page.endPage}">
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${pageNum}">
                [${pageNum}]&nbsp;
        </a>
    </c:forEach>

  • 效果:
image

重構(gòu)優(yōu)化

分頁(yè)重構(gòu)

我們?cè)倩仡^看看BusinessService中獲取分頁(yè)數(shù)據(jù)的代碼:


    //既然Page對(duì)象代表是分頁(yè)數(shù)據(jù),那么返回Page對(duì)象即可鸣个!
    //web層應(yīng)該傳入想要看哪一頁(yè)數(shù)據(jù)的參數(shù)羞反!
    public Page getPageData(String currentPageCount) {

        Page page = new Page();

        //獲取數(shù)據(jù)庫(kù)中有多少條記錄,并封裝到Page對(duì)象中
        Long totalRecord = customerDao.getTotalRecord();
        page.setTotalRecord(totalRecord);

        //算出總頁(yè)數(shù)囤萤,并封裝到Page對(duì)象中
        int totalPagecount = (int) (totalRecord % page.getLinesize() == 0 ? totalRecord / page.getLinesize() : totalRecord / page.getLinesize() + 1);
        page.setTotalPageCount(totalPagecount);

        int start ;
        int end = page.getLinesize();

        //現(xiàn)在又分兩種情況了昼窗,如果傳遞進(jìn)來(lái)的參數(shù)是null的,那么說(shuō)明外界是第一次查詢的
        if (currentPageCount == null) {

            //第一次查詢涛舍,就應(yīng)該設(shè)置當(dāng)前頁(yè)數(shù)是第一頁(yè)
            page.setCurrentPageCount(1);

            page.setStartPage(1);
            page.setEndPage(10);

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);
        } else {

            //如果不是第一次澄惊,就把外界傳遞進(jìn)來(lái)的頁(yè)數(shù)封裝到Page對(duì)象中
            page.setCurrentPageCount(Long.parseLong(currentPageCount));

            start = (int) ((page.getCurrentPageCount() - 1) * page.getLinesize());

            if (page.getCurrentPageCount() <= 10) {
                page.setStartPage(1);
                page.setEndPage(10);
            } else {
                page.setStartPage((int) (page.getCurrentPageCount() - 4));
                page.setEndPage((int) (page.getCurrentPageCount() + 5));

                //如果因?yàn)榧訙p角標(biāo)越界了,那么就設(shè)置最前10頁(yè),或者最后10頁(yè)
                if (page.getStartPage() < 1) {
                    page.setStartPage(1);
                    page.setEndPage(10);
                }
                if (page.getEndPage() > page.getTotalPageCount()) {
                    page.setEndPage(page.getTotalPageCount());
                    page.setStartPage(page.getTotalPageCount() - 9);
                }
            }

            List<Customer> customers = customerDao.getPageData(start, end);

            page.setList(customers);

        }
        return page;

    }

太太太太太tm復(fù)雜缤削,太太太太tm長(zhǎng)了>焦!Mじ摇!图筹!我們BusinessService要做的僅僅是調(diào)用Dao層的功能帅刀,為web層提供數(shù)據(jù),但我們?cè)诜椒ㄖ惺褂么罅苛诉壿嬇袛嘣妒#疫@些邏輯判斷都是屬于Page類的扣溺!

明確一下:只有獲取數(shù)據(jù)庫(kù)總記錄數(shù)是在BusinessService中做的,其他的數(shù)據(jù)變量都是應(yīng)該在Page類中完成瓜晤!

在BusinessService獲取了總記錄數(shù)之后锥余,我們要對(duì)其他變量進(jìn)行初始化(根據(jù)總記錄數(shù),用戶想要看哪一頁(yè)的數(shù)據(jù))痢掠,算出其他的數(shù)據(jù)(JSP記錄開(kāi)始頁(yè)數(shù)驱犹、結(jié)束頁(yè)數(shù)、總頁(yè)數(shù)等等)足画,最好的辦法就是通過(guò)Page的構(gòu)造函數(shù)來(lái)實(shí)現(xiàn)初始化雄驹!

  • 改良后的BusinessService

    public Page getPageData2(String currentPageCount) {

   
    //獲取得到總記錄數(shù)
    Long totalPageCount = customerDao.getTotalRecord();

    if (currentPageCount == null) {

        //如果是第一次,那么就將用戶想看的頁(yè)數(shù)設(shè)置為1
        Page page = new Page(1, totalPageCount);

        List<Customer> customers = customerDao.getPageData(page.getStartIndex(), page.getLinesize());

        page.setList(customers);
        return page;

    } else {

        //如果不是第一次淹辞,就將獲取得到的頁(yè)數(shù)傳遞進(jìn)去
        Page page = new Page(Integer.parseInt(currentPageCount), totalPageCount);

        List<Customer> customers = customerDao.getPageData(page.getStartIndex(), page.getLinesize());

        page.setList(customers);
        return page;
    }
    
    }

  • 改良后的Page類(原來(lái)的Page類只有成員變量和setter医舆、getter方法)

    public Page(int currentPageCount, long totalRecord) {

        //將傳遞進(jìn)來(lái)的currentPageCount初始化
        this.currentPageCount = currentPageCount;

        //總頁(yè)數(shù)
        totalPageCount = (int) (totalRecord % linesize == 0 ? totalRecord / linesize : totalRecord / linesize + 1);

        //總記錄數(shù)
        this.totalRecord = totalRecord;

        //開(kāi)始取數(shù)據(jù)的位置
        startIndex = (currentPageCount - 1) * linesize;

        //如果當(dāng)前頁(yè)小于10,那么開(kāi)始頁(yè)為1象缀,結(jié)束頁(yè)為10就行了
        if (this.currentPageCount <= 10) {
            this.startPage = 1;
            this.endPage = 10;
        } else {
            startPage = this.currentPageCount - 4;
            endPage = this.currentPageCount + 5;

            //加減后頁(yè)數(shù)越界的情況
            if (startPage < 1) {
                this.startPage = 1;
                this.endPage = 10;
            }
            if (endPage > totalPageCount) {
                this.startPage = this.currentPageCount - 9;
                this.endPage = this.totalPageCount;
            }
        }

    }

分頁(yè)顯示頁(yè)面重構(gòu)

分頁(yè)的顯示頁(yè)面都是永恒不變的蔬将,我們可以把代碼重構(gòu)成一個(gè)jsp,需要用到分頁(yè)顯示頁(yè)面的地方央星,就包含進(jìn)去就行了霞怀!

  • page.jsp

    <%@ page contentType="text/html;charset=UTF-8" language="java" %>
    <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
    <%--顯示當(dāng)前頁(yè)數(shù)--%>
    當(dāng)前頁(yè)數(shù)是:[${page.currentPageCount}]&nbsp;&nbsp;&nbsp;

    <%--如果當(dāng)前的頁(yè)碼大于1,才顯示上一步--%>
    <c:if test="${page.currentPageCount>1}">

        <%--把傳遞過(guò)去的頁(yè)碼-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount-1}">
            上一步
        </a>
    </c:if>

    <%--提供頁(yè)數(shù)的界面--%>
    <c:forEach var="page" begin="${page.startPage}" end="${page.endPage}">
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page}">
            [${page}]&nbsp;
        </a>
    </c:forEach>

    <%--如果當(dāng)前的頁(yè)碼小于總頁(yè)數(shù)等曼,才顯示下一步--%>
    <c:if test="${page.currentPageCount<page.totalPageCount}">

        <%--把傳遞過(guò)去的頁(yè)碼-1就行了--%>
        <a href="${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}">
            下一步
        </a>&nbsp;&nbsp;
    </c:if>

    <input type="text" id="currentPageCount">
    <input type="button" value="跳轉(zhuǎn)" onclick="goPage()">

    總頁(yè)數(shù)是:${page.totalPageCount}&nbsp;&nbsp;

    總記錄數(shù)是:${page.totalRecord}

    <script type="text/javascript">

        /*既然寫(xiě)上了JavaScript代碼了里烦,就順便驗(yàn)證輸入框輸入的數(shù)據(jù)是否合法吧*/
        function goPage() {

            /*獲取輸入框控件*/
            var input = document.getElementById("currentPageCount");

            /*獲取輸入框的數(shù)據(jù)*/
            var value = input.value;

            if(value==null || value==""){
                alert("請(qǐng)輸入頁(yè)碼");
                return false;
            }

            if(!value.match("\\d+")){
                alert("請(qǐng)輸入數(shù)字");
                return false;
            }

            if(value<1 || value>${page.totalPageCount}){
                alert("請(qǐng)輸入合法數(shù)據(jù)");
                return false ;
            }

            window.location.href="${pageContext.request.contextPath}/LookCustomer?currentPageCount="+value;
        }

    </script>

用需要用到的地方,導(dǎo)入即可禁谦!


    <jsp:include page="page.jsp"></jsp:include>

為了做到更好的通用性胁黑,處理分頁(yè)數(shù)據(jù)的url應(yīng)該由Servlet傳進(jìn)去給Page類,讓Page類封裝起來(lái)州泊!要使用的時(shí)候丧蘸,再用Page取出來(lái)就行了。

下面寫(xiě)法已經(jīng)固定了,不夠靈活力喷!也就是說(shuō)刽漂,下面的url地址不應(yīng)該寫(xiě)死的


    ${pageContext.request.contextPath}/LookCustomer?currentPageCount=${page.currentPageCount+1}

我們可以這樣做:

  • 在Controller上獲取Servlet的名稱,在傳遞用戶想要看的頁(yè)數(shù)的同時(shí)弟孟,把Servlet的url也傳遞進(jìn)去

        String servletName = this.getServletName();

        //調(diào)用BusinessService的方法贝咙,獲取得到所有客戶信息
        BusinessService businessService = new BusinessService();

        //把Servlet的url也傳遞進(jìn)去
        Page page = businessService.getPageData2(currentPageCount, request.getContextPath() + "/" + servletName);

  • 在Page類上,多增加一個(gè)成員變量

    private String url;
    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }
  • 在BusinessService接受到web層傳遞進(jìn)來(lái)的url拂募,set到Page對(duì)象上就行了庭猩!

    page.setUrl(url);

我們?cè)趈sp頁(yè)面跳轉(zhuǎn)到處理分頁(yè)數(shù)據(jù)的Servlet上,就再不用寫(xiě)死了陈症。直接用Page對(duì)象中獲取出來(lái)就行了蔼水!


    <%--把傳遞過(guò)去的頁(yè)碼-1就行了--%>
    <a href="${page.url}?currentPageCount=${page.currentPageCount-1}">
        上一步
    </a>


開(kāi)發(fā)web的刪除和修改

在查詢jsp頁(yè)面上,增添刪除和修改的操作鏈接录肯!

[圖片上傳中...(image-a7a356-1519566284704-4)]

image

開(kāi)發(fā)處理刪除操作的Servlet

超鏈接綁定要?jiǎng)h除用戶的id趴腋,帶過(guò)去給Controller

        <a href="${pageContext.request.contextPath}/DeleteCustomer?id=${customer.id}">刪除</a>

controller的代碼也十分簡(jiǎn)單:


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

        //調(diào)用BusinessService層的功能,就可以完成刪除操作了
        BusinessService businessService = new BusinessService();

        businessService.deleteCustomer(id);

刪除客戶記錄也是一件非常重要的事情论咏,應(yīng)該提供JavaSrcript代碼詢問(wèn)是否要真的刪除

在超鏈接控件上綁定事件优炬!


       <a href="${pageContext.request.contextPath}/DeleteCustomer?id=${customer.id}" onclick=" return sureDelete()">刪除</a>

    function sureDelete() {
        var b = window.confirm("你確定要?jiǎng)h除嗎?");

        if(b) {
            return true;
        }else {
            return false;
        }
    }

測(cè)試:

image

修改操作

修改操作的流程是這樣的:點(diǎn)擊修改超鏈接潘靖,跳轉(zhuǎn)到該用戶的詳細(xì)信息頁(yè)面穿剖,在詳細(xì)信息頁(yè)面中修改數(shù)據(jù),再提交修改卦溢!【跳轉(zhuǎn)到用戶詳細(xì)信息頁(yè)面時(shí)糊余,用戶的id還在的,在提交數(shù)據(jù)的時(shí)候单寂,記得把id也給到服務(wù)器贬芥,【id是不包含在表單中的,要我們自己提交過(guò)去】宣决!】


   <a href="${pageContext.request.contextPath}/UpdateCustomerUI?=${customer.id}">修改</a>

開(kāi)發(fā)提供用戶詳細(xì)信息的Servlet


        String id = request.getParameter("id");
        BusinessService businessService = new BusinessService();

        //通過(guò)id獲取得到用戶的詳細(xì)信息
        Customer customer = businessService.findCustomer(id);

        request.setAttribute("customer", customer);
        //跳轉(zhuǎn)到顯示用戶詳細(xì)信息的jsp頁(yè)面上
        request.getRequestDispatcher("/WEB-INF/customerInformation").forward(request, response);

開(kāi)發(fā)顯示用戶信息的JSP【數(shù)據(jù)回顯】

想要日期能夠選擇蘸劈,記得導(dǎo)入JavaScript代碼,響應(yīng)事件尊沸!

注意:在顯示頁(yè)面上威沫,一定要把id傳遞過(guò)去給處理表單的Servlet吉挣,不然服務(wù)器是不知道你要修改哪一條數(shù)據(jù)的捅位!

<head>
    <title>用戶詳細(xì)信息</title>
    <script type="text/javascript" src="${pageContext.request.contextPath}/customer.js">

    </script>
</head>
<body onload="pageInit()">

<form action="${pageContext.request.contextPath}/updateCustomer?id=${customer.id}" method="post" onsubmit="makeForm()">
    <table border="1px">
        <tr>
            <td>用戶名:</td>
            <td><input type="text" name="name" value="${customer.name}"></td>
        </tr>

        <tr>
            <td>性別</td>
            <td><input type="radio" name="gender" value="male" ${customer.gender=='male'?'checked':''}>男
            <input type="radio" name="gender" value="female"${customer.gender=='female'?'checked':''}>女
            </td>
        </tr>
        <tr>
            <td>生日</td>
            <td>
                <select id="year">
                    <option value="${fn:split(customer.birthday,'-')[0]}">${fn:split(customer.birthday,'-')[0]}</option>
                </select>
                <select id="month">
                    <option value="${fn:split(customer.birthday,'-')[1]}">${fn:split(customer.birthday,'-')[1]}</option>
                </select>
                <select id="day">
                    <option value="${fn:split(customer.birthday,'-')[2]}">${fn:split(customer.birthday,'-')[2]}</option>
                </select>
            </td>
        </tr>
        <tr>
            <td>電話號(hào)碼:</td>
            <td><input type="text" name="cellphone" value="${customer.cellphone}"></td>
        </tr>
        <tr>
            <td>郵箱:</td>
            <td><input type="text" name="email"value="${customer.email}"></td>
        </tr>
        <tr>
            <td>愛(ài)好:</td>
            <td>
                <input type="checkbox" name="hobbies" value="唱歌"${fn:contains(customer.preference, '唱歌')==true?'checked':''}>唱歌

                <input type="checkbox" name="hobbies" value="跳舞"${fn:contains(customer.preference, '跳舞')==true?'checked':''}>跳舞
                <input type="checkbox" name="hobbies" value="打代碼"${fn:contains(customer.preference, '打代碼')==true?'checked':''}>打代碼
            </td>
        </tr>
        <tr>
            <td>客戶類型</td>
            <td>
                <input type="radio" name="type" value="VIP" ${customer.type=='VIP'?'checked':''}>VIP
                <input type="radio" name="type" value="普通客戶"${customer.type=='普通客戶'?'checked':''}>普通客戶
                <input type="radio" name="type" value="黑名單客戶"${customer.type=='黑名單客戶'?'checked':''}>黑名單客戶
            </td>
        </tr>
        <tr>
            <td>描述</td>
            <td>
                <textarea name="description" cols="30" rows="10">${customer.description}</textarea>
            </td>
        </tr>
        <tr>
            <td><input type="submit" value="確定修改"></td>
            <td><input type="reset" value="重置"></td>
        </tr>
    </table>
</form>

效果:

image

處理修改表單數(shù)據(jù)的Servlet


        //將數(shù)據(jù)封裝到Bean中
        Customer customer = WebUtils.request2Bean(request, Customer.class);

        //將id封裝到Customer對(duì)象中4痢E住!不要忘了id6钕妗G吹妗蜓耻!在表單中獲取到的數(shù)據(jù)是沒(méi)有id的!N砀ぁP羯浮!芹橡!記得6咎场!A炙怠粘驰!
        customer.setId(request.getParameter("id"));

        //調(diào)用Service層的方法,實(shí)現(xiàn)修改
        BusinessService businessService = new BusinessService();
        businessService.updateCustomer(customer);

        //修改成功就跳回查看客戶界面
        request.getRequestDispatcher("/LookCustomer").forward(request, response);
  • 效果:
image

總結(jié)

  1. 在dao層中述么,我們有添加客戶、通過(guò)id查找用戶愕掏、刪除用戶度秘、修改用戶信息的方法。
  2. 日期我們一般用下拉框來(lái)給用戶選取饵撑,要想下拉框的信息有足夠多的數(shù)據(jù)剑梳,我們需要用到JavaScript【DOM編程動(dòng)態(tài)增加和修改數(shù)據(jù)】
  3. javasrcipt文件不能放在WEB-INF目錄下面
  4. 日期的數(shù)據(jù)通過(guò)下拉框選取,年滑潘、月垢乙、日是分散的,我們需要把他們拼接语卤,于是我們也用JavaScript來(lái)拼接【減低服務(wù)器端的壓力】
  5. 開(kāi)發(fā)工具方法request2Bean追逮,主要用到了BeanUtils框架,這樣就不用在Servlet一個(gè)一個(gè)封裝了粹舵。
  6. 在JSP判斷集合是否有元素時(shí)钮孵,我們可以用EL表達(dá)式${empty(集合)}
  7. 如果記錄數(shù)有很多眼滤,我們應(yīng)該使用分頁(yè)技術(shù)巴席,一般地,我們使用Page類來(lái)封裝分頁(yè)的數(shù)據(jù)
  8. 要使用分頁(yè)技術(shù)诅需,就必須在數(shù)據(jù)庫(kù)用查詢總記錄數(shù)漾唉,通過(guò)總記錄數(shù),就可以算出總頁(yè)數(shù)了【每頁(yè)顯示多少條記錄由我們說(shuō)了算】
  9. 在dao層還要編寫(xiě)獲取具體的分頁(yè)數(shù)據(jù)堰塌,從哪里開(kāi)始赵刑,哪里結(jié)束,返回一個(gè)List集合蔫仙,再把List集合封裝到Page對(duì)象上
  10. 由于獲取分頁(yè)數(shù)據(jù)需要當(dāng)前的頁(yè)數(shù)是多少料睛,(所以在service中要判斷當(dāng)前頁(yè)數(shù)是否存在,如果不存在,那么就設(shè)置為1)【更新恤煞,我認(rèn)為在Controller判斷會(huì)好一點(diǎn)】
  11. 分頁(yè)中屎勘,我們還支持上一頁(yè)和下一頁(yè)的功能,如果頁(yè)數(shù)大于1居扒,才顯示上一頁(yè)概漱,如果頁(yè)數(shù)小于最大頁(yè)數(shù),才顯示下一頁(yè)喜喂。
  12. 給出下拉框進(jìn)行頁(yè)數(shù)跳轉(zhuǎn)瓤摧,使用JavaScript事件機(jī)制,獲取頁(yè)數(shù)玉吁,再提交給Servlet處理即可
  13. 我們還要控制頁(yè)數(shù)的顯示照弥,因?yàn)椴豢赡苡?00頁(yè),我們就顯示100頁(yè)进副,這樣是不可能的这揣。在Page類中維護(hù)兩個(gè)變量,startPage影斑,endPage给赞。我們規(guī)定每次只能顯示10頁(yè)數(shù)據(jù),如果第一次訪問(wèn)就顯示1-10頁(yè)矫户。如果當(dāng)前頁(yè)數(shù)大于10片迅,那么就顯示6-15頁(yè)。如果角標(biāo)越界了皆辽,那么就顯示前10頁(yè)或者后10頁(yè)
  14. 我們把顯示分頁(yè)的頁(yè)面封裝成單獨(dú)的jsp柑蛇,使用的Servlet連接也可以用url變量來(lái)維護(hù)。
  15. 前臺(tái)數(shù)據(jù)做拼接膳汪,最終都是把拼接好的數(shù)據(jù)用一個(gè)隱藏域封裝起來(lái)唯蝶,隨后讓form表單一起提交

如果文章有錯(cuò)的地方歡迎指正,大家互相交流遗嗽。習(xí)慣在微信看技術(shù)文章的同學(xué)粘我,想要獲取更多的Java資源的同學(xué),可以關(guān)注微信公眾號(hào):Java3y

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末痹换,一起剝皮案震驚了整個(gè)濱河市征字,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娇豫,老刑警劉巖匙姜,帶你破解...
    沈念sama閱讀 223,126評(píng)論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異冯痢,居然都是意外死亡氮昧,警方通過(guò)查閱死者的電腦和手機(jī)框杜,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評(píng)論 3 400
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)袖肥,“玉大人咪辱,你說(shuō)我怎么就攤上這事∽底椋” “怎么了油狂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 169,941評(píng)論 0 366
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)寸癌。 經(jīng)常有香客問(wèn)我专筷,道長(zhǎng),這世上最難降的妖魔是什么蒸苇? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 60,294評(píng)論 1 300
  • 正文 為了忘掉前任磷蛹,我火速辦了婚禮,結(jié)果婚禮上溪烤,老公的妹妹穿的比我還像新娘弦聂。我一直安慰自己,他們只是感情好氛什,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著匪凉,像睡著了一般枪眉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上再层,一...
    開(kāi)封第一講書(shū)人閱讀 52,874評(píng)論 1 314
  • 那天贸铜,我揣著相機(jī)與錄音,去河邊找鬼聂受。 笑死蒿秦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛋济。 我是一名探鬼主播棍鳖,決...
    沈念sama閱讀 41,285評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼碗旅!你這毒婦竟也來(lái)了渡处?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 40,249評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤祟辟,失蹤者是張志新(化名)和其女友劉穎医瘫,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體旧困,經(jīng)...
    沈念sama閱讀 46,760評(píng)論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡醇份,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評(píng)論 3 343
  • 正文 我和宋清朗相戀三年稼锅,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片僚纷。...
    茶點(diǎn)故事閱讀 40,973評(píng)論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡矩距,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出畔濒,到底是詐尸還是另有隱情剩晴,我是刑警寧澤,帶...
    沈念sama閱讀 36,631評(píng)論 5 351
  • 正文 年R本政府宣布侵状,位于F島的核電站赞弥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏趣兄。R本人自食惡果不足惜绽左,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望艇潭。 院中可真熱鬧拼窥,春花似錦、人聲如沸蹋凝。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,797評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)鳍寂。三九已至改含,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間迄汛,已是汗流浹背捍壤。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,926評(píng)論 1 275
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鞍爱,地道東北人鹃觉。 一個(gè)月前我還...
    沈念sama閱讀 49,431評(píng)論 3 379
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像睹逃,于是被迫代替她去往敵國(guó)和親盗扇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容