【JavaWeb】客戶關係管理系統

来源:https://www.cnblogs.com/Java3y/archive/2018/02/25/8470712.html
-Advertisement-
Play Games

前言 為了鞏固開發的流程,我們再拿一個客戶關係管理系統來練手...! 成果圖 我們完成的就是下麵的項目! 搭建配置環境 配置Tomcat 導入開發包 建立開發用到的程式包 在資料庫創建相對應的表 開發實體 開發實體十分簡單,對照著資料庫的表就行了! 開發獲取資料庫連接池的Utils 導入配置文件 開 ...


前言

為了鞏固開發的流程,我們再拿一個客戶關係管理系統來練手...!

成果圖

我們完成的就是下麵的項目!


搭建配置環境

  • 配置Tomcat
  • 導入開發包
  • 建立開發用到的程式包

  • 在資料庫創建相對應的表

    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)
    
    );


開發實體

開發實體十分簡單,對照著資料庫的表就行了!


    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

開發獲取資料庫連接池的Utils

導入配置文件


    <?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>

開發提供數據連接池的工具類


    public class Utils2DB {
    
        private static ComboPooledDataSource comboPooledDataSource = null;
    
            static {
    
                //它會自動尋找配置文件,節點為mysql的資料庫(預設就是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("資料庫初始化失敗了!");
            }
        }
    }

開發UUID工具類


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

開發DAO

DAO應該提供增加客戶和查詢用戶的功能

增加用戶



    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 (?, ?, ?, ?, ?, ?, ?, ?,?)";


        //得到用戶傳遞進來的數據
        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();

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

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

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

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

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

測試增加用戶

寫完一個功能,不要急著去寫其他的功能,先測試一下!


    @Test
    public void add() {

        //為了測試的方便,直接使用構造函數了!
        Customer customer = new Customer("1", "zhongfucheng", "男", new Date(), "1234", "[email protected]", "打代碼", "高貴的用戶", "我是個好人");



        CustomerDao customerDao = new CustomerDao();
        customerDao.addCustomer(customer);
        
    }
  • 好的,沒有報錯!再看看資料庫-----------只要是中文的數據,都亂碼了!


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


查詢用戶

將所有的客戶查詢出來就行了!



    //得到所有的用戶
    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));

            //如果集合大於個數大於0,就返回集合,不大於0,就返回null
            return customers.size() > 0 ? customers : null;
            
        } catch (SQLException e) {
            e.printStackTrace();
            throw new DaoException("獲取所有的用戶出錯了!");
        }
        
    }

測試查詢用戶


    @Test
    public void find() {

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

        for (Customer customer : customers) {

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


修改用戶信息

修改用戶信息首先要知道用戶的信息,在web端,只有id能唯一標識用戶,我們需要通過id,獲取用戶全部信息(也就是Customer對象)


    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("查找用戶失敗了");
        }

    }

修改用戶都是外邊傳遞個對象進來,Dao層取出對象的數據,從而對資料庫的數據進行修改!



    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("更新失敗");
        }
    }

測試修改用戶


    @Test
    public void update() {

        CustomerDao customerDao = new CustomerDao();

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

        //修改用戶信息
        customer.setName("看完博客要點贊");
        customerDao.update(customer);
    }
  • 原來該用戶的名字是d

  • 測試完之後:


刪除用戶

  • 通過外界傳遞進來的id,就可以刪除資料庫表中的記錄了

    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("刪除用戶失敗了");
        }
    }

測試刪除用戶


    @Test
    public void delete() {

        CustomerDao customerDao = new CustomerDao();

        //我們已經知道了某id,通過id刪除資料庫中的記錄
        String id = "043f7cce-c6f1-4155-b688-ba386cae1636";

        customerDao.delete(id);
    }

資料庫已經查詢不到id為043f7cce-c6f1-4155-b688-ba386cae1636的記錄了!

開發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);
        }
    }

開發web 的增加和查詢

提供UI,增加客戶的Servlet


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

開發顯示添加客戶頁面


<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>電話號碼:</td>
            <td><input type="text" name="cellphone"></td>
        </tr>
        <tr>
            <td>郵箱:</td>
            <td><input type="text" name="email"></td>
        </tr>
        <tr>
            <td>愛好:</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>
  • 效果是這樣子的

我們發現,在日期的下拉框中,只有一個數據(因為我們在value中只寫了一個數據)

要想在下拉框中可以選擇很多的數據,那麼value的值就不能單單隻有一個。當然了,也不可能在JSP頁面中寫下麵的代碼


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

我們用javaScript生成下拉框的數據就行了!!

  • 獲取年份!

    function makeYear() {
    
        //得到下拉框的控制項
        var year = document.getElementById("year");
    
        //要想下拉框有更多的數據,就需要有更多的option控制項
        //js獲取得到年份是getFullYear(),單單的getYear()只是獲取兩位數
        for (var i=1901; i<= new Date().getFullYear(); i++) {
    
    
            //生成option控制項
            var option = document.createElement("option");
    
            //option控制項的值和文本內容為迴圈生成的年分!
            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頁面中導入javascript文件

  • 註意:javasrcipt文件不能放在WEB-INF下麵!!!!否則是獲取不到的!!!


    <script type="text/javascript" src="${pageContext.request.contextPath}/customer.js" ></script>
  • 這三個函數都是在頁面載入時就應該被初始化了,所以在body上綁定onload時間即可!!

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


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


JavaScript拼湊數據

表單的數據非常多,毫無疑問,我們會使用BeanUtils來將數據封裝到Bean對象中!

對於表單的數據,還是有些雜亂的。表單中日期的年月日是分開的,我們要麼在客戶端將年月日的數據拼湊起來,要麼在伺服器端將年月日拼湊起來!同理,客戶的喜好可能不單單有一個,但在Customer對象中,喜好單單用一個String類型來表示的。我們也要把客戶的喜好拼湊起來。

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


    function makeBirthday() {
    
        //獲取下拉框的數據,把數據拼湊成日期字元串
        var year = document.getElementById("year");
        var month = document.getElementById("month");
        var day = document.getElementById("day");
        var birthday = year + "-" + month + "-" + day;
    
        //想要將拼湊完的字元串提交給伺服器,用隱藏域就行了
        var input = document.createElement("input");
        input.type = "hidden";
        input.value = birthday;
        input.name = "birthday";
    
        //將隱藏域綁定在form下【為了方便,在form中設置id,id名字為form】
        document.getElementById("form").appendChild(input);
    
    }
    
    function makePreference() {
    
        //獲取喜好的控制項
        var hobbies = document.getElementsByName("hobbies");
    
        //定義變數,記住用戶選中的選項
        var preference = "";
    
        //遍歷喜好的控制項,看用戶選上了什麼!
        for (var i = 0; i < hobbies.length; i++) {
    
            if (hobbies[i].checked == true) {
                preference += hobbies[i].value + ",";
            }
        }
    
        //剛纔拼湊的時候,最後一個逗號是多餘的,我們要把它去掉
        preference = preference.substr(0, preference.length - 1);
    
        //也是用隱藏域將數據帶過去給伺服器
        var input = document.createElement("input");
        input.type = "hidden";
        input.value = preference;
        input.name = "preference";
        
        //將隱藏域綁定到form表單上
        document.getElementById("form").appendChild(input);
        
    }
  • 當表單提交的時候,觸發上面兩個函數就行了!所以在form表單上綁定onsumit事件!

    function makeForm() {
        
        makeBirthday();
        makePreference();
        return true;
        
    }

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

開發處理表單數據的Servlet

  • 將表單的數據封裝到Bean對象中,要開發工具類

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

        try {
            
            //獲取Bean的對象
            T bean = aClass.newInstance();
            
            //獲取表單中所有的名字
            Enumeration enumeration = httpServletRequest.getParameterNames();

            //遍歷表單提交過來的名字
            while (enumeration.hasMoreElements()) {

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

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

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

              
            }
              return bean;
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("封裝數據到Bean中,失敗了!");
        }
        
    }
  • 處理表單數據的Servlet代碼:

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


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

            //如果執行到這裡,說明成功了,如果被catch了,說明失敗了。
            request.setAttribute("message", "添加成功!");

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


提供查詢客戶界面的Servlet


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

開發顯示客戶信息的頁面


    <c:if test="${empty(list)}">
        對不起,還沒有任何客戶的信息!
    </c:if>
    
    <c:if test="${!empty(list)}">
        <table border="1px">
            <tr>
                <td>用戶名:</td>
                <td>密碼:</td>
                <td>性別:</td>
                <td>生日:</td>
                <td>電話號碼:</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>
  • 效果:


將功能拼接在首頁上

採用分貞技術,讓界面更加好看!

index頁面:



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

head頁面:


    <body style="text-align: center;">
    
    <h1>客戶管理系統!</h1>
    
    <a href="${pageContext.request.contextPath}/AddCustomer" target="body">增添客戶</a>
    <a href="${pageContext.request.contextPath}/LookCustomer" target="body">查看客戶</a>
    </body>

body頁面:



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

效果圖


改善顯示頁面

現在問題來了,如果我們客戶信息有非常非常地多,我們不可能把客戶信息全部都擠在同一個頁面上,如果我們這樣做的話,網頁的長度就會非常的長!

於是乎,我們就需要用到了分頁的技術,對於分頁技術基礎的講解,在我另一篇博文中有介紹: https://zhongfucheng.bitcron.com/post/jdbc/jdbcdi-si-pian-shu-ju-ku-lian-jie-chi-dbutilskuang-jia-fen-ye

看完上篇博文,我們知道,首先要做的就是:明確分頁技術中需要用到的4個變數的值!

查詢總記錄數

查詢總記錄數也就是查詢資料庫表的記錄有多少條,這是關於對資料庫數據的操作,所以肯定是在dao層做!


    public Long getTotalRecord() {

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

        String sql = "SELECT * FROM customer";
        
        try {
            //獲取查詢的結果
            Long l = (Long) queryRunner.query(sql, new ScalarHandler());
            return l;
           
        } catch (SQLException e) {
            e.printStackTrace();
            throw new RuntimeException("查詢總記錄數失敗了!");
        }
        
    }

查詢分頁的數據

獲取分頁的數據也是查詢資料庫的記錄,這也是關於對資料庫的操作,所以也是在Dao層做的!



    /*查詢分頁數據*/
    //獲取分頁的數據是需要start和end兩個變數的【從哪條開始取,取到哪一條】
    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("獲取分頁數據失敗了!");
        }
    }

分析

現在我們已經可以知道總記錄數了,對於其他3個變數(每頁顯示記錄數【由程式員來指定】,當前是多少頁【由用戶來指定】,總頁數【由總記錄數和每頁顯示記錄數來算數來的】)

現在要分析的是,這些變數應該放在哪裡呢???全部放在Dao層??全部放在Dao層是可以實現功能的,但是,這樣MVC結構就被破壞掉了(Dao層只用來對數據進行CRUD操作,4個變數存在Dao層,是不合理的)

最好的做法是這樣的:創建一個實體Page,將分頁用到的信息全部封裝在Page中實現!Page就代表著分頁的數據這樣就非常符合面向對象的思想了!

將數據封裝到Page中併在頁面上顯示分頁的數據

①:創建Page類



    //保存著分頁的數據
    private List<Customer> list;

    //總記錄數
    private long totalRecord;

    //每頁顯示記錄數,這裡我規定每頁顯示3條
    private int linesize = 3;

    //總頁數
    private int totalPageCount;

    //當前顯示的頁數
    private long currentPageCount;

    //...各種的setter、getter

②:BusinessService應該提供獲取分頁數據的服務


    //既然Page對象代表是分頁數據,那麼返回Page對象即可!
    //web層應該傳入想要看哪一頁數據的參數!
    public Page getPageData(String currentPageCount) {

        Page page = new Page();

        //獲取資料庫中有多少條記錄,並封裝到Page對象中
        Long totalRecord = customerDao.getTotalRecord();
        page.setTotalRecord(totalRecord);

        //算出總頁數,並封裝到Page對象中
        int totalPagecount = (int) (totalRecord % page.getLinesize() == 0 ? totalRecord / page.getLinesize() : totalRecord / page.getLinesize() + 1);
        page.setTotalPageCount(totalPagecount);

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

        //現在又分兩種情況了,如果傳遞進來的參數是null的,那麼說明外界是第一次查詢的
        if (currentPageCount == null) {

            //第一次查詢,就應該設置當前頁數是第一頁
            page.setCurrentPageCount(1);

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

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

            page.setList(customers);
        } else {

            //如果不是第一次,就把外界傳遞進來的頁數封裝到Page對象中
            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層調用BusinessService層的功能,獲取得到Page對象


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

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

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

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

④:在JSP頁面中,使用EL表達式獲取到Page對象,從而輸出數據


        <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>${cust

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 定義: 本質是函數(裝飾其他函數),是為其他函數添加附加功能 本質是函數(裝飾其他函數),是為其他函數添加附加功能 原則: 不能修改被裝飾函數的源代碼 不能修改被裝飾函數的調用方式 實現裝飾器知識儲備: 函數及“變數” 高階函數 嵌套函數 裝飾器 = 高階函數 + 嵌套函數 實際使用方式: 1 #裝 ...
  • 目 錄 python高級(一)—— python數據模型(特殊方法) python高級(二)—— python內置序列類型 python高級(三)—— 字典和集合(泛映射類型) ...
  • 在網路通信中,Socket通信的雙方分為服務端與客戶端,在Java NIO 的實現中採用Socket/ServerSocket, SocketChannel/ServerSocketChannel分別表示客戶端與服務端對象及程式與所操作的Socket間的連接通道。 在Mina框架中採用IoAccep ...
  • 1、面向對象編程(OOP)有哪些優點? 代碼開發模塊化,更易維護和修改。 代碼復用。 增強代碼的可靠性和靈活性。 增加代碼的可理解性。 2、面向對象編程有哪些特性? 封裝、繼承、多態、抽象 封裝 封裝給對象提供了隱藏內部特性和行為的能力。對象提供一些能被其他對象訪問的方法來改變它內部的數據。在Jav ...
  • sort函數無法對map進行排序,網上的方法一般是通過將map轉為vector後,再來使用sort進行排序。 如下, 比較函數 主函數 ...
  • SG函數部分內容大多借(chao)鑒(xi)自 "zyf學長" 也有一些自己獨到的理解 Hackenbush和納什均衡直接棄掉了 不平等博弈有空再看 題目還有很多沒切完 不過確實是沒時間了,畢竟博弈只是一小塊內容。 經典博弈 "博弈論入門之巴什博奕" "博弈論入門之nim游戲" "博弈論入門之威佐夫 ...
  • 1.線程進程進程:程式並不能單獨運行,只有將程式裝載到記憶體中,系統為它分配資源才能運行,而這種執行的程式就稱之為進程,不具備執行感念,只是程式各種資源集合 線程:線程是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中 ...
  • 實際設置:系統變數新建: PATH新加: 查看是否安裝成功: ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...