Java學習不走彎路教程(4.用SQL查詢遠端伺服器的檔案)
一. 前言
在前上一章教程中,介紹了用SQL查詢本地檔案。
程式程式碼請從 ofollow,noindex" target="_blank">這裡 下載。
本章將在上一章的基礎上,進一步擴充套件程式。
實際的生產環境中,一般查詢的檔案都放在遠端的檔案或資料伺服器上,
下面我將帶大家一步一步實現遠端查詢的程式。
注:
1.本文針對初學Java的同學訓練學習思路,請不要太糾結於細節問題。
2.本文旨在達到拋磚引玉的效果,希望大家擴充套件本例子,以學到更多知識的精髓。
二. 寫給初學Java的同學
在介紹本章內容之前,首先介紹一下Java的學習方法。
相信大家在看本文的時候已經已經拿到了各種Java學習路徑,大體都是一樣。
我想說的是,不要讓知識的學習成為負擔,Java技術種類繁多,是無論如何也學不完的。
正確的學習方法是興趣驅動,例項驅動。
即通過一個簡單的例項,不斷加入所學知識進行擴充套件,最終擴充套件為一個大專案,達到系統學習,學以致用的效果。
三. 步入正題
話不多說,大家自己理解,下面步入正題:
本章系統的流程如下:
【客戶端】
1.連線遠端伺服器。
2.向遠端伺服器傳送查詢SQL。
3.將遠端伺服器反饋的查詢結果輸出。
【伺服器】
1.在指定埠監聽,等待客戶端連線。
2.有客戶端連線後,讀取客戶端傳來的SQL。
3.呼叫檔案查詢模組,查詢資料。
4.將查詢的資料反饋給客戶端。
5.轉到步驟1。
工程的結構如下:

其中檔案查詢模組複用上一章的程式碼,在此不做講解。
我們著重介紹客戶端與伺服器通訊的過程。
要想與網路中的一臺機器的某個程式進行通訊,首先我們需要定位這臺機器的某個程式。
IP地址標識了網路中唯一的機器,這臺機器的不同的埠則標示了不同的程式。
所以,客戶端要知道連線伺服器的IP地址和埠號,來完成於伺服器的連線。
而伺服器程式之需要在特定的埠監聽,等待客戶端的連線。
伺服器連線成功後,即可通過輸入輸出流進行通訊。
前者能維持穩定的通訊,確保每一個傳送的資訊對方都收到。
後者只負責傳送資訊而不管對方有沒有收到。
比如文字通訊的軟體一般採用TCP/IP協議,因為要確保傳送的每條訊息對方都能收到。
音訊視訊通訊軟體一般採用UDP協議,因為缺了一點資訊也不影響對聲音影象的識別。
本專案我們採用TCP/IP協議,在Java中用ServerSocket和Socket封裝了TCP/IP協議,所以我們直接拿來用即可,感興趣的同學可以研究一下底層的實現。
四. 服務端程式
我們首先看單個客戶端與伺服器的通訊流程,如下圖所示:

多個客戶端連線後,如下圖所示:

所以,我們首先做一個類ClientThread,用來負責伺服器與客戶端通訊的執行緒,程式碼如下:
1 /** 2* 3* @author http://www.java123.vip 4* 5*/ 6 public class ClientThread implements Runnable{ 7 8private Socket socket; 9private BufferedReader br; 10private PrintWriter pw; 11 12public ClientThread(Socket socket) { 13try { 14 15// 建立輸入輸出流 16InputStream is = socket.getInputStream(); 17InputStreamReader isr = new InputStreamReader(is); 18br = new BufferedReader(isr); 19 20OutputStream os = socket.getOutputStream(); 21OutputStreamWriter osw = new OutputStreamWriter(os); 22pw = new PrintWriter(osw,true); 23 24} catch (IOException e) { 25e.printStackTrace(); 26} 27} 28 29public void run() { 30 31GetFile gf = new GetFile("c:/temp/"); 32 33while(true) { 34try { 35 36// 讀取客戶端的一行資訊 37String message = br.readLine(); 38System.out.println("get message:"+message); 39 40// 用冒號(:)來分隔資訊的頭與內容 41String header = message.split(":")[0]; 42String body = message.substring(message.indexOf(":")+1); 43 44// 查詢請求 45if(header.equals("query")) { 46String result = gf.queryFile(body); 47pw.println(result); 48 49// 斷開連線請求 50}else if(header.equals("bye")) { 51if(socket != null) { 52socket.close(); 53} 54break; 55} 56 57} catch(IOException e) { 58e.printStackTrace(); 59} catch (Exception e) { 60e.printStackTrace(); 61} 62} 63} 64 65 }
伺服器實現程式碼如下:
1 /** 2* 3* @author http://www.java123.vip 4* 5*/ 6 public class FileViewServer { 7 8private int port; 9 10public FileViewServer(int port) { 11this.port = port; 12} 13 14/** 15* 啟動伺服器 16*/ 17public void startServer() { 18try { 19 20ServerSocket ss = new ServerSocket(port); 21System.out.println("listening at port:"+port); 22 23while(true) { 24Socket s = ss.accept(); 25System.out.println("get connection:"+s.getInetAddress().toString()); 26 27// 得到連線後,啟動新執行緒負責通訊 28ClientThread clientThread = new ClientThread(s); 29new Thread(clientThread).start(); 30} 31 32} catch (IOException e) { 33e.printStackTrace(); 34} 35} 36 37public static void main(String[] args) { 38FileViewServer fvs = new FileViewServer(8000); 39fvs.startServer(); 40} 41 }
五. 客戶端程式
我們需要做三個方法:
・連線伺服器方法
・斷開伺服器方法
・查詢遠端檔案方法
程式碼如下:
連線伺服器方法
1private Socket socket; 2private BufferedReader br; 3private PrintWriter pw; 4 5/** 6* 連線遠端伺服器 7* 8* @param ip 9* @param port 10*/ 11public void connect(String ip, int port) { 12try { 13 14// 連線伺服器 15socket = new Socket(ip, port); 16 17// 建立輸入輸出流 18InputStream is = socket.getInputStream(); 19InputStreamReader isr = new InputStreamReader(is); 20br = new BufferedReader(isr); 21 22OutputStream os = socket.getOutputStream(); 23OutputStreamWriter osw = new OutputStreamWriter(os); 24pw = new PrintWriter(osw,true); 25 26} catch (IOException e) { 27e.printStackTrace(); 28} 29} 30
斷開伺服器方法
1 2/** 3* 斷開連線 4*/ 5public void disConnect() { 6try { 7 8// 傳送斷開連線請求 9pw.println("bye:bye"); 10socket.close(); 11} catch (IOException e) { 12e.printStackTrace(); 13} 14} 15
查詢遠端檔案方法
1/** 2* 查詢 3* 4* @param sql 5* @return 6*/ 7public String query(String sql) { 8 9StringBuffer result = new StringBuffer(""); 10 11try { 12 13// 傳送查詢請求 14pw.println("query:"+sql); 15 16while(true) { 17 18// 讀取查詢結果的每一行 19String queryResultLine = br.readLine(); 20 21// 讀到空字串表示結果讀取完畢 22if("".equals(queryResultLine)) { 23break; 24 25// 否則,把讀到的內容存起來 26}else { 27result.append(queryResultLine); 28result.append("\n"); 29} 30} 31} catch (IOException e) { 32e.printStackTrace(); 33} 34 35// 返回查詢結果 36return result.toString(); 37} 38
六. 測試
最後我們來測試這個程式,測試程式碼如下:
1 2/** 3* 測試 4* @param args 5*/ 6public static void main(String[] args) { 7FileViewClient fvc = new FileViewClient(); 8fvc.connect("127.0.0.1",8000); 9 10String sql1 = "select * from abc.csv "; 11String sql2 = "select id from abc.csv "; 12String sql3 = "select id,username from abc.csv where id=2 "; 13String sql4 = "select id,username from abc.csv where username=abc and password=aaa "; 14String sql5 = "select id,username from abc.csv where username=abc and password=bbb "; 15 16System.out.println("Execute:"+sql1); 17System.out.println(fvc.query(sql1)); 18 19System.out.println("Execute:"+sql2); 20System.out.println(fvc.query(sql2)); 21 22System.out.println("Execute:"+sql3); 23System.out.println(fvc.query(sql3)); 24 25System.out.println("Execute:"+sql4); 26System.out.println(fvc.query(sql4)); 27 28System.out.println("Execute:"+sql5); 29System.out.println(fvc.query(sql5)); 30 31fvc.disConnect(); 32}
首先啟動伺服器,輸出如下:
listening at port:8000
啟動客戶端測試程式:
客戶端輸出如下:
Execute:select * from abc.csv 1,abc,aaa 2,def,bbb 3,xyz,ccc Execute:select id from abc.csv 1 2 3 Execute:select id,username from abc.csv where id=2 2,def Execute:select id,username from abc.csv where username=abc and password=aaa 1,abc Execute:select id,username from abc.csv where username=abc and password=bbb
伺服器輸出如下:
listening at port:8000 get connection:/127.0.0.1 get message:query:select * from abc.csv get message:query:select id from abc.csv get message:query:select id,username from abc.csv where id=2 get message:query:select id,username from abc.csv where username=abc and password=aaa get message:query:select id,username from abc.csv where username=abc and password=bbb get message:bye:bye
完整程式碼請在 這裡 下載
如有問題,大家來我的網站進行提問。
https://www.java123.vip/qa七. 後續
本例為通過簡單的SQL語句查詢遠端存在的檔案,大家可以擴充套件此程式,比如用執行緒池來管理執行緒,對於異常資訊的處理等。
後續章節我將在此程式的基礎上,其支援JDBC介面,然後換成資料庫,並且一步一步實現ORM,Service,HTTP查詢等功能。
版權宣告:本教程版權歸java123.vip所有,禁止任何形式的轉載與引用。
原帖發表於:https://www.cnblogs.com/java123vip/p/9732445.html