如何通过本地客户端远程访问服务端进行数据采集,
优采云 发布时间: 2021-05-09 06:07如何通过本地客户端远程访问服务端进行数据采集,
在上一期中,我们在html页面采集之后学习了数据查询,但这仅是在本地查询数据库。如果我们想通过远程操作采集进行数据存储和查询,该怎么办?今天我们将一起学习:如何通过本地客户端远程访问服务器以执行数据存储和查询采集。
此问题概述
在上一期中,我们在html页面采集之后学习了数据查询,但这仅是在本地查询数据库。如果我们想通过远程操作采集进行数据存储和查询,该怎么办? ?
今天我们一起学习:如何通过本地客户端远程访问服务器以进行数据存储和查询采集。
数据采集页2011-2012赛季英超联赛记录
了解简单的远程访问(RMI示例)
首先,让我们学习一个客户端对服务器进行远程访问的简单示例。
此处使用Java RMI(远程方法调用)
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还继承了U优采云tRemoteObject远程对象。这必须写。尽管代码智能提示不会在未编写的情况下不会提示错误,但是服务器在启动后会莫名其妙地报告错误。
由于U优采云tRemoteObject远程对象需要引发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(">>服务端启动成功");
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();
}
}
}
内部的Data采集AndStorage类和dataCollectAndStore()方法用于采集和存储数据。
Data采集AndStorage类
<p>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})";
//创建 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方法 来剔除'