一. 前言
在前上一章教程中,介紹了用SQL查詢本地文件。
程序代碼請從這裏下載。html
本章將在上一章的基礎上,進一步擴展程序。
實際的生產環境中,通常查詢的文件都放在遠程的文件或數據服務器上,
下面我將帶你們一步一步實現遠程查詢的程序。java
注:
1.本文針對初學Java的同窗訓練學習思路,請不要太糾結於細節問題。
2.本文旨在達到拋磚引玉的效果,但願你們擴展本例子,以學到更多知識的精髓。sql
二. 寫給初學Java的同窗
在介紹本章內容以前,首先介紹一下Java的學習方法。
相信你們在看本文的時候已經已經拿到了各類Java學習路徑,大致都是同樣。
我想說的是,不要讓知識的學習成爲負擔,Java技術種類繁多,是不管如何也學不完的。
正確的學習方法是興趣驅動,實例驅動。
即經過一個簡單的實例,不斷加入所學知識進行擴展,最終擴展爲一個大項目,達到系統學習,學以至用的效果。數據庫
三. 步入正題
話很少說,你們本身理解,下面步入正題:服務器
本章系統的流程以下:網絡
【客戶端】
1.鏈接遠程服務器。
2.向遠程服務器發送查詢SQL。
3.將遠程服務器反饋的查詢結果輸出。app
【服務器】
1.在指定端口監聽,等待客戶端鏈接。
2.有客戶端鏈接後,讀取客戶端傳來的SQL。
3.調用文件查詢模塊,查詢數據。
4.將查詢的數據反饋給客戶端。
5.轉到步驟1。socket
工程的結構以下:
其中文件查詢模塊複用上一章的代碼,在此不作講解。
咱們着重介紹客戶端與服務器通信的過程。學習
要想與網絡中的一臺機器的某個程序進行通信,首先咱們須要定位這臺機器的某個程序。
IP地址標識了網絡中惟一的機器,這臺機器的不一樣的端口則標示了不一樣的程序。測試
因此,客戶端要知道鏈接服務器的IP地址和端口號,來完成於服務器的鏈接。
而服務器程序之須要在特定的端口監聽,等待客戶端的鏈接。
服務器鏈接成功後,便可經過輸入輸出流進行通信。
通信協議分爲兩種TCP/IP協議和UDP協議:
前者能維持穩定的通信,確保每個發送的信息對方都收到。
後者只負責發送信息而無論對方有沒有收到。
好比文字通信的軟件通常採用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 8 private Socket socket; 9 private BufferedReader br; 10 private PrintWriter pw; 11 12 public ClientThread(Socket socket) { 13 try { 14 15 // 建立輸入輸出流 16 InputStream is = socket.getInputStream(); 17 InputStreamReader isr = new InputStreamReader(is); 18 br = new BufferedReader(isr); 19 20 OutputStream os = socket.getOutputStream(); 21 OutputStreamWriter osw = new OutputStreamWriter(os); 22 pw = new PrintWriter(osw,true); 23 24 } catch (IOException e) { 25 e.printStackTrace(); 26 } 27 } 28 29 public void run() { 30 31 GetFile gf = new GetFile("c:/temp/"); 32 33 while(true) { 34 try { 35 36 // 讀取客戶端的一行信息 37 String message = br.readLine(); 38 System.out.println("get message:"+message); 39 40 // 用冒號(:)來分隔信息的頭與內容 41 String header = message.split(":")[0]; 42 String body = message.substring(message.indexOf(":")+1); 43 44 // 查詢請求 45 if(header.equals("query")) { 46 String result = gf.queryFile(body); 47 pw.println(result); 48 49 // 斷開鏈接請求 50 }else if(header.equals("bye")) { 51 if(socket != null) { 52 socket.close(); 53 } 54 break; 55 } 56 57 } catch(IOException e) { 58 e.printStackTrace(); 59 } catch (Exception e) { 60 e.printStackTrace(); 61 } 62 } 63 } 64 65 }
服務器實現代碼以下:
1 /** 2 * 3 * @author http://www.java123.vip 4 * 5 */ 6 public class FileViewServer { 7 8 private int port; 9 10 public FileViewServer(int port) { 11 this.port = port; 12 } 13 14 /** 15 * 啓動服務器 16 */ 17 public void startServer() { 18 try { 19 20 ServerSocket ss = new ServerSocket(port); 21 System.out.println("listening at port:"+port); 22 23 while(true) { 24 Socket s = ss.accept(); 25 System.out.println("get connection:"+s.getInetAddress().toString()); 26 27 // 獲得鏈接後,啓動新線程負責通信 28 ClientThread clientThread = new ClientThread(s); 29 new Thread(clientThread).start(); 30 } 31 32 } catch (IOException e) { 33 e.printStackTrace(); 34 } 35 } 36 37 public static void main(String[] args) { 38 FileViewServer fvs = new FileViewServer(8000); 39 fvs.startServer(); 40 } 41 }
五. 客戶端程序
咱們須要作三個方法:
・鏈接服務器方法
・斷開服務器方法
・查詢遠程文件方法
代碼以下:
鏈接服務器方法
1 private Socket socket; 2 private BufferedReader br; 3 private PrintWriter pw; 4 5 /** 6 * 鏈接遠程服務器 7 * 8 * @param ip 9 * @param port 10 */ 11 public void connect(String ip, int port) { 12 try { 13 14 // 鏈接服務器 15 socket = new Socket(ip, port); 16 17 // 建立輸入輸出流 18 InputStream is = socket.getInputStream(); 19 InputStreamReader isr = new InputStreamReader(is); 20 br = new BufferedReader(isr); 21 22 OutputStream os = socket.getOutputStream(); 23 OutputStreamWriter osw = new OutputStreamWriter(os); 24 pw = new PrintWriter(osw,true); 25 26 } catch (IOException e) { 27 e.printStackTrace(); 28 } 29 } 30
斷開服務器方法
1 2 /** 3 * 斷開鏈接 4 */ 5 public void disConnect() { 6 try { 7 8 // 發送斷開鏈接請求 9 pw.println("bye:bye"); 10 socket.close(); 11 } catch (IOException e) { 12 e.printStackTrace(); 13 } 14 } 15
查詢遠程文件方法
1 /** 2 * 查詢 3 * 4 * @param sql 5 * @return 6 */ 7 public String query(String sql) { 8 9 StringBuffer result = new StringBuffer(""); 10 11 try { 12 13 // 發送查詢請求 14 pw.println("query:"+sql); 15 16 while(true) { 17 18 // 讀取查詢結果的每一行 19 String queryResultLine = br.readLine(); 20 21 // 讀到空字符串表示結果讀取完畢 22 if("".equals(queryResultLine)) { 23 break; 24 25 // 不然,把讀到的內容存起來 26 }else { 27 result.append(queryResultLine); 28 result.append("\n"); 29 } 30 } 31 } catch (IOException e) { 32 e.printStackTrace(); 33 } 34 35 // 返回查詢結果 36 return result.toString(); 37 } 38
六. 測試
最後咱們來測試這個程序,測試代碼以下:
1 2 /** 3 * 測試 4 * @param args 5 */ 6 public static void main(String[] args) { 7 FileViewClient fvc = new FileViewClient(); 8 fvc.connect("127.0.0.1",8000); 9 10 String sql1 = "select * from abc.csv "; 11 String sql2 = "select id from abc.csv "; 12 String sql3 = "select id,username from abc.csv where id=2 "; 13 String sql4 = "select id,username from abc.csv where username=abc and password=aaa "; 14 String sql5 = "select id,username from abc.csv where username=abc and password=bbb "; 15 16 System.out.println("Execute:"+sql1); 17 System.out.println(fvc.query(sql1)); 18 19 System.out.println("Execute:"+sql2); 20 System.out.println(fvc.query(sql2)); 21 22 System.out.println("Execute:"+sql3); 23 System.out.println(fvc.query(sql3)); 24 25 System.out.println("Execute:"+sql4); 26 System.out.println(fvc.query(sql4)); 27 28 System.out.println("Execute:"+sql5); 29 System.out.println(fvc.query(sql5)); 30 31 fvc.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