Java学习不走弯路教程(4.用SQL查询远程服务器的文件)

 一. 前言
在前上一章教程中,介绍了用SQL查询本地文件。
程序代码请从这里下载。

本章将在上一章的基础上,进一步扩展程序。
实际的生产环境中,一般查询的文件都放在远程的文件或数据服务器上,
下面我将带大家一步一步实现远程查询的程序。

注:
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协议,因为要确保发送的每条消息对方都能收到。
音频视频通讯软件一般采用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

posted @ 2018-10-01 17:50  java123.vip  阅读(474)  评论(0编辑  收藏  举报