Java網頁數據采集器[續篇-遠程操作]


本期概述

上期我們學習了html頁面采集后的數據查詢, 但這僅僅是在本地查詢數據庫,如果我們想通過遠程操作來進行數據的采集,存儲和查詢,那又該怎么做呢?

今天我們一起來學習下:如何通過本地客戶端遠程訪問服務端進行數據的采集,存儲和查詢.

數據采集頁面 2011-2012賽季英超球隊戰績

 

學習簡單遠程訪問(RMI實例)

首先我們學習下簡單的客戶端遠程訪問服務端的例子. 

這里用到了 Java RMI (Remote Method Invocation)

Java RMI是一種機制, 是能夠讓一個 java虛擬機 調用 另一個java 虛擬機上對象的方法, 從而實現遠程訪問.

但是通過客戶端實現該遠程訪問,必須綁定一個遠程接口對象(意味着客戶端可以訪問到的服務端上的方法必須全部包含在這個接口里).

 

好了,我們來寫下例子代碼.

定義遠程接口

首先,我們需要寫個遠程接口HelloInterface 該接口繼承了遠程對象Remote.

接口HelloInterface里面有個sayHello的方法,用於客戶端連接后 打招呼.

由於sayHello方法繼承了遠程Remote對象, 所以需要拋一個 RemoteException 遠程異常.

package Remote_Interface;

import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* 接口HelloInterface 繼承了 遠程接口 Remote 用於客戶端Client遠程調用
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public interface HelloInterface extends Remote{

public String sayHello(String name) throws RemoteException;
}

 

實現接口(實現接口在服務端)

接下來,我們實現下 該接口里的方法, 實現接口的方法在服務端.

這里的HelloInterfaceImpl類 實現了接口HelloInterface里的方法.

注意:這里HelloInterfaceImpl 同樣繼承了 UnicastRemoteObject 遠程對象,這個必須寫,雖然不寫 代碼智能提示不會提示有錯,但服務端啟動后會莫名其妙報錯.

由於 UnicastRemoteObject 遠程對象 需要拋出一個RemoteException 異常, 所以這里用了一個構造方法 HelloInterfaceImpl() 來拋這個異常.

package Server;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

import Remote_Interface.HelloInterface;
/**
* HelloInterfaceImpl 用於實現 接口HelloInterface 的遠程 SayHello方法
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
@SuppressWarnings("serial")
// 繼承 UnicastRemoteObject 遠程對象 這個一定要寫 否則 服務端啟動報異常
public class HelloInterfaceImpl extends UnicastRemoteObject implements HelloInterface{

//HelloInterfaceImpl的構造方法 用於拋出UnicastRemoteObject 遠程對象里的異常
protected HelloInterfaceImpl() throws RemoteException {
}

public String sayHello(String name) throws RemoteException {
//該信息 在客戶端上發出
String strHello = "你好! " + name+" 歡迎訪問服務端!";
//這條信息 是在服務端上 打印出來
System.out.println(name +" 正在 訪問本服務端!");
return strHello;
}
}

 

編寫服務端

接下來,我們來寫 服務端,由於RMI 實現遠程訪問的機制是指:客戶端通過在RMI注冊表上尋找遠程接口對象的地址(服務端地址) 達到實現遠程訪問的目的,

所以,我們需要在 服務端 創建一個遠程對象的注冊表,用於綁定和注冊 服務端地址 和 遠程接口對象,便於后期客戶端能夠成功找到服務端 (詳細請看代碼注釋).

package Server;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

import Remote_Interface.HelloInterface;

/**
* Server 類 用於 啟動 注冊服務端
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public class Server {

public static void main(String[] args) {
try {
// 定義遠程接口HelloInterface 對象 用於綁定在服務端注冊表上 該接口由HelloInterfaceImpl()類實現
HelloInterface hInterface = new HelloInterfaceImpl();
int port = 6666; // 定義一個端口號
// 創建一個接受對特定端口調用的遠程對象注冊表 注冊表上需要接口一個指定的端口號
LocateRegistry.createRegistry(port);
// 定義 服務端遠程地址 URL格式
String address = "rmi://localhost:" + port + "/hello";
// 綁定遠程地址和接口對象
Naming.bind(address,hInterface);

// 如果啟動成功 則彈出如下信息
System.out.println(">>>服務端啟動成功");
System.out.println(">>>請啟動客戶端進行連接訪問");
} catch (MalformedURLException e) {
System.out.println("地址出現錯誤!");
e.printStackTrace();
} catch (AlreadyBoundException e) {
System.out.println("重復綁定了同一個遠程對象!");
e.printStackTrace();
} catch (RemoteException e) {
System.out.println("創建遠程對象出現錯誤!");
e.printStackTrace();
}
}
}


編寫客戶端

服務端寫完了,我們來寫下訪問服務端需要的客戶端.

客戶端上同樣需要定義一個 遠程訪問的地址 - 即服務端地址,

然后,通過在RMI注冊表上尋找 該地址;  如果找到 則建立連接.

package Client;

import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

import Remote_Interface.HelloInterface;

/**
* Client 用於連接 並訪問 服務端Server
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public class Client {

public static void main(String[] args) {
// 定義一個端口號 該端口號必須與服務端的端口號相同
int port = 6666;
// 同樣定義一個遠程地址 該地址為服務端的遠程地址 所以 與服務端的地址是一樣的
String address = "rmi://localhost:" + port + "/hello";

// 在RMI注冊表上需找 對象為HelloInterface的地址 即服務端地址
try {
HelloInterface hInterface = (HelloInterface) Naming.lookup(address);
// 一旦客戶端找到該服務端地址 則 進行連接
System.out.println("<<<客戶端訪問成功!");
//客戶端 Client 調用 遠程接口里的 sayHello 方法 並打印出來
System.out.println(hInterface.sayHello("SoFlash"));

} catch (MalformedURLException e) {
System.out.println("錯誤的地址!");
e.printStackTrace();
} catch (RemoteException e) {
System.out.println("創建遠程對象出錯!");
e.printStackTrace();
} catch (NotBoundException e) {
System.out.println("未綁定的遠程對象!");
e.printStackTrace();
}
}
}


運行程序

首先,啟動服務端,這里用的是 導出的服務端可運行jar文件.

 

然后,啟動客戶端來訪問,服務端反饋一條訪問成功信息:你好! SoFlash 歡迎訪問服務端!

 

同時服務端顯示:客戶端用戶SoFlash 正在訪問本服務端

 

例子介紹完了,你是否明白了呢?  :p

附上例子 源代碼 下載   Remote_Hello.zip  

jar文件  客戶端 Hello_Client_jar.zip  服務端 Hello_Server_jar.zip

 

遠程數據采集實現

定義遠程接口

例子學完,那么讓我們來 一起實現下 遠程訪問服務端 實現 足球網站的數據采集.

首先,我們寫個 遠程接口DataQueryInterface,它繼承了遠程對象Remote 里面包含了一些空方法,在服務端的DataQueryImpl類里面實現.

DataQueryInterface 類
package Remote_Interface;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.util.List;
import java.util.Vector;

/**
* 接口 DataQueryInterface 繼承了 遠程接口 Remote 用於遠程訪問
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public interface DataQueryInterface extends Remote {

public void initialDataBase() throws RemoteException;

public void dataCollectAndStore() throws RemoteException;

public Vector<String> getAllTeams() throws RemoteException;

public Vector<String> querySpecifiedTeam(String league) throws RemoteException;

public List<String> queryByDate(String date) throws RemoteException;

}

 

編寫服務端(服務端包含了接口的實現)

接口完成, 我們來寫下服務端代碼.

Server類是包含了一個主函數 並且 綁定了遠程接口對象(詳細介紹 請看代碼注釋).

Server類
package Server;

import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

import Remote_Interface.DataQueryInterface;
/**
 * Server 類 用於啟動服務端
 * @author SoFlash - 博客園  http://www.cnblogs.com/longwu
 */
public class Server {
    /**
     * 服務端上主函數 用於啟動服務端
     */
    public static void main(String[] args) {
        
        try {
            //定義遠程接口DataQueryInterface對象 用於綁定在服務端上  該接口由 DataQueryImpl()類實現
            DataQueryInterface dqi = new DataQueryImpl();
            int port = 6666;  //定義一個端口號
            //創建一個接受對特定端口調用的遠程對象注冊表  注冊表上需要接口一個指定的端口號
            LocateRegistry.createRegistry(port);
            //定義 服務端遠程地址  URL格式
            String address = "rmi://localhost:" + port + "/RemoteQuery";
            //綁定遠程地址和接口對象
            Naming.bind(address,dqi);
            //如果啟動成功 則彈出如下信息
            System.out.println(">>>服務端啟動成功");
            System.out.println(">>>請啟動客戶端進行連接訪問");
        } catch (MalformedURLException e) {
            System.out.println("地址出現錯誤!");
            e.printStackTrace();
        } catch (AlreadyBoundException e) {
            System.out.println("重復綁定了同一個遠程對象!");
            e.printStackTrace();
        } catch (RemoteException e) {
            System.out.println("創建遠程對象出現錯誤!");
            e.printStackTrace();
        }
    }
}

 

DataCollectionAndStorage 類 以及里面的dataCollectAndStore() 方法 用於收集和存儲數據.

DataCollectionAndStorage類
package Server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
/**
* DataCollectionAndStorage類 用於數據的收集和存儲
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public class DataCollectionAndStorage{
/**
* dataCollectAndStore()方法 用於Html數據收集和存儲
*/
public void dataCollectAndStore() {
// 首先用一個字符串 來裝載網頁鏈接
String strUrl = "http://www.footballresults.org/league.php?all=1&league=EngPrem";

String sqlLeagues = "";
try {
// 創建一個url對象來指向 該網站鏈接 括號里()裝載的是該網站鏈接的路徑
// 更多可以看看 http://wenku.baidu.com/view/8186caf4f61fb7360b4c6547.html
URL url = new URL(strUrl);
// InputStreamReader 是一個輸入流讀取器 用於將讀取的字節轉換成字符
// 更多可以看看 http://blog.sina.com.cn/s/blog_44a05959010004il.html
InputStreamReader isr = new InputStreamReader(url.openStream(),
"utf-8"); // 統一使用utf-8 編碼模式
// 使用 BufferedReader 來讀取 InputStreamReader 轉換成的字符
BufferedReader br = new BufferedReader(isr);
String strRead = ""; // new 一個字符串來裝載 BufferedReader 讀取到的內容

// 定義3個正則 用於獲取我們需要的數據
String regularDate = "(\\d{1,2}\\.\\d{1,2}\\.\\d{4})";
String regularTwoTeam = ">[^<>]*</a>";
String regularResult = ">(\\d{1,2}-\\d{1,2})</TD>";

//創建 GroupMethod類的對象 gMethod 方便后期調用其類里的 regularGroup方法
GroupMethod gMethod = new GroupMethod();
//創建DataStructure數據結構 類的對象 用於數據下面的數據存儲
DataStructure ds = new DataStructure();
//創建MySql類的對象 用於執行MySql語句
MySql ms = new MySql();
int i = 0; // 定義一個i來記錄循環次數 即收集到的球隊比賽結果數
int index = 0; // 定義一個索引 用於獲取分離 2個球隊的數據 因為2個球隊正則是相同的
// 開始讀取數據 如果讀到的數據不為空 則往里面讀
while ((strRead = br.readLine()) != null) {
/**
* 用於捕獲日期數據
*/
String strGet = gMethod.regularGroup(regularDate, strRead);
// 如果捕獲到了符合條件的 日期數據 則打印出來

if (!strGet.equals("")) {
//System.out.println("Date:" + strGet);
//將收集到的日期存在數據結構里
ds.date = strGet;
// 這里索引+1 是用於獲取后期的球隊數據
++index; // 因為在html頁面里 源代碼里 球隊數據是在剛好在日期之后
}
/**
* 用於獲取2個球隊的數據
*/
strGet = gMethod.regularGroup(regularTwoTeam, strRead);
if (!strGet.equals("") && index == 1) { // 索引為1的是主隊數據
// 通過subtring方法 分離出 主隊數據
strGet = strGet.substring(1, strGet.indexOf("</a>"));
//System.out.println("HomeTeam:" + strGet); // 打印出主隊
//將收集到的主隊名稱 存到 數據結構里
ds.homeTeam = strGet;
index++; // 索引+1之后 為2了
// 通過subtring方法 分離出 客隊
} else if (!strGet.equals("") && index == 2) { // 這里索引為2的是客隊數據
strGet = strGet.substring(1, strGet.indexOf("</a>"));
//System.out.println("AwayTeam:" + strGet); // 打印出客隊
//將收集到的客隊名稱 存到數據結構里
ds.awayTeam = strGet;
index = 0; //收集完客隊名稱后 需要將索引還原 用於收集下一條數據的主隊名稱
}
/**
* 用於獲取比賽結果
*/
strGet = gMethod.regularGroup(regularResult, strRead);
if (!strGet.equals("")) {
// 這里同樣用到了substring方法 來剔除'<' 和 "</TD>" 標簽 來獲取我們想要的比賽結果
strGet = strGet.substring(1, strGet.indexOf("</TD>"));
//System.out.println("Result:" + strGet);
ds.result = strGet; //將收集到的比賽結果存到數據結構里
//System.out.println();

//MySql插入語句
sqlLeagues = "INSERT INTO Premiership values(\""
+ ds.date + "\"," + "\"" + ds.homeTeam
+ "\"," + "\"" + ds.awayTeam + "\","+ "\"" + ds.result + "\")";
//調用MySql類的datatoMySql()方法 來執行 MySql插入語句
ms.datatoMySql(sqlLeagues);
i++; //每插入完一條記錄 i+1;
System.out.println("第"+i+"條數據插入成功");
}
}
// 當讀完數據后 記得關閉 BufferReader
br.close();
//System.out.println("共收集到" + i + "條比賽記錄");// 打印出循環次數
//當數據存儲完成后 打印出 收集球隊記錄數
System.out.println("數據存儲完畢,共插入數據庫"+i+"條記錄");
} catch (IOException e) {
// 如果出錯 拋出異常
e.printStackTrace();
}
}
}

 

實現接口(在服務端)

DataQueryImpl 類 用於實現接口DataQueryInterface 以及里面的所有方法 (具體請看代碼及注釋).

DataQueryImpl 類
package Server;

import Remote_Interface.DataQueryInterface;

import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector;
/**
* DataQueryImpl類 用於實現 接口 DataQueryInterface
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
@SuppressWarnings("serial")
public class DataQueryImpl extends UnicastRemoteObject implements
DataQueryInterface {
/**
* DataQueryImpl類的空構造方法
* 這個構造方法一定要寫 因為繼承 UnicastRemoteObject類 需要拋出了一個遠程異常
* 這里使用 DataQueryImpl類 來拋這個異常
*
@throws RemoteException
*/
public DataQueryImpl() throws RemoteException {
}

/**
* 因為實現了 遠程接口DataQueryInterface里的方法 所以需要拋出一個遠程異常 以下所有接口里的方法同理
* 用於清空數據庫里比賽結果
*/
public void initialDataBase() throws RemoteException {
String initialSql = "delete from premiership";
MySql ms = new MySql();
try {
// MySql類里 提供了一個 刪除數據的 方法 executeUpdate()
ms.datatoMySql(initialSql);
System.out.println("數據庫清空成功!");
} catch (Exception e) {
System.out.println("數據庫清空失敗!");
}
}

/**
* 因為這里只用了一個遠程接口 DataQueryInterface
* 所以實現該接口的類DataQueryImpl 需要實施所有的方法
* 這里調用了 DataCollectionAndStorage類里收集和存儲數據的方法
*/
public void dataCollectAndStore() throws RemoteException {
DataCollectionAndStorage ds = new DataCollectionAndStorage();
ds.dataCollectAndStore();
}

/**
* 用於 獲取當前數據庫里一共有多少球隊 方便后期查看自己喜歡的球隊比賽成績
*
@return 所有的參與過比賽的球隊名
*/
public Vector<String> getAllTeams() throws RemoteException {
// 使用一個向量來 存取 從數據庫中讀到的值
Vector<String> vecAllTeams = new Vector<String>();
String allteamsSql = "select HomeTeam,AwayTeam from premiership group by HomeTeam;";
ResultSet rs = null;
MySql ms = new MySql();
// 調用 MySql類里 查看數據的方法
rs = ms.queryMySql(allteamsSql);
try {
// 如果 ResultSet數據集里的數據不為空 則獲取相應的 數據 添加到 向量vecAllTeams里
while (rs.next()) {
if (!vecAllTeams.contains(rs.getString("HomeTeam")))
vecAllTeams.add(rs.getString("HomeTeam"));
else if (!vecAllTeams.contains(rs.getString("AwayTeam")))
vecAllTeams.add(rs.getString("AwayTeam"));
}

} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
// 返回 取到的所有球隊名
return vecAllTeams;
}

/**
* 查看具體的球隊比賽結果
*
@param league
*
@return 具體球隊的所有比賽結果
*/
public Vector<String> querySpecifiedTeam(String league) {
// 創建一個向量 來裝載 從數據庫中 讀到的數據
Vector<String> lsMatches = new Vector<String>();
String specifiedTeamSql = "select * from premiership where HomeTeam ='"
+ league + "' or AwayTeam ='" + league + "'";
MySql ms = new MySql();
ResultSet rs = null;
rs = ms.queryMySql(specifiedTeamSql);
try {
while (rs.next()) {
lsMatches.add(rs.getString("Date"));
lsMatches.add(rs.getString("HomeTeam"));
lsMatches.add(rs.getString("AwayTeam"));
lsMatches.add(rs.getString("Result"));
}
} catch (SQLException e) {
e.printStackTrace();
}
return lsMatches;

}

/**
* 查看 某一天的 比賽結果
*
@param date
*
@return 某一天的所有比賽結果
*/
public List<String> queryByDate(String date) throws RemoteException {
// 使用一個 list泛型來裝載 比賽結果
List<String> lsMatchesOnDate = new ArrayList<String>();
String sqlDate = "SELECT * FROM premiership WHERE Date ='" + date + "'";
// 創建一個ResultSet數據集 用來 獲取查詢到的結果集
ResultSet rs = null;
MySql ms = new MySql();
// 調用 MySql 類里的 查看數據庫數據的方法
rs = ms.queryMySql(sqlDate);
try {
// 如果 ResultSet數據集 不為空
while (rs.next()) {
// 則 從ResultSet數據集 中取出 相應的 字段值 添加到 list泛型里
lsMatchesOnDate.add(rs.getString("Date"));
lsMatchesOnDate.add(rs.getString("HomeTeam"));
lsMatchesOnDate.add(rs.getString("AwayTeam"));
lsMatchesOnDate.add(rs.getString("Result"));
}
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
// 最后 返回 取到的所有比賽數據結果
return lsMatchesOnDate;
}

}

 

DataStructure類 簡單的數據結構 用於頁面采集到的數據 臨時性的存儲.

DataStructure 類
package Server;
/**
* DataStructure 類 一個簡單的數據結構
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public class DataStructure {
//定義數據字段
public String homeTeam;
public String awayTeam;
public String date;
public String result;
}

 

GroupMethod類 以及 里面的regularGroup()方法 用於匹配 並抓取 html 頁面上需要的數據.

GroupMethod 類
package Server;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* GroupMethod 類 用於匹配和抓取 html頁面的數據
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public class GroupMethod {
// 傳入2個字符串參數 一個是pattern(我們使用的正則) 另一個matcher是html源代碼
public String regularGroup(String pattern, String matcher) {
Pattern p = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
Matcher m = p.matcher(matcher);
if (m.find()) { // 如果讀到
return m.group();// 返回捕獲的數據
} else {
return ""; // 否則返回一個空字符串
}
}
}

 

MySql類 用於實施 MySql數據庫操作 里面包含了2個方法

  • datatoMySql() 方法 用於向數據庫里插入數據 
  • queryMySql() 方法 用於查詢數據 
MySql 類
package Server;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
* MySql類用於實施MySql數據庫操作
*
@author SoFlash - 博客園 http://www.cnblogs.com/longwu
*/
public class MySql {

// 定義MySql驅動,數據庫地址,數據庫用戶名 密碼, 執行語句和數據庫連接
public String driver = "com.mysql.jdbc.Driver";
public String url = "jdbc:mysql://127.0.0.1:3306/htmldatacollection";
public String user = "root";
public String password = "root";
public Statement stmt = null;
public Connection conn = null;

/**
* 創建一個插入數據的方法 executeUpdate()
*
@param insertSQl
*/
public void datatoMySql(String insertSQl) {

try {
try {
Class.forName(driver).newInstance();
} catch (Exception e) {
System.out.println("無法找到驅動器");
e.printStackTrace();
}
// 創建連接
conn = DriverManager.getConnection(url, user, password);
// 創建一個 Statement 對象來將 SQL 語句發送到數據庫
stmt = conn.createStatement();
// 執行SQL 插入語句
stmt.executeUpdate(insertSQl);
// 執行完 停止執行語句
stmt.close();
// 執行完關閉數據庫連接
conn.close();
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}

/**
* 創建一個用於select查看數據的方法 executeQuery();
*
@param strSelect
*
@return ResultSet
*/
public ResultSet queryMySql(String strSelect) {
// 創建一個數據集 用於獲取查詢到的行數據
ResultSet rs = null;
try {
Class.forName(driver).newInstance();
} catch (Exception e) {
System.out.println("無法找到驅動器!");
e.printStackTrace();
}

try {
// 創建連接
conn = DriverManager.getConnection(url, user, password);
// 創建一個 Statement 對象來將 SQL 語句發送到數據庫
stmt = conn.createStatement();
// 執行查詢語句 獲取ResultSet對象
rs = stmt.executeQuery(strSelect);
} catch (SQLException e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
//返回結果集
return rs;
}
}

 

編寫客戶端

客戶端 Client 類包含了一個客戶端主函數,用於連接並訪問服務端.

通過在RMI注冊表上需找 服務端的地址 來獲取對服務端的連接和訪問 (詳細請看 代碼注釋).

Client類
package Client;

import java.rmi.Naming;
import java.util.List;
import java.util.Scanner;
import java.util.Vector;

import Remote_Interface.DataQueryInterface;
/**
 * Client 類 用於啟動客戶端  遠程連接並訪問 服務端
 * @author SoFlash - 博客園  http://www.cnblogs.com/longwu
 */
public class Client {
    /**
     * 客戶端上主函數 用於連接 並訪問服務端
     */
    public static void main(String[] args) {
        //定義一個端口號  該端口號必須與服務端的端口號相同 
        int port = 6666;
        //同樣定義一個遠程地址 該地址為服務端的遠程地址 所以 與服務端的地址是一樣的 
        String address = "rmi://localhost:" + port + "/RemoteQuery";

        try {
            //在RMI注冊表上需找 對象為DataQueryInterface的地址 
            //即服務端地址  - 因為服務端上DataQueryImpl類 實現了該接口的所有方法
            DataQueryInterface dqInterface = (DataQueryInterface) Naming
                    .lookup(address);
            
            //一旦客戶端找到該服務端地址 則 進行連接
            System.out.println("<<<客戶端訪問成功!");
            System.out.println("<<<開始查詢服務端!");
            System.out.println("---------------------------");
            while (true) {
                System.out.println("清空服務端上的數據庫-請按1");
                System.out.println("服務端收集英超比賽數據-請按2");
                System.out.println("查看英超所有球隊-請按3");
                System.out.println("查看具體球隊比賽結果-請按4");
                System.out.println("查看某一天的比賽-請按5");
                // Scanner 文本掃描器 用於讀取 用戶的輸入
                Scanner sc = new Scanner(System.in);
                int intInput = sc.nextInt();
                if (intInput == 1) {
                    try{
                    dqInterface.initialDataBase();
                    System.out.println("服務端上數據清空完畢!");
                    }catch(Exception e){
                        System.out.println("清空數據失敗!請檢查!");
                        System.out.println(e.getMessage());
                    }
                    
                    System.out
                            .println("---------------------------------------------");
                } else if (intInput == 2) {
                    System.out.println("服務端開始收集英超比賽數據,請稍等....");
                    System.out.println("------------------------------------");
                    try{
                        dqInterface.dataCollectAndStore();
                        System.out.println("服務端上數據收集成功! 按3,4,5查看相關");
                        }catch(Exception e){
                            System.out.println("服務端收集數據失敗!請檢查!");
                            System.out.println(e.getMessage());
                        }
                    System.out
                            .println("---------------------------------------------");
                } else if (intInput == 3) {
                    // 獲取 查詢到的所有球隊名稱
                    Vector<String> vecAllTeams = dqInterface.getAllTeams();
                    if (vecAllTeams.size() != 0) {
                        System.out.println("參加過比賽的球隊如下:");

                        System.out
                                .print("-----------------------------------------------\r\n");
                        for (int i = 0; i < vecAllTeams.size(); i++) {
                            if (i % 7 == 0 && i != 0) {
                                System.out.println("\r\n");
                            }
                            System.out.print(vecAllTeams.get(i) + "\t");
                        }
                    } else
                        System.out.print("服務端上數據庫目前沒有數據,請按2收集數據!");
                    System.out
                    .print("-----------------------------------------------\r\n");

                } else if (intInput == 4) {
                    System.out.println("請輸入你要查看的球隊");
                    Scanner scLeague = new Scanner(System.in);
                    String strLeague = scLeague.next();
                    // 獲取 具體球隊的比賽結果
                    Vector<String> lsResult = dqInterface
                            .querySpecifiedTeam(strLeague);
                    if (lsResult.size() != 0) {
                        System.out.println("日期\t\t\t主隊\t\t客隊\t\t比分");
                        for (int i = 0; i < lsResult.size(); i++) {
                            if (i % 4 == 0 && i != 0)
                                System.out.println();
                            System.out.print(lsResult.get(i) + "\t\t");
                        }
                    } else
                        System.out.println("服務端上沒有相關球隊的記錄或沒有數據!");
                    System.out
                            .println("\r\n---------------------------------------------------");
                } else if (intInput == 5) {
                    System.out.println("請輸入你要查看的比賽日期  例子格式[14.01.2012]");
                    Scanner scDate = new Scanner(System.in);
                    String strDate = scDate.next();
                    // 獲取具體日期下的 所有比賽
                    List<String> lsResulOnDate = dqInterface
                            .queryByDate(strDate);
                    if (lsResulOnDate.size() != 0) {
                        System.out.println("日期\t\t\t主隊\t\t客隊\t\t比分");
                        for (int i = 0; i < lsResulOnDate.size(); i++) {
                            if (i % 4 == 0 && i != 0)
                                System.out.println();
                            System.out.print(lsResulOnDate.get(i) + "\t\t");
                        }
                    } else
                        System.out.println("該天沒有比賽 或 服務端數據庫沒有數據!");
                    System.out
                            .println("\r\n---------------------------------------------------");
                }
            }
        } catch (Exception e) {
            System.out.println("遠程鏈接出錯,請檢查!");
            System.out.println(e.getMessage());
        }
    }

}

 

運行數據采集器

代碼寫好了, 我們來運行看看.

啟動服務端


啟動客戶端來連接服務端

 

輸入1 清空數據 服務端方 顯示 "數據庫清空成功!"

同時客戶端顯示 "服務端上數據清空完畢!"


輸入2 操作服務端插入數據

我們看到 大量的數據被成功插入到服務端上.

 

客戶端也最終 顯示 "服務端上數據收集成功!".

 

輸入3  在客戶端上查看服務端上收集到的所有球隊名稱.

 

輸入4選擇 按球隊查詢比賽結果,再輸入球隊名稱 查看到該球隊的比賽記錄. 這里查看的球隊是 NewCastle

 

輸入5 選擇按日期查看比賽結果,這里查看的日期是 03.01.2012

 

我們輸入1 清空下數據庫,檢測下是否真正清空.

 

輸入3 通過查看所有球隊名稱來檢測 是否數據庫里的數據已被清空.

 

這樣,我們的客戶端遠程訪問服務端就做好了. :)

這里我們的java網頁數據采集器教程也就告於段落了,如果對此感興趣的學友,可以訂閱本博客或是關注一下! 歡迎常來學習和討論. :) 

附上源代碼   htmlDataQuery_RemoteVisit.zip 

以及 jar文件 服務端htmlDataQuery_Server_jar.zip  客戶端 htmlDataQuery_Client_jar.zip

 

 

相關推薦 [點此查看目錄]

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM