1. 程式人生 > >Java開發專案2_個人記賬軟體

Java開發專案2_個人記賬軟體

帥帥個人賬務管理專案說明

專案功能

 檢視賬務
 多條件組合檢視賬務
 增加賬務
 編輯賬務
 刪除賬務
 匯出賬務

表結構

CREATE TABLE personal_zhangwu (
  zwid INT PRIMARY KEY AUTO_INCREMENT,
  flname VARCHAR(200),
  money DOUBLE,
  zhangHu VARCHAR(100),
  createtime DATE,
  description VARCHAR(1000) 
);




INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (1,'支出-餐費',247,'中國銀行','2017-03-02','家庭聚餐');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (2,'收入-工資',12345,'現金','2017-03-15','發工資');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (3,'支出-服裝',1998,'現金','2017-04-02','買衣服');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (4,'支出-餐費',325,'現金','2017-06-18','朋友聚餐');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (5,'收入-股票',8000,'建設銀行','2017-10-28','股票賺錢');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (6,'收入-股票',5000,'建設銀行','2017-10-28','股票賺錢');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (7,'收入-工資',5000,'中國銀行','2017-10-28','發工資');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (8,'支出-禮金',5000,'現金','2017-10-28','朋友結婚');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (9,'支出-其他',1560,'現金','2017-10-29','丟錢了');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (10,'支出-交通',2300,'中國銀行','2017-10-29','油價上升');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (11,'支出-餐費',1000,'建設銀行','2017-10-29','吃飯');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (12,'收入-工資',1000,'現金','2017-10-30','發工資');
INSERT  INTO personal_zhangwu(zwid,flname,money,zhangHu,createtime,description) VALUES (13,'支出-交通',2000,'現金','2017-10-30','外出旅遊機票');

功能展示
主選單

檢視賬務
查詢所有

帶分頁顯示,預設每頁顯示10條記錄。
只可往下一頁翻,不可上翻,提示使用者,按空格鍵,顯示下一頁。
當檢視到最後一頁後,顯示統計資訊(見後面說明)。
當檢視到最後一頁後,顯示功能選單選項。

統計資訊包括:總收入,總支出,總收入-總支出,每種支出的總金額,每種收入的總支出(收入和支出按金額從大到小排序)。
統計資訊的計算要使用到group by 。
統計資訊顯示樣例:

總支出: 8800.0, 總收入: 6000.0,淨收入:-2800.0
收入統計:
收入-工資 5000.0
收入-股票 1000.0
支出統計:
支出-禮金 3800.0
支出-餐費 3000.0
支出-交通 1000.0
支出-其他 1000.0

條件查詢
帶分頁顯示。
只可往下一頁翻,不可上翻,提示使用者,按空格鍵,顯示下一頁。
當檢視到最後一頁後,顯示統計資訊。
當檢視到最後一頁後,顯示功能選單選項。

修改賬務

增加賬務

刪除賬務

匯出賬務記錄
在專案中,嵌入一個TCP server,用於接受客戶端的匯出請求。
再編寫一個單獨的TCP客戶端程式,執行此程式,可以向TCP Server發出匯出請求。
TCP SERVER收到客戶端請求後,從資料庫中讀取所有賬務記錄,按照賬務時間後先順序排序,然後把這些記錄返回給客戶端。
客戶端接收到伺服器端的資料後,把資料寫入本地檔案。
檔案中的格式與內容與“檢視賬務”介面上顯示的格式和內容一樣。
伺服器端要記錄匯出日誌到檔案,日誌檔名為export.log,日誌檔案格式樣例:
匯出總次數: 88,成功次數:77
20181017-10:33:22 192.168.10.66 匯出成功
20181017-10:36:33 127.0.0.1 匯出失敗,非法客戶端
20181022-09:10:12 192.168.10.77 匯出成功

記錄日誌檔案是,要避免多個客戶端同時匯出是日誌記錄的併發問題。

伺服器端監聽埠從配置檔案server.ini讀取,配置檔案中還包括客戶端白名單,只有白名單中的客戶端才能匯出。
合法的和非法的客戶端連線時,伺服器端要返回相應的資訊給客戶端,客戶端由此資訊來判斷是否可以匯出。
server.ini格式如下:
port=8888
ips=192.168.10.66,127.0.0.1,192.168.10.77

專案環境搭建
專案技術選型和jar包介紹
每個專案都要使用一些已經成熟的技術,它們通常是由一些專業組織或團隊所提供的開源免費技術。
在今後的學習過程中,我們會逐漸對這些專業組織有所瞭解。本專案中使用的技術如下:
 c3p0-0.9.1.2.jar::資料庫連線池c3p0
 commons-dbutils-1.4.jar:封裝並簡化了JDBC;
 commons-logging-1.1.3.jar:c3p0依賴的包;
 mchange-commons-java-0.2.3.4.jar:c3p0依賴的包;
 mysql-connector-java-5.1.28-bin.jar:MySQL的JDBC驅動包,用JDBC連線MySQL資料庫必須使用該JAR包。

專案分層開發
分層原理
 如果程式規模小,可以一個人全部完成,但當程式規模很大時,一個人難以完成,這時,要多人合作完成程式開發。
多人合作方式將會碰到工作任務分配問題,這時我們會想,每個人負責完成專案的一塊內容就可以了。那麼,這一塊塊內容的劃分,就需要我們採用分層(分包)的方式完成了。
以“使用者註冊功能”為例,來講解下,專案中常見的分層(分包)。
在這裡插入圖片描述

常用的分層層次包括:

 view層: 檢視層,即專案中的介面
 controller層: 控制層, 獲取介面上的資料,為介面設定資料; 將要實現的功能交給業務層處理
 service層: 業務層, 功能的實現, 與controller控制層和資料訪問層DAO互動, 將對資料庫的操作交給DAO資料訪問層來處理
 dao層: 資料訪問層, 用來操作資料庫表的資料
 db資料庫: 這裡指MySQL
 domain 實體包: 存放JavaBean
 tools工具包:存放專案中使用到的工具類
 test 測試包: 存放專案功能測試的程式碼

工程建立及包管理

  1. 使用Eclipse建立Java工程,命名為zwgl
  2. 建立工程包
     cn.njit.gjp.app: 存放main方法類;
     cn.njit.gjp.domain: 存放JavaBean;
     cn.njit.gjp.view: 存放介面,及表現層類;
     cn.njit.gjp.service: 存放業務層類;
     cn.njit.gjp.dao: 存放資料訪問層類;
     cn.njit.gjp.tools:存放工具類
  3. 建立lib資料夾,用來儲存使用的jar包

各個包結構

  1. 在app包中,建立類MainApp.java,編寫main主方法,用來完成本專案的啟動。
  2. 在domain包中,建立類ZhangWu.java,它是用來封裝賬務資訊的JavaBean。
  3. 在dao包中,建立類ZhangWuDao.java,給ZhangWuDao類新增一個成員變數QueryRunner物件,因為我們使用dbutils來操作資料庫。
  4. 在service包中,建立類ZhangWuService.java,給ZhangWuService類新增一個型別為ZhangWuDao的成員變數,因為service依賴dao。
  5. 在view包中,建立類MainView.java,給MainView類新增一個型別為ZhangWuService的成員變數,因為本專案中view依賴service。

開發步驟:

  1. 首先先在工程下建立lib包,並且把5個驅動包匯入工程;
    在這裡插入圖片描述

 c3p0-0.9.1.2.jar::資料庫連線池c3p0
 commons-dbutils-1.4.jar:封裝並簡化了JDBC;
 commons-logging-1.1.3.jar:c3p0依賴的包;
 mchange-commons-java-0.2.3.4.jar:c3p0依賴的包;
 mysql-connector-java-5.1.28-bin.jar:MySQL的JDBC驅動包,用JDBC連線MySQL資料庫必須使用該JAR包。

  1. 然後開始構建專案框架,這個專案採用標準的MVC開發,一共8個包,分別存放了:
    在這裡插入圖片描述
    主函式
    控制層
    實現層
    實體類
    tcp網路服務
    服務層
    工具類
    表示層
  2. 接著進行使用連線池的準備:配置xml以及編寫JDBCUtils
<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<default-config>
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/njit?useUnicode=true&amp;characterEncoding=utf8
		</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">root</property>
		<property name="password">admin</property>
		
		<property name="checkoutTimeout">30000</property>
		<property name="idleConnectionTestPeriod">30</property>
		<property name="initialPoolSize">10</property>
		<property name="maxIdleTime">30</property>
		<property name="maxPoolSize">100</property>
		<property name="minPoolSize">10</property>
		<property name="maxStatements">200</property>
	</default-config>
</c3p0-config>

package cn.njit.gjp.tools;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

public class JDBCUtils {
	static private DataSource ds=new ComboPooledDataSource();
	
	public static DataSource getDataSource() {
		return ds;
	}
	
	static public Connection getConnection() {

		 try {
			return ds.getConnection();
		} catch (SQLException e) {
			
			e.printStackTrace();
		}
		return null;
		
	}
}
  1. mainview.java

     package cn.njit.gjp.view;
     import java.text.ParseException;
     import java.text.SimpleDateFormat;
     import java.util.Date;
     import java.util.Scanner;
     
     import cn.njit.gjp.controller.ZhangWuController;
     import cn.njit.gjp.entity.PageBean;
     import cn.njit.gjp.entity.ZhangWu;
     import cn.njit.gjp.ser.ChatServer;
     import cn.njit.gjp.ser.Server;
     import cn.njit.gjp.tools.DataUtils;
     import cn.njit.gjp.tools.DateUtils;
     /***
      * 介面顯示類
      * @author Liu
      *
      */
     public class MainView  implements Runnable{
    
     private ZhangWuController controller = new ZhangWuController();
    
     public void run() {
     	/*Server server=new Server();
     	Thread t=new Thread(server, "服務端");
     	t.start();*/
     	
     	Scanner sc = new Scanner(System.in);
     	while (true) {
     		System.out.println("---------------帥帥個人記賬軟體---------------");
     		System.out.println("1.增加賬務 2.修改賬務 3.刪除賬務 4.檢視賬務 5.登出系統");
     		System.out.println("請選擇要操作的功能序號[1-5]:");
     		// 接收使用者的選單選擇
     		String choose = sc.next();
     		int mm = 0;
     		try {
     			mm = Integer.parseInt(choose);
     		} catch (NumberFormatException e) {
     			System.out.println("請輸入1-5!");
     			continue;
     		}
    
     		switch (mm) {
     		case 1:
     			// 選擇新增賬務,呼叫新增賬務的方法
     			addZhangWu();
     			break;
     		case 2:
     			// 選擇的編輯賬務,呼叫編輯賬務方法
     			editZhangWu();
     			break;
     		case 3:
     			// 選擇的刪除賬務,呼叫刪除賬務方法
     			deleteZhangWu();
     			break;
     		case 4:
     			// 選擇的是查詢賬務,呼叫查詢方法
     			selectZhangWu();
     			break;
     		case 5:
     			System.exit(0);
     			break;
     		default:
     			System.out.println("請輸入1—5!");
     			break;
     		}
    
     	}
     }
     /***
      * 二級查詢介面
      */
     public void selectZhangWu() {
     	// 查詢2級介面
     	System.out.println("1.查詢所有 2.條件查詢3.返回上一級");
     	Scanner sc = new Scanner(System.in);
     	while (true) {
     		String choose = sc.next();
     		int mm = 0;
     		try {
     			mm = Integer.parseInt(choose);
     		} catch (NumberFormatException e) {
     			System.out.println("請輸入1、2或者3!");
     			continue;
     		}
     		switch (mm) {
     		case 1:
     			selectAll();
     			break;
     		case 2:
     			conditionSelectZhangwu();
     			break;
     		case 3:
     			run();
     			break;
     		default:
     			System.out.println("請輸入1、2或者3!!");
     			break;
     		}
     	}
     }
     public void conditionSelectZhangwu() {
     	// 條件查詢
     	System.out.println("選擇的條件查詢,請輸入日期格式:XXXX-XX-XX");
     	Scanner sc = new Scanner(System.in);
     	System.out.println("請輸入開始日期:");
     	String begin = sc.next();
     	while(!DataUtils.verifyDate(begin)) {
     		System.out.println("請重新輸入開始日期!");
     		begin = sc.next();
     	}
     	
     	
     	System.out.println("請輸入截至日期:");
     	String end = sc.next();
     	while(!DataUtils.verifyDate(end)) {
     		System.out.println("請重新輸入截至日期!");
     		end = sc.next();
     	}
     	
     	if(DateUtils.Dateyyyy_MM_dd_time(end).before((DateUtils.Dateyyyy_MM_dd_time(begin)))) {
     		System.out.println("日期先後錯誤!");
     		System.out.println("請輸入開始日期:");
     		begin = sc.next();
     		while(!DataUtils.verifyDate(begin)) {
     			System.out.println("請重新輸入開始日期!");
     			begin = sc.next();
     		}
     		System.out.println("請輸入截至日期:");
     		end = sc.next();
     		while(!DataUtils.verifyDate(end)) {
     			System.out.println("請重新輸入截至日期!");
     			end = sc.next();
     		}
     	}
     	PageBean<ZhangWu> page = new PageBean<ZhangWu>();
     	page.setPageNumber(1);
     	page.setPageSize(4);
     	page = controller.conditionSelectZhangwu(begin,end,page);
     	
    
     	System.out.println("輸入空格翻頁");
     	String m = sc.nextLine();
     	int count=1;
     	while (true) {
     		if (m.equals(" ")) {
     			if (count >= page.getPageCount()) {
     				controller.getTotal();
     				System.out.println("輸入3返回上一級!");
     				break;
     			} else {
     				count++;
     				System.out.println("翻頁");
     				page.setPageNumber(count);
     			}
     		} else {
     			System.out.println("");
     		}
    
     		page = controller.conditionSelectZhangwu(begin,end,page);
     		System.out.println("ID\t類別\t賬戶\t金額\t時間\t\t說明");
     		for (ZhangWu z : page.getData()) {
     			System.out.println(z.toString());
     		}
     		System.out.println("第" + page.getPageNumber() + "頁;共" + page.getPageCount() + "頁。");
     		System.out.println("------------------");
    
     		m = sc.nextLine();
     	}
    
     	
     }
    
     public void deleteZhangWu() {
     	// 刪除
     	// 呼叫查詢所有賬務資料的功能,顯示出來---
     	showAll();
     	// -------------------
     	Scanner sc=new Scanner(System.in);
     	System.out.println("選擇的刪除賬務,請輸入");
     	int id=sc.nextInt();
     	int cnt=controller.deleteZhangWu(id);
     	if(cnt>0) {
     		System.out.println("刪除成功");
     	}else {
     		System.out.println("刪除失敗");
     	}
     }
    
     public void editZhangWu() {
     	// 修改
     	// 呼叫查詢所有賬務資料的功能,顯示出來---
     			showAll();
     			// -------------------
     	System.out.println("選擇的是編輯功能,請輸入");
     	Scanner sc=new Scanner(System.in);
     	//-----------------------
     	System.out.println("請輸入ID:");
     	String id=sc.next();
     	while(!DataUtils.verifyMoney(id)) {
     		System.out.println("請重新輸入!");
     		id=sc.next();
     	}
     	//-=---------------------------
     	System.out.println("請輸入賬務分類:");
     	String flname = sc.next();
     	System.out.println("請輸入金額:");
     //	double money = sc.nextDouble();		
     	String money = sc.next();
     	while(!DataUtils.verifyMoney(money)) {
     		System.out.println("請重新輸入!");
     		money=sc.next();
     	}
     	
     	
     	System.out.println("請輸入賬戶名稱:");
     	String zhangHu = sc.next();
     	
     	System.out.println("請輸時間(xxxx-xx-xx):");
     	String time = sc.next();
     	while(!DataUtils.verifyDate(time)) {
     		System.out.println("請重新輸入!");
     		time=sc.next();
     	}
     	
     	System.out.println("請輸入用途:");
     	String description = sc.next();
     	
     	SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
     	Date date = new Date();
     	try {
     		date = formatter.parse(time);
     	} catch (ParseException e) {
     		System.out.println("日期轉換除了問題!");
     		e.printStackTrace();
     	}
    
     	ZhangWu zhangwu = new ZhangWu();
     	zhangwu.setZwid(Integer.parseInt(id));
     	zhangwu.setFlname(flname);
     	zhangwu.setMoney(Double.parseDouble(money));
     	zhangwu.setZhangHu(zhangHu);
     	zhangwu.setDescription(description);
     	zhangwu.setCreatetime(date);
    
     	int cnt=controller.editZhangWu(zhangwu);
     	if(cnt>0) {
     		System.out.println("修改成功!");
     	}else {
     		System.out.println("修改失敗!");
     	}
     	
     	
    
     }
    
     public void showAll() {
     	//顯示全部賬戶
     	PageBean<ZhangWu> page = new PageBean<ZhangWu>();
     	page.setPageNumber(1);
     	page.setPageSize(5);
     	page = controller.selectAll(page);
     	page.setPageSize(page.getTotal());
     	page = controller.selectAll(page);
     	System.out.println("ID\t類別\t賬戶\t金額\t時間\t\t說明");
     	for (ZhangWu z : page.getData()) {
     		System.out.println(z.toString());
     	}
     	// ----------------
     }
     
     public void addZhangWu() {
     	// 呼叫查詢所有賬務資料的功能,顯示出來---
     	showAll();
     	// -------------------
     	System.out.println("選擇的是增加賬務功能,請輸入:");
     	Scanner scc = new Scanner(System.in);
     	System.out.println("請輸入賬務分類:");
     	String flname = scc.next();
     	System.out.println("請輸入金額:");
     	String money = scc.next();
     	while(!DataUtils.verifyMoney(money)) {
     		System.out.println("請重新輸入!");
     		money=scc.next();
     	}
     	
     	
     	System.out.println("請輸入賬戶名稱:");
     	String zhangHu = scc.next();
     	System.out.println("請輸時間(xxxx-xx-xx):");
     	String time = scc.next();
     	
     	while(!DataUtils.verifyDate(time)) {
     		System.out.println("請重新輸入!");
     		time=scc.next();
     	}
     	
     	
     	System.out.println("請輸入用途:");
     	String description = scc.next();
     	
     	
     	
     	
     	SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
     	Date date = new Date();
     	try {
     		date = formatter.parse(time);
     	} catch (ParseException e) {
     		System.out.println("日期轉換除了問題!");
     		e.printStackTrace();
     	}
     	
     	
    
     	ZhangWu zhangwu = new ZhangWu();
     	zhangwu.setFlname(flname);
     	zhangwu.setMoney(Double.parseDouble(money));
     	zhangwu.setZhangHu(zhangHu);
     	zhangwu.setDescription(description);
     	zhangwu.setCreatetime(date);
    
     	int cnt = controller.addZhangWu(zhangwu);
     	if (cnt > 0) {
     		System.out.println("增加賬務成功");
     	} else {
     		System.out.println("增加賬務失敗");
     	}
    
     }
    
     public void selectAll() {
     	// 分頁查詢全部資料
    
     	int count = 1;
     	PageBean<ZhangWu> page = new PageBean<ZhangWu>();
    
     	page.setPageNumber(1);
     	page.setPageSize(4);
     	page = controller.selectAll(page);
     	System.out.println("ID\t類別\t賬戶\t金額\t時間\t\t說明");
     	for (ZhangWu z : page.getData()) {
     		System.out.println(z.toString());
     	}
     	System.out.println("第" + page.getPageNumber() + "頁;共" + page.getPageCount() + "頁。");
     	System.out.println("------------------");
    
     	System.out.println("輸入空格翻頁");
     	Scanner sc = new Scanner(System.in);
     	String m = sc.nextLine();
    
     	while (true) {
     		if (m.equals(" ")) {
     			if (count >= page.getPageCount()) {
     				// System.out.println("_________");
     				controller.getTotal();
     				System.out.println("輸入3返回上一級!");
     				break;
     			} else {
     				count++;
     				System.out.println("翻頁");
     				page.setPageNumber(count);
     			}
     		} else {
     			System.out.println("+++++++");
     		}
    
     		page = controller.selectAll(page);
     		System.out.println("ID\t類別\t賬戶\t金額\t時間\t\t說明");
     		for (ZhangWu z : page.getData()) {
     			System.out.println(z.toString());
     		}
     		System.out.println("第" + page.getPageNumber() + "頁;共" + page.getPageCount() + "頁。");
     		System.out.println("------------------");
    
     		m = sc.nextLine();
     	}
    
     }
    

}

5.在view中寫完自己的需求後,再就可以編寫control層:

package cn.njit.gjp.controller;

import cn.njit.gjp.entity.PageBean;
import cn.njit.gjp.entity.ZhangWu;
import cn.njit.gjp.service.ZhangWuService;
/***
 * 控制層
 * @author Liu
 *
 */
public class ZhangWuController {
	private ZhangWuService service=new ZhangWuService();
	
	public int addZhangWu(ZhangWu zhangwu) {
		return service.addZhangWu(zhangwu);
	}

	public PageBean<ZhangWu> selectAll(PageBean<ZhangWu> page) {		
		return service.selectAll(page);
	}
	
	
	
	public void getTotal() {		
		service.getTotal();
	}

	public PageBean<ZhangWu> conditionSelectZhangwu(String begin, String end,PageBean<ZhangWu> page) {		
		return service.conditionSelectZhangwu(begin,end,page);
	}

	public int deleteZhangWu(int id) {
		
		return service.deleteZhangWu(id);
	}

	public int editZhangWu(ZhangWu zhangwu) {
		return service.editZhangWu(zhangwu);
	}


	
}

6.service層

package cn.njit.gjp.service;

import cn.njit.gjp.dao.ZhangWuDao;
import cn.njit.gjp.entity.PageBean;
import cn.njit.gjp.entity.ZhangWu;

public class ZhangWuService {
	private ZhangWuDao dao = new ZhangWuDao();

	public int addZhangWu(ZhangWu zhangwu) {
		/**
		 * 定義方法,實現刪除功能
		 * 檢視層呼叫,傳遞int型別主鍵
		 * 呼叫service層方法,傳遞int主鍵
		 */
		
		
		return dao.addZhangWu(zhangwu);
		
		
	}

	public PageBean<ZhangWu> selectAll(PageBean<ZhangWu> page) {
		
		return dao.selectAll(page);
	}

	public void getTotal() {
		
		dao.getTotal();
	}

	public PageBean<ZhangWu> conditionSelectZhangwu(String begin, String end,PageBean<ZhangWu> page) {
		
		return dao.conditionSelectZhangwu(begin,end,page);
	}

	public int deleteZhangWu(int id) {
	
		return dao.deleteZhangWu(id);
	}

	public int editZhangWu(ZhangWu zhangwu) {
		
		return dao.editZhangWu(zhangwu);
	}
	
	
}

7.dao層

package cn.njit.gjp.dao;

import java.sql.SQLException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.ArrayListHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import cn.njit.gjp.entity.PageBean;
import cn.njit.gjp.entity.ZhangWu;
import cn.njit.gjp.tools.JDBCUtils;
/**
 * Dao實現層
 * @author Liu
 *
 */
public class ZhangWuDao {
	private QueryRunner qr=new QueryRunner(JDBCUtils.getDataSource());
	
	/**
	 * 
	 * @param zhangwu 實體類
	 * @return 增加賬務方法
	 */
	public int addZhangWu(ZhangWu zhangwu) {
		
		String sql="insert into personal_zhangwu(flname,money,zhangHu,createtime,description) VALUES(?,?,?,?,?); ";
		Object[] o= {zhangwu.getFlname(),zhangwu.getMoney(),zhangwu.getMoney(),zhangwu.getCreatetime(),zhangwu.getDescription()};
		try {
			int row=qr.update(sql,o);
			return row;
		} catch (SQLException e) {
			e.printStackTrace();
			return 0;
		}
		
	}
	
	/***
	 * 
	 * @param page 引數為一張空白的頁面
	 * @return 返回有內容的頁面
	 */
	public PageBean<ZhangWu> selectAll(PageBean<ZhangWu> page) {
		String sqll="select count(1) from personal_zhangwu";
		ScalarHandler<Long> slh=new ScalarHandler<Long>();
		
		Long cnt = null;
		try {
			cnt = qr.query(sqll, slh);
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
		int total=cnt.intValue();

		String sql="select * from personal_zhangwu limit ?,?;";
		BeanListHandler<ZhangWu> blh=new BeanListHandler<ZhangWu>(ZhangWu.class);
		
		int pageSize = page.getPageSize();
		int begin = (page.getPageNumber() - 1) * pageSize;
		
	//	System.out.println(begin+"xxxx"+pageSize);
		Object[] o= {begin,pageSize};
		

		try {		
			List<ZhangWu> list=qr.query(sql, blh,o);			
			page.setData(list);		
			page.setTotal(total);		
		} catch (SQLException e) {
			System.out.println("Dao層selectAll出錯");
			e.printStackTrace();
		}		
		return page;
	}
	/***
	 * 統計所有的賬戶
	 */
	public void getTotal() {
		String sql1="select SUM(money) FROM personal_zhangwu where flname LIKE ('支出%');";
		
		ArrayHandler ah=new ArrayHandler();
		String str1 = null;
		String str2 = null;
		
		try {
			Object[] rs=qr.query(sql1, ah);
			str1=rs[0].toString();
//			//-------------------------------
//			System.out.println(str1);
			
		} catch (SQLException e) {
			System.out.println("Dao>>getTotal()出錯>>第1個sql"); 
			System.out.println(sql1);
			e.printStackTrace();
		}
		
		String sql2="select SUM(money) FROM personal_zhangwu where flname LIKE ('收入%');";
		ah=new ArrayHandler();
		
		try {
			Object[] rs2=qr.query(sql2, ah);
			str2=rs2[0].toString();
//			//-------------------------------
//			System.out.println(str2);
		} catch (SQLException e) {
			System.out.println("Dao>>getTotal()出錯>>第2個sql");
			System.out.println(sql2);
			e.printStackTrace();
		}
		
		System.out.println("總支出:"+str1+", 總收入:"+str2+",淨收入:"+(Double.parseDouble(str2)-Double.parseDouble(str1)));
		
		String sql3="select flname as 款項,SUM(money) as 支出 FROM personal_zhangwu where flname LIKE ('支出%') GROUP BY flname ; ";
		ArrayListHandler ahs=new ArrayListHandler();

		System.out.println("支出統計:");
		try {
			List<Object[]> list=qr.query(sql3, ahs);
			for (int i = 0; i < list.size(); i++) {
				Object[] o=list.get(i);
				for(Object ox:o) {
					System.out.print(ox.toString()+"\t");	
				}
				System.out.println("");
			}
			
		} catch (SQLException e) {
			System.out.println("Dao>>getTotal()出錯>>第3個sql");
			System.out.println(sql3);
			e.printStackTrace();
		}

		
		String sql4="select flname as 款項,SUM(money) as 收入 FROM personal_zhangwu where flname LIKE ('收入%') GROUP BY flname ; ";
		ahs=new ArrayListHandler();
		System.out.println("收入統計:");
		try {
			List<Object[]> list=qr.query(sql4, ahs);
			for (int i = 0; i < list.size(); i++) {
				Object[] o=list.get(i);
				for(Object ox:o) {
					System.out.print(ox.toString()+"\t");	
				}
				System.out.println("");
			}
			
		} catch (SQLException e) {
			System.out.println("Dao>>getTotal()出錯>>第4個sql");
			System.out.println(sql4);
			e.printStackTrace();
		}
	}

/*	public PageBean<ZhangWu> conditionSelectZhangwu(String begin, String end,PageBean<ZhangWu> page) {

		String sqll="select count(1) from personal_zhangwu";
		ScalarHandler<Long> slh=new ScalarHandler<Long>();
		
		Long cnt = null;
		try {
			cnt = qr.query(sqll, slh);
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
		int total=cnt.intValue();
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		Date beginDate = new Date();
		Date endDate = new Date();
		
		try {
			beginDate = formatter.parse(begin);
			endDate=formatter.parse(end);
		} catch (ParseException e) {
			System.out.println("日期轉換除了問題!");
			e.printStackTrace();
		}
		//-----------------------------------------------------
		String sql="select * from personal_zhangwu where createtime>? and createtime<? limit ?,?";
		BeanListHandler<ZhangWu> blh=new BeanListHandler<ZhangWu>(ZhangWu.class);
		int pageSize = page.getPageSize();
		int beginSize = (page.getPageNumber() - 1) * pageSize;
		Object[] o= {beginDate,endDate,beginSize,pageSize};
		try {
			List<ZhangWu> list=qr.query(sql, blh,o);
			page.setData(list);
			page.setTotal(total);
		} catch (SQLException e) {
			System.out.println("Dao>>conditionSelectZhangwu()出錯>>第1個sql");
			e.printStackTrace();
		}
		return page;
	}
*/
	/**
	 * 
	 * @param begin 開始日期
	 * @param end	截至日期
	 * @param page  空白的頁面
	 * @return 有內容的頁面
	 */
	public PageBean<ZhangWu> conditionSelectZhangwu(String begin, String end,PageBean<ZhangWu> page){
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		Date beginDate = new Date();
		Date endDate = new Date();		
		
		
		
		try {
			beginDate = formatter.parse(begin);
			endDate=formatter.parse(end);
		} catch (ParseException e) {
			System.out.println("日期轉換除了問題!");
			e.printStackTrace();
		}
		String sqll="select count(1) from personal_zhangwu where createtime>? and createtime<?";
		ScalarHandler<Long> slh=new ScalarHandler<Long>();
		Object[] ox= {beginDate,endDate};
		Long cnt = null;
		try {
			cnt = qr.query(sqll, slh,ox);
		} catch (SQLException e1) {
			e1.printStackTrace();
		}
		int total=cnt.intValue();
		
		String sql="select * from personal_zhangwu where createtime>? and createtime<? limit ?,?";
		BeanListHandler<ZhangWu> blh=new BeanListHandler<ZhangWu>(ZhangWu.class);
		
		int pageSize = page.getPageSize();
		int beginPage = (page.getPageNumber() - 1) * pageSize;
		

		Object[] o= {begin,end,beginPage,pageSize};
		

		try {		
			List<ZhangWu> list=qr.query(sql, blh,o);			
			page.setData(list);		
			page.setTotal(total);		
		} catch (SQLException e) {
			e.printStackTrace();
		}		
		
		
		return page;
		
	}
	/**
	 * 
	 * @param id 賬務id
	 * @return 刪除結果 (1/0)
	 */
	public int deleteZhangWu(int id) {
		String sql="Delete from personal_zhangwu where zwid=?";
		int cnt = 0;
		try {
			cnt=qr.update(sql,id);			
		} catch (SQLException e) {
			System.out.println("Dao>>deleteZhangWu()出錯>>第1個sql");
			e.printStackTrace();
		}
		return cnt;
	}
	/***
	 * 
	 * @param zhangwu 
	 * @return cnt
	 */
	public int editZhangWu(ZhangWu zhangwu) {
		String sql="Update personal_zhangwu set zwid=?,flname=?,money=?,zhangHu=?,createtime=?,description=? where zwid=?";
		Object[] o= {zhangwu.getZwid(),zhangwu.getFlname(),zhangwu.getMoney(),zhangwu.getZhangHu(),zhangwu.getCreatetime(),zhangwu.getDescription(),zhangwu.getZwid()};
		int cnt = 0;
		try {
			cnt=qr.update(sql,o);
		} catch (SQLException e) {
			System.out.println("Dao>>editZhangWu()出錯>>第1個sql");
			e.printStackTrace();
		}
		
		
		return cnt;
	}
	
	/***
	 * 
	 * @return 所有結果封裝在list型中
	 */
	public List<ZhangWu> showListAll() {
		List<ZhangWu> list = null;
		String sql="select * from personal_zhangwu;";
		BeanListHandler<ZhangWu> blh=new BeanListHandler<ZhangWu>(ZhangWu.class);
		try {
			list=qr.query(sql,blh);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return list;
		
	}
	
}

8.當然,這個專案最重要的就是表現層和實現層,寫到DAO層的時候,我們就要寫實體類:兩個JavaBean——一個用於分頁管理,一個是賬務實體;

package cn.njit.gjp.entity;

import java.util.Date;

public class ZhangWu {
	private int zwid;
	private String flname;
	private double money;
	private String zhangHu;
	private Date createtime;
	private String description;
	public int getZwid() {
		return zwid;
	}
	public void setZwid(int zwid) {
		this.zwid = zwid;
	}
	public String getFlname() {
		return flname;
	}
	public void setFlname(String flname) {
		this.flname = flname;
	}
	public double getMoney() {
		return money;
	}
	public void setMoney(double money) {
		this.money = money;
	}
	public String getZhangHu() {
		return zhangHu;
	}
	public void setZhangHu(String zhangHu) {
		this.zhangHu = zhangHu;
	}
	public Date getCreatetime() {
		return createtime;
	}
	public void setCreatetime(Date createtime) {
		this.createtime = createtime;
	}
	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}
	public String toString() {
		return zwid+"\t"+flname+"\t"+zhangHu+"\t"+money+"\t"+createtime+"\t"+description;
	}
}
----------------------------------------------------------------------------------------
package cn.njit.gjp.entity;

import java.util.List;

public class PageBean<T> {
	private List<T> data;
	private int pageSize;//每頁顯示的條數
	private int total;//當前查詢條件下的總記錄條數
	private int pageNumber;//顯示哪一頁
	
	public int getPageCount() {
		return (int) Math.ceil(total*1.0/pageSize);
	}
	public List<T> getData() {
		return data;
	}
	public void setData(List<T> data) {
		this.data = data;
	}
	public int getPageSize() {
		return pageSize;
	}
	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}
	public int getTotal() {
		return total;
	}
	public void setTotal(int total) {
		this.total = total;
	}
	public int getPageNumber() {
		return pageNumber;
	}
	public void setPageNumber(int pageNumber) {
		this.pageNumber = pageNumber;
	}
}

9.秉承一個類只做一件事的原則,我們還需要大量的工具類,比如讀取配置檔案和對日期的處理;

package cn.njit.gjp.tools;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
/****
 * 獲取配置檔案的工具類
 * @author Liu
 *
 */
public class ConfigurationFiles {
	/***
	 * 
	 * @return port 埠
	 *
	 */
	public static String getPort() {
		String path="D:\\FileDemo\\SecondProject\\service.ini";
		InputStream is = null;
		try {
			is = new FileInputStream(path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		Properties pro=new Properties();
		try {
			pro.load(is);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String port=pro.getProperty("port");
		
		return port;
		
	}
	
	/**
	 * 
	 * @return 返回IP陣列
	 */
	public static String[] getIp() {
		String path="D:\\FileDemo\\SecondProject\\service.ini";
		InputStream is = null;
		try {
			is = new FileInputStream(path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		Properties pro=new Properties();
		
		try {
			pro.load(is);
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		try {
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		String ips=pro.getProperty("ips")+",";
		
		String[] strArray = null;   
        strArray = ips.split(",");
			
        for (int i = 0; i < strArray.length; i++) {
			strArray[i]=strArray[i].trim();
		}
        
		return strArray;
		
	}
	/**
	 * 判斷ip是否存在
	 * @param ip
	 * @return
	 */
	public static boolean isExist(String ip) {
		
		String[] array=ConfigurationFiles.getIp();
		for (String s : array) {
			if(ip.equals(s)) {
				return true;
			}
		}
		return false;
	}
}
----------------------------------------------------------------------
package cn.njit.gjp.tools;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtils {

	public static String Dateyyyy_MM_dd_time() {
		Date date=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyyMMdd-HH:mm:ss");
		String str=sdf.format(date);
		return str;
		
	}
	
	public static Date Dateyyyy_MM_dd_time(String str) {
		
		SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
		Date date = new Date();		
		try {
			date = formatter.parse(str);
		} catch (ParseException e) {
			System.out.println("日期轉換除了問題!");
			e.printStackTrace();
		}

		return date;
	}
}	

10.匯出賬務日誌;
在專案中,嵌入一個TCP server,用於接受客戶端的匯出請求。
再編寫一個單獨的TCP客戶端程式,執行此程式,可以向TCP Server發出匯出請求。
TCP SERVER收到客戶端請求後,從資料庫中讀取所有賬務記錄,按照賬務時間後先順序排序,然後把這些記錄返回給客戶端。
客戶端接收到伺服器端的資料後,把資料寫入本地檔案。
檔案中的格式與內容與“檢視賬務”介面上顯示的格式和內容一樣。
伺服器端要記錄匯出日誌到檔案,日誌檔名為export.log,日誌檔案格式樣例:
匯出總次數: 88,成功次數:77
20181017-10:33:22 192.168.10.66 匯出成功
20181017-10:36:33 127.0.0.1 匯出失敗,非法客戶端
20181022-09:10:12 192.168.10.77 匯出成功

記錄日誌檔案是,要避免多個客戶端同時匯出是日誌記錄的併發問題。

TCP服務端:

package cn.njit.gjp.ser;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import cn.njit.gjp.tools.ConfigurationFiles;
import cn.njit.gjp.tools.LogUtils;

public class ChatServer {
	private ServerSocket serverSocket;	
	public void setServerSocket() {
		try {
			this.serverSocket = new ServerSocket(Integer.parseInt(ConfigurationFiles.getPort()));
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	
	
private Socket socket;

public void Connect() {
	setServerSocket();
	while(true)
	{
		try {
			socket=serverSocket.accept();
			System.out.println("連線成功");
		} catch (IOException e) {
			e.printStackTrace();
			System.out.println("獲取失敗");
		}
		
		ChatThread s=new ChatThread(socket);
		Thread t= new Thread(s);
		t.start();
		
		try {
			LogUtils.LogPrint();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	}
}

服務執行緒類:

package cn.njit.gjp.ser;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.util.List;

import cn.njit.gjp.dao.ZhangWuDao;
import cn.njit.gjp.tools.ConfigurationFiles;
import cn.njit.gjp.tools.DateUtils;
import cn.njit.gjp.tools.LogUtils;

public class ChatThread implements Runnable {
	private Socket socket;
	private DataInputStream dis;
	private DataOutputStream dos;
	
	
	public ChatThread(Socket socket) {
		super();
		setSocket(socket);
	}
	
	public Socket getSocket() {
		return socket;
	}
	public void setSocket(Socket socket) {
		this.socket = socket;
	}

	@Override
	public void run() {
		//----------------------1.初始化------------//
		try {
			dis=new DataInputStream(socket.getInputStream());
			dos=new DataOutputStream(socket.getOutputStream());
		} catch (IOException e) {
			e.printStackTrace();
		}
		//-----------------------2.驗證ip-----------//
		InetAddress address=socket.getInetAddress();
		String ip=address.getHostAddress();
		StringBuffer strb=new StringBuffer();
		
		boolean tip=ConfigurationFiles.isExist(ip);
		//-----------------------3.打檔案-----------//
		System.out.println(tip);
		if(tip) {
			
			List<?> list=new ZhangWuDao().showListAll();
			StringBuffer sb=new StringBuffer();
			for (int i = list.size()-1; i >=0; i--) {
				sb.append(list.get(i));
				sb.append("\n");
			}
			System.out.println("OKOKOOK");
			try {
				dos.writeUTF(sb.toString());
			} catch (IOException e) {
				e.printStackTrace();
			}
			
			strb.append(DateUtils.Dateyyyy_MM_dd_time()+"\t"+ip+"\t匯入成功");
	
		}else{
			
			System.out.println("沒有這個ip");
			System.out.println("非法ip,非法連線");
			
			try {
				
				dos.writeUTF("非法ip,非法連線");
				
			} catch (IOException e) {
				e.printStackTrace();
			}
			strb.append(DateUtils.Dateyyyy_MM_dd_time()+"\t"+ip+"\t匯入失敗");
		}
		
		//------------------------4.打日誌------------------//
		try {
			//打日誌
			LogUtils.Write(strb.toString());
		//	LogUtils.LogPrint();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		
	}
	}

客戶端:

package cn.njit.gjp.ser;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
import java.util.UUID;

public class ChatClient {
	public static void main(String[] args) throws Exception{
		String host=args[0];
		int port=8888;
		int cnt=5; //執行緒數量
		long begin=new Date().getTime();
		ClientThread[] cts=new ClientThread[cnt];
		for(int i=0;i<cnt;i++) {
			ClientThread t=new ClientThread(host,port);
			cts[i]=t;
			t.start();
		}
		for(int i=0;i<cnt;i++) {
			cts[i].join();
		}
		long end=new Date().getTime();
		System.out.println("花費時間:"+(end-begin)+"毫秒");
	}
}

class ClientThread extends Thread{
	String host;
	int port;
	public ClientThread(String host,int port) {
		this.host=host;
		this.port=port;
	}
	public void run(){
		try {
			Socket s=new Socket(host,8888);
			InputStream is=s.getInputStream();
			int len=0;
			byte[] buffer=new byte[1024];
			len=is.read(buffer);
//----------------------------------------------------------------//			
			
			String fileName="D:\\FileDemo\\SecondProject\\"+UUID.randomUUID().toString()+".txt";
			OutputStream os=new FileOutputStream(fileName);
			while(-1!=len) {
				os.write(buffer,0,len);
				len=is.read(buffer);
			}
			
			os.close();
			is.close();
			s.close();
			
		}catch(Exception ex) {
			ex.printStackTrace();
		}
	}
}

11.同樣,對於TCP服務來說,也需要大量的工具類:

package cn.njit.gjp.tools;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;

public class ServerUtils {
	
	public static void send(DataOutputStream dos,String ip) {
		try {
			dos.writeUTF(ip);
			dos.flush();//++++		
		} catch (IOException e) {
			e.printStackTrace();
		}
		
	}
	
	public static String receiveId(DataInputStream dis) {
		String readUTF = null;
		try {
			readUTF = dis.readUTF();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return readUTF;
		
	}
	
	
	
    }
-----------------------------------------------------------------------------
package cn.njit.gjp.tools;

import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/***
 * 日誌列印工具類
 * @author Liu
 *
 */
public class LogUtils {
	private static DataInputStream dis;
	private static DataOutputStream dos;
	/***
	 * 
	 * @param str 列印的字串
	 * @throws IOException 丟擲IO異常
	 */
	public static void Write(String str) throws IOException {
		dos=new DataOutputStream(new FileOutputStream("D:\\FileDemo\\SecondProject\\log.log",true));
		dos.writeUTF(str+"\n");
		dos.flush();
		dos.close();
	}
	
	public static void LogPrint() throws IOException {
		dis=new DataInputStream(new FileInputStream("D:\\FileDemo\\SecondProject\\log.log"));
		
		byte[] buf=new byte[1024];
		int len=dis.read(buf);
		StringBuffer sb=new StringBuffer();
		while(-1!=len) {
			String str=new String(buf,0,buf.length);
			sb.append(str);
			len=dis.read(buf);
		}
		
		String[] strArray = null;   
        strArray = sb.toString().split("\n");
        List<String> list=new ArrayList<String>();
        for (int i = 0; i < strArray.length; i++) {
        	list.add(strArray[i].trim());
		}
        
        int count1 = 0,count2 = 0;
        for (int i = 0; i < list.size(); i++) {
			String str=list.get(i);
			if(str.contains("匯入")) {
				count1++;
			}
			if(str.contains("匯入成功")) {
				count2++;
			}
		}
        String str1="總次數:"+count1;
        String str2="成功:"+count2;
        String strM=str1+"\t"+str2;
        

        
//        for (int i = 0; i <list.size(); i++) {
//        	 sbb.append(list.get(i));
//		}
//       
//        
       
        BufferedWriter  br = new BufferedWriter(new FileWriter("D:\\FileDemo\\SecondProject\\log的log.txt"));        
        br.write(strM);
        br.close(); 
	}
	
}

12.最後是主函式:

package cn.njit.gjp.app;
import cn.njit.gjp.ser.ChatServer;
import cn.njit.gjp.view.MainView;

/****
 * 
 * @author Liu
 *
 */
public class MainApp{


	public static void main(String[] args) {

		MainView m=new MainView();
		Thread mm=new Thread(m,"主函式");
		mm.start();
		
		ChatServer cs=new ChatServer();
		cs.Connect();	
	}
}

結果演示:

增刪改查就不演示了,主要演示的是匯出賬務日誌這一段:
首先,啟動主函式的同時,啟動tcp執行緒:
在這裡插入圖片描述

然後,在命令列啟動客戶端:
在這裡插入圖片描述

最後檢視日誌:
在這裡插入圖片描述
在這裡插入圖片描述
在這裡插入圖片描述

寫在最後:
當然,任何一個專案都要求異常處理,尤其是使用標準輸入流在控制檯輸入資料的時候,對於Scanner函式的nextInt()來說,如果讀取到其他值是會報錯的,所以我們就要進行巧妙的型別檢查,還有日期之類的,平年時沒有2月29日的;

package cn.njit.gjp.tools;

import java.util.regex.Pattern;
/***
 * 驗證類,使用正則表示式
 * @author Liu
 *
 */
public class DataUtils {
	public static final String REGEX_money = "^[0-9]{0,10}$";
	public static final String REGEX_date = "((\\d{2}(([02468][048])|([13579][26]))[\\-]((((0?[13578])|(1[02]))[\\-]((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-]((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-]((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][1235679])|([13579][01345789]))[\\-]((((0?[13578])|(1[02]))[\\-]((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))[\\-]((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-]((0?[1-9])|(1[0-9])|(2[0-8]))))))";
	/***
	 * 
	 * @param str
	 * @return 是否是int
	 */
	public static boolean verifyMoney(String str) {    
		return Pattern.matches(REGEX_money,str);		
	}
	public static boolean verifyDate(String str) {
		return Pattern.matches(REGEX_date,str);
	}
}

Scanner的next是可以讀取到你輸入的任何字元的,所以我們在讀取字元的時候就一律使用這個函式,例如對money的處理。我們一般是使用nextDouble()來讀取,但是一旦讀取到其他型別就會報錯,所以我們使用next()來讀取,然後判斷它合不合法:

	String money = scc.next();
	while(!DataUtils.verifyMoney(money)) {
		System.out.println("請重新輸入!");
		money=scc.next();
	}
	
	//最後在插入的時候把合法的資料轉換成Double型:
	zhangwu.setMoney(Double.parseDouble(money));

對日期的驗證也是一樣,截至日期不能比開始日期早,而且要符合當年的規範(例如平年沒有2月29);

		System.out.println("請輸入開始日期:");
		String begin = sc.next();
		
		while(!DataUtils.verifyDate(begin)) {
			System.out.println("請重新輸入開始日期!");
			begin = sc.next();
		}
		
		
		System.out.println("請輸入截至日期:");
		String end = sc.next();
		while(!DataUtils.verifyDate(end)) {
			System.out.println("請重新輸入截至日期!");
			end = sc.next();
		}
		
		if(DateUtils.Dateyyyy_MM_dd_time(end).before((DateUtils.Dateyyyy_MM_dd_time(begin)))) {
			System.out.println("日期先後錯誤!");
			System.out.println("請輸入開始日期:");
			begin = sc.next();
			while(!DataUtils.verifyDate(begin)) {
				System.out.println("請重新輸入開始日期!");
				begin = sc.next();
			}
			System.out.println("請輸入截至日期:");
			end = sc.next();
			while(!DataUtils.verifyDate(end)) {
				System.out.println("請重新輸入截至日期!");
				end = sc.next();
			}
		}

當然,異常處理不只是我寫出來的那些,還有更多的異常等著我們去發現,去處理;