jsp簡單留言板

這個範例有新增留言、查詢留言及留言分頁顯示等功能,後台的管理還沒有建置完成,留言者需要填入標題、顯示名稱、電話、信箱及留言內容,其中電話與電子信箱不顯示在留言列表中,電話及信箱可以為之後後台回覆寄信連絡使用。

當然這還有需多可以增加的功能,像是留言通知、隱私留言、留言刪除等,之後會再慢慢增加。

資料庫使用MySQL資料庫,使用JDBC來連接資料庫(DataSource方式),記錄檔則是使用log4j。

在新增留言部份,submit之前會先檢查是否有未填欄位,如果檢查通過則會自動建立IFrame來給這個form的target使用,新增完成後會自動回到留言列表的頁面。

留言版留言

查詢留言會對資料的標題及留言內容進行比對,有相同資料就會顯示查詢的結果,如果想進階做一個Search-Engine則可以參考建立自己的搜尋引擎

留言板查詢

最後也就是最重要的資料顯示功能,這裡包含了一個分頁模組,傳入的參數會有s,查詢條件,及p,目前頁數。

留言內容列表
原始碼下載
範例檢視

資料表

CREATE TABLE `threads` (
  `post_id` int(11) NOT NULL auto_increment,
  `post_name` varchar(150) NOT NULL,
  `post_title` varchar(300) default NULL,
  `post_mail` varchar(100) default NULL,
  `post_tel` varchar(100) default NULL,
  `post_desc` text,
  `post_reply` int(11) default NULL,
  `post_show` varchar(1) default '1',
  `post_state` varchar(1) default '1',
  `create_time` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `create_id` int(11) NOT NULL default '0',
  `optn_time` timestamp NULL default NULL,
  `optn_id` int(11) default NULL,
  PRIMARY KEY  (`post_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

設定檔

資料庫設定檔setting.properties

ServerName=127.0.0.1
Port=3306
DB_Name=test
DB_User=root
DB_PW=12345

log4j.properties

log4j.rootLogger=DEBUG,R, stdout
#log4j.logger.system = debug,R


log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p    %c- %m%n

log4j.appender.R=org.apache.log4j.DailyRollingFileAppender
log4j.appender.R.Append=true
log4j.appender.R.File.DatePattern='.'yyyy-MM-dd
log4j.appender.R.File=mail.log


#log4j.appender.R.MaxFileSize=100KB
#log4j.appender.R.MaxBackupIndex=5

log4j.appender.R.layout=org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern=%d %p    %c- %m%n

Java程式碼

資料庫連結與資料庫設定檔載入

package yslifes.db;

public class DataSource {
    private static com.mysql.jdbc.jdbc2.optional.MysqlDataSource ds = null;
    private static java.util.Properties p = null;

    public static javax.sql.DataSource getPool() {
        // com.mysql.jdbc.jdbc2.optional. ds = null;
        if (ds == null)
        // try
        {
            // ds = new oracle.jdbc.pool.OracleConnectionPoolDataSource ();
            if (p == null)
                loadSetting();
            ds = new com.mysql.jdbc.jdbc2.optional.MysqlDataSource();

            // 傳入參數
            // ds.setDriverType("thin");
            ds.setServerName(p.getProperty("ServerName"));
            ds.setPortNumber(Integer.parseInt(p.getProperty("Port")));
            ds.setDatabaseName(p.getProperty("DB_Name"));
            ds.setUser(p.getProperty("DB_User"));
            ds.setPassword(p.getProperty("DB_PW"));
            // ds.setEncoding("utf-8");
            ds.setCharacterEncoding("utf-8");
            // ds.set
        }
        // catch(java.sql.SQLException ex)
        // {
        // System.out.println(ex);
        // }

        return ds;
    }

    public static java.sql.Connection getConnection()
            throws java.sql.SQLException {
        return getPool().getConnection();
    }

    private static void loadSetting() {
        java.io.FileReader fr = null;
        java.io.BufferedReader in = null;
        p = new java.util.Properties();
        try {
            fr = new java.io.FileReader(yslifes.db.DataSource.class
                    .getResource("/setting.properties").getPath());
            in = new java.io.BufferedReader(fr);
            String str = null;

            while ((str = in.readLine()) != null) {
                String data[] = str.split("=");
                if (data.length > 0)
                    p.setProperty(data[0], data[1]);
            }
        } catch (java.io.IOException e) {
        }
    }

}


關閉資料庫物件

package yslifes.db;

public class Close {
    public static void Single(Object obj) {
        if (obj == null)
            return;
        try {
            if (obj instanceof java.sql.ResultSet)
                ((java.sql.ResultSet) obj).close();
            else if (obj instanceof java.sql.PreparedStatement)
                ((java.sql.PreparedStatement) obj).close();
            else if (obj instanceof java.sql.Statement)
                ((java.sql.Statement) obj).close();
            else if (obj instanceof java.sql.ResultSet)
                ((java.sql.ResultSet) obj).close();
        } catch (java.sql.SQLException e) {

        }
    }
}


共用參數,像是google-analytics就可以放在這裡

package yslifes.tools;

public class CommonDesc {
    private static String google_analytics = "<script type=\"text/javascript\">//<![CDATA[ \r\n"
            + "var _gaq = _gaq || []; \r\n"
            + "_gaq.push(['_setAccount','UA-0000000-0']); \r\n"
            + "_gaq.push(['_trackPageview']); \r\n"
            +

            "(function() { \r\n"
            +

            "    var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; \r\n"
            +

            "    ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; \r\n"
            +

            "    var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); \r\n"
            +

            "})(); \r\n"
            + "//]]></script>  \r\n"
            + "<script type=\"text/javascript\"> \r\n"
            + "window.google_analytics_uacct = \"UA-5842101-4\"; \r\n"
            + "</script>";

    public static String script() {
        return google_analytics;
    }
}


Date日期格式化

package yslifes.tools;

import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class DateTool {
    private static DateFormat dateFormat = new SimpleDateFormat(
            "yyyy/MM/dd kk:mm:ss");

    public static String DateTimeFormat(java.sql.Timestamp time) {

        return (dateFormat.format(time));
    }
}


字串如果是null變成空白nvl及移除html tag函數

package yslifes.tools;

public class StringTool {
    public static String nvl(String str, String d) {
        if (str == null)
            return d;
        else
            return str.trim();
    }

    public static String reFormat(String content) {
        content = content.replaceAll("(?is)\\s\\s", " ");
        content = content.replaceAll("(?is)</?br>", "\n");
        content = content.replaceAll("(?is)</?p>", "\n");
        content = content.replaceAll("(?is)&nbsp;", "");
        content = content.replaceAll("(?is)</?[a-z][a-z0-9]*[^<>]*>", "");
        content = content.replaceAll("<!–/?.*–>", "");
        content = content.replaceAll(" ", "");
        content = content.trim();
        return content;
    }

}


分頁模組

package yslifes.tools;

public class SubPages {
    private int each_disNums;// 每頁顯示的條目數

    private int nums;// 總條目數

    private int current_page;// 目前所在頁數

    private int sub_pages;// 每次顯示的頁數

    private int pageNums;// 總頁數 總數/每次顯示的頁數

    // private java.util.ArrayList<Integer> page_array;// 用來構造分頁的數組

    private String subPage_link;// 每個分頁的鏈接

    // private int subPage_type;// 顯示分頁的類型

    /*
     * 當subPage_type=1的時候為普通分頁模式 example: 共4523條記錄,每頁顯示10條,當前第1/453頁 [首頁] [上頁]
     * [下頁] [尾頁] 當subPage_type=2的時候為經典分頁樣式 example: 當前第1/453頁 [首頁] [上頁] 1 2 3 4
     * 5 6 7 8 9 10 [下頁] [尾頁]
     */

    public SubPages(int each_disNums, int nums, int current_page,
            int sub_pages, String subPage_link) {
        this.each_disNums = each_disNums;
        this.nums = nums;
        if (current_page < 1) {
            this.current_page = 1;
        } else {
            this.current_page = current_page;
        }
        this.sub_pages = sub_pages;
        this.pageNums = (int) java.lang.Math.ceil(nums / each_disNums)
                + ((nums % each_disNums == 0) ? 0 : 1);
        this.subPage_link = subPage_link;

    }

    /*
     * 用來給建立分頁的數組初始化的函數。1,2,3,4,5,6.....
     */
    public java.util.ArrayList<Integer> initArray() {
        java.util.ArrayList<Integer> page_array = new java.util.ArrayList<Integer>();
        for (int i = 0; i < this.sub_pages; i++) {
            page_array.add(i, i);
            ;
        }
        return page_array;
    }

    /*
     * construct_num_Page該函數使用來構造顯示的條目 即使:[1][2][3][4][5][6][7][8][9][10]
     */
    public java.util.ArrayList<Integer> construct_num_Page() {
        java.util.ArrayList<Integer> current_array = new java.util.ArrayList<Integer>();
        if (this.pageNums < this.sub_pages) {
            // current_array=array();
            for (int i = 0; i < this.pageNums; i++) {
                current_array.add(i, i + 1);
            }
        } else {
            current_array = this.initArray();
            if (this.current_page <= 3) {
                for (int i = 0; i < current_array.size(); i++) {
                    current_array.set(i, i + 1);
                }
            } else if (this.current_page <= this.pageNums
                    && this.current_page > this.pageNums - this.sub_pages + 1) {
                for (int i = 0; i < current_array.size(); i++) {
                    current_array.set(i, (this.pageNums) - (this.sub_pages) + 1
                            + i);
                }
            } else {
                for (int i = 0; i < current_array.size(); i++) {
                    current_array.set(i, this.current_page - 2 + i);
                }
            }
        }
        for (int i = 0; i < current_array.size(); i++)
            System.out.print(current_array.get(i) + " ");
        System.out.println();
        return current_array;
    }

    /*
     * 構造普通模式的分頁 共4523條記錄,每頁顯示10條,當前第1/453頁 [首頁] [上頁] [下頁] [尾頁]
     */
    public String subPageCss1() {
        String subPageCss1Str = "";
        subPageCss1Str += "共" + this.nums + "條記錄,";
        subPageCss1Str += "每頁顯示" + this.each_disNums + "條,";
        subPageCss1Str += "當前第" + this.current_page + "/" + this.pageNums
                + "頁 ";
        if (this.current_page > 1) {
            String firstPageUrl = this.subPage_link + "1";
            String prewPageUrl = this.subPage_link + (this.current_page - 1);
            subPageCss1Str += "[<a href='" + firstPageUrl + "'>首頁</a>] ";
            subPageCss1Str += "[<a href='" + prewPageUrl + "'>上一頁</a>] ";
        } else {
            subPageCss1Str += "[首頁] ";
            subPageCss1Str += "[上一頁] ";
        }

        if (this.current_page < this.pageNums) {
            String lastPageUrl = this.subPage_link + this.pageNums;
            String nextPageUrl = this.subPage_link + (this.current_page + 1);
            subPageCss1Str += " [<a href='" + nextPageUrl + "'>下一頁</a>] ";
            subPageCss1Str += "[<a href='" + lastPageUrl + "'>尾頁</a>] ";
        } else {
            subPageCss1Str += "[下一頁] ";
            subPageCss1Str += "[尾頁] ";
        }

        return subPageCss1Str;

    }

    /*
     * 構造經典模式的分頁 當前第1/453頁 [首頁] [上頁] 1 2 3 4 5 6 7 8 9 10 [下頁] [尾頁]
     */
    public String subPageCss2() {
        String subPageCss2Str = "";
        subPageCss2Str += "當前第" + current_page + "/" + pageNums + "頁 ";

        if (current_page > 1) {
            String firstPageUrl = subPage_link + "1";
            String prewPageUrl = subPage_link + (current_page - 1);
            subPageCss2Str += "[<a href='" + firstPageUrl + "'>首頁</a>] ";
            subPageCss2Str += "[<a href='" + prewPageUrl + "'>上一頁</a>] ";
        } else {
            subPageCss2Str += "[首頁] ";
            subPageCss2Str += "[上一頁] ";
        }

        java.util.ArrayList<Integer> a = construct_num_Page();
        int s;
        for (int i = 0; i < a.size(); i++) {
            s = a.get(i);
            if (s == current_page) {
                subPageCss2Str += "[<span style='color:red;font-weight:bold;'>"
                        + s + "</span>]";
            } else {
                String url = subPage_link + s;
                subPageCss2Str += "[<a href='" + url + "'>" + s + "</a>]";
            }
        }

        if (current_page < pageNums) {
            String lastPageUrl = subPage_link + pageNums;
            String nextPageUrl = subPage_link + (current_page + 1);
            subPageCss2Str += " [<a href='" + nextPageUrl + "'>下一頁</a>] ";
            subPageCss2Str += "[<a href='" + lastPageUrl + "'>尾頁</a>] ";
        } else {
            subPageCss2Str += "[下一頁] ";
            subPageCss2Str += "[尾頁] ";
        }
        return subPageCss2Str;
    }

}


11 thoughts to “jsp簡單留言板”

  1. 板大我試你的都跑不出來 以下問題
    postIt.jsp 有顯是送出後跳到postAction.jsp 這裡就沒動進囉 好像沒連到mysql

    都是copy

    以下是我設定mysql
    連線名稱:test
    localhost
    3306
    root
    123456

    建立board資廖庫

    建立標單threads 有結取sql那個

    不知到是那出錯
    mysql的是5.1板的jar檔都有放

    請板大次教

      1. @yku, tomcat都沒有問題但好像連不到mysql
        連機本的postAction.jsp 險是錯誤視窗都沒有動靜

        輸入後postAction.jsp 沒有任何東西

        沒輸入postAction.jsp 沒有任何東西

  2. 板大方便的話
    及時通加我(雖然很久沒用)
    4/24都可以
    我會先用好相關的東西
    等板大有空密我即可

    感謝板大

  3. 板大我測試可以連資料庫但postIt.jsp 33行有問題找不出來不資源屬性

    第二個問題是輸入中文後

    查詢會查不到變成亂碼
    TEXT況內變亂碼所以都查不到之前輸入的中文

    1. 第一點可以給我錯誤訊息嘛?
      第二點的部份
      你可以到tomcat設定檔apache-tomcat-6.0.29\conf\server.xml裡
      (如果是Eclipse請找到專案目錄名稱為Server的,打開結點,可以看到server.xml這個檔)

      然後在Connector這個xml結點裡加上一個attribute
      useBodyEncodingForURI=”true”  及
      URIEncoding=”UTF-8″

      應該就可以解決中文亂碼的問題了

yku 發表迴響取消回覆