一個簡單的格式化信函產生器

來源:互聯網
上載者:User

        童鞋們都應該見過各種各樣的請柬咯, 請柬上面通常是一個模板,然後填上被邀請人及相關資訊,在 Word 裡面稱之為 “合併列印”特性。 今天,我們就來實現一個簡單的格式化信函產生器。 我們將要做的東西, 包括一個非常簡單的學生選課資料庫,以及簡單的模板, 利用資料庫中的記錄及模板產生格式化的通知資訊。 關於C語言的實現, 請參考 《編程珠璣I》(第二版) 的第三章第二節。

        別看這個東西簡單, 其中也蘊涵了不變和變化的部分。 不變是資訊模板內容, 變化部分是資料庫中的記錄資訊, 所要做的,就是將不變和變化隔離開來。 基本的設計思想如下:

        1.  一個非常簡單的學生選課資料庫, 包括學生資訊表 students , 課程資訊表 courses, 學生選課資訊表 stus_cours; 

        2.  一個JDBC 工具 + 生產力類 JDBCUtil , 主要是從資料庫中檢索記錄, 並將其轉換為相應的記錄對象 DBRecord; 

        3.  記錄對象 DBRecord: 包含一個 String[] 數組, 用來儲存每條記錄中的資料項目,一個 String 對應一條基本資料項目。

        4.  模板資訊介面: interface Template , 包含一個 getText() 的方法聲明;

        5.  兩個模板實現: 課程開設資訊 CourseInfoTemplate 及 學生選課資訊 CourseChosenTemplate

        6.  格式化信函產生器 FormattedLetter : 根據資料庫記錄及模板產生格式化通知

        因為這個東西並不複雜,  這裡就不講解太多了, 相信童鞋們看過代碼之後很快就會明白的。下面給出代碼實現:

        ### course.sql 

############################################### course.sql: 建立一個簡單的學生選課資料庫# NOTE: 必須儲存為 utf-8 格式(檔案 - 另存新檔), #       以保證在命令列下執行該檔案能夠順利插入中文############################################################################################# how to exec sql file  # mysql -u root -p < /your_path/course.sql# Enter password: [input your root password]   ############################################### 或者使用 root 登入 mysql, # 然後複製所有語句在 mysql 中執行。#################################################################################### mysql statement:######################################CREATE USER 'course6'@'localhost' IDENTIFIED BY  'course6';CREATE DATABASE course;grant all on course.* to 'course6'@'localhost';#####################################USE course;CREATE TABLE students (       id INT NOT NULL AUTO_INCREMENT,       stuName varchar(12) NOT NULL,        PRIMARY KEY(id)      ) ;      CREATE TABLE courses (      id INT NOT NULL AUTO_INCREMENT,       cName varchar(15) NOT NULL,       cTime int NOT NULL,       note varchar(30),      PRIMARY KEY(id)      ) ;        CREATE table stus_cours (       stu_id int NOT NULL,        cour_id int NOT NULL,       sch_term  varchar(5) NOT NULL,        PRIMARY KEY(stu_id, cour_id)      );  alter table stus_cours add constraint stuCons foreign key(stu_id) references students(id);alter table stus_cours add constraint courCons foreign key(cour_id) references courses(id); desc courses; desc students; desc stus_cours;  insert into students values(10001, '小華'); insert into students values(10002, '小明'); insert into courses values(1001, '高數', 54, ''); insert into courses values(1002, '大學英語', 81, ''); insert into stus_cours values(10001, 1001, '2nd'); insert into stus_cours values(10002, 1001, '2nd'); insert into stus_cours values(10001, 1002, '1st'); insert into stus_cours values(10002, 1002, '1st');  SELECT * from students; SELECT * from courses; SELECT * from stus_cours;    SELECT stuName , cName, cTime , sch_term    FROM students, courses, stus_cours   WHERE students.id = stus_cours.stu_id   AND courses.id = stus_cours.cour_id; 

  JDBCUtil.java

       

package javatech.JDBClearn;import java.sql.Connection;import java.sql.DriverManager;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;import com.mysql.jdbc.ResultSetMetaData;import com.mysql.jdbc.Statement;public class JDBCUtil {private static Connection conn;private static final String mysqlDriver = "com.mysql.jdbc.Driver";private static final String mysqlURL = "jdbc:mysql://localhost:3306/course";private static final String username = "course6";private static final String password = "course6";private JDBCUtil() { }public static Connection getConnection() throws SQLException, ClassNotFoundException {Class.forName(mysqlDriver);conn = DriverManager.getConnection(mysqlURL, username, password);return conn;}public static void printResult(ResultSet rs) throws SQLException{ResultSetMetaData rsmd = (ResultSetMetaData) rs.getMetaData();int colNum = rsmd.getColumnCount();while(rs.next()) {for (int i = 0; i < colNum; i++)                 System.out.printf(rs.getString(i+1) + " ");System.out.println();}}public static List<DBRecord> toRecords(ResultSet rs) throws SQLException {List<DBRecord> records = new ArrayList<DBRecord>();ResultSetMetaData rsmd = (ResultSetMetaData) rs.getMetaData();int colNum = rsmd.getColumnCount();while(rs.next()) {String[] datas = new String[colNum];for (int i = 0; i < colNum; i++)                 datas[i] = rs.getString(i+1);records.add(new DBRecord(datas));}rs.close();conn.close();return records;}public static ResultSet getResultSet(String sqlString) throws SQLException, ClassNotFoundException{Connection conn = getConnection();Statement stm = (Statement) conn.createStatement();ResultSet rs = stm.executeQuery(sqlString);return rs;}public static void main(String[] args) throws SQLException, ClassNotFoundException{String sqlString = "SELECT stuName, cName, cTime, sch_term " +                           "FROM students, courses, stus_cours " +                           "WHERE students.id = stu_id AND " +                           "      courses.id = cour_id; ";ResultSet rs = getResultSet(sqlString);printResult(rs);rs.close();conn.close();}}

        DBRecord.java

       

package javatech.JDBClearn;/** * DBRecord: 與資料庫中一條行記錄相對應的資料對象 * */public class DBRecord {// 將資料庫中檢索到的一條記錄轉化為字串並儲存private String[] datas;public DBRecord(String[] datas) {this.datas = datas;}// 返回資料庫中一條記錄的第 index 個資料項目public String getDataTerm(int index) {if (index < 0 || index > datas.length-1) {throw new ArrayIndexOutOfBoundsException("數組下標越界!");}return datas[index];}// 返回資料庫一條記錄所含的資料項目的數目public int dataTermNum() {return datas.length;}public String toString() {StringBuilder sb = new StringBuilder("[DBRecord]: ");for (String s: datas) {sb.append(s);sb.append(' ');}sb.append('\n');return sb.toString();}}

         FormattedLetter.java

         

package javatech.JDBClearn;import java.sql.ResultSet;import java.sql.SQLException;import java.util.ArrayList;import java.util.List;public class FormattedLetter {/** * 用資料庫中每條記錄的資料項目依序替換模板中的模板資料。 * @param record 資料庫中的一條記錄 * @param tpl 指定模板檔案介面 * @return 替換後的格式化信函 */public String formattedLetter(DBRecord record, Template tpl) {String text = tpl.getText();for (int i=0; i < record.dataTermNum(); i++)     text = text.replaceAll("\\$" + (i+1), record.getDataTerm(i));return text;}/** * 批量產生格式化信函 */public List<String> batFormattedLetter(List<DBRecord> records, Template tpl){List<String> letters = new ArrayList<String>();for (DBRecord r: records) {letters.add(formattedLetter(r, tpl));}return letters;}/** * printList: 列印列表內容 */public static <T> void printList(List<T> list){System.out.println("List: [");for (T t: list) {System.out.println(t);}System.out.println("]");}public static void test(String sqlStmt, Template tpl) throws SQLException, ClassNotFoundException{ResultSet rs = JDBCUtil.getResultSet(sqlStmt);List<DBRecord> records = JDBCUtil.toRecords(rs);List<String> letters = new FormattedLetter().batFormattedLetter(records , tpl);System.out.println("Formatted letters: ");printList(letters);}public static void main(String[] args) throws SQLException, ClassNotFoundException{String courseInfoSql = "SELECT cName, cTime FROM courses";test(courseInfoSql, new CourseInfoTemplate());String courseChosenString = "SELECT stuName, cName, cTime, sch_term " +           "FROM students, courses, stus_cours " +           "WHERE students.id = stu_id AND " +           "      courses.id = cour_id; ";test(courseChosenString, new CourseChosenTemplate());}}

            

           CourseInfoTemplate.java

package javatech.JDBClearn;public class CourseInfoTemplate implements Template {private String text = "同學們請注意: 本學期開設的課程有 $1, 共 $2 學時,請勿錯過!";public String getText(){return text;}}

         CourseChosenTemplate.java

         

package javatech.JDBClearn;public class CourseChosenTemplate implements Template {private String text =     "$1 ,  你好! 你所選修的課程是 $2, 共 $3 學時, 在 $4 上, 請勿錯過。 ";public String getText(){return text;}}

       Template.java

package javatech.JDBClearn;public interface Template {String getText();}

        末記: 可以改進的地方

          1. 使用 replaceAll 方法替換模板檔案中的多個模板資料效率可能會有些低下, 有待改進;

          2. 必鬚根據資料庫中檢索到的記錄的資料項目順序及模板中定義的模板項依序對應地替換,而不能無序的任意替換;

          3. 模板檔案及格式化信函產生器還可以做得更靈活一點, 比如,添加輸入輸出資料流, 使之模板檔案可以來自於各種輸入資料流而不是簡單的字串, 格式化資訊可以輸出到各種目標流中,而不僅僅是控制台。
 

        

 

  

  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.