本期概述
上期我们学习了html页面采集后的数据查询, 但这仅仅是在本地查询数据库,如果我们想通过远程操作来进行数据的采集,存储和查询,那又该怎么做呢?
今天我们一起来学习下:如何通过本地客户端远程访问服务端进行数据的采集,存储和查询.
数据采集页面 2011-2012赛季英超球队战绩
学习简单远程访问(RMI实例)
首先我们学习下简单的客户端远程访问服务端的例子.
这里用到了 Java RMI (Remote Method Invocation)
Java RMI是一种机制, 是能够让一个 java虚拟机 调用 另一个java 虚拟机上对象的方法, 从而实现远程访问.
但是通过客户端实现该远程访问,必须绑定一个远程接口对象(意味着客户端可以访问到的服务端上的方法必须全部包含在这个接口里).
好了,我们来写下例子代码.
定义远程接口
首先,我们需要写个远程接口HelloInterface 该接口继承了远程对象Remote.
接口HelloInterface里面有个sayHello的方法,用于客户端连接后 打招呼.
由于sayHello方法继承了远程Remote对象, 所以需要抛一个 RemoteException 远程异常.
1
2
3
4
5
6
7
8
9
10
11
12
|
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() 来抛这个异常.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
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注册表上寻找远程接口对象的地址(服务端地址) 达到实现远程访问的目的,
所以,我们需要在 服务端 创建一个远程对象的注册表,用于绑定和注册 服务端地址 和 远程接口对象,便于后期客户端能够成功找到服务端 (详细请看代码注释).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
|
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格式
// 绑定远程地址和接口对象
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注册表上寻找 该地址; 如果找到 则建立连接.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
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 ;
// 同样定义一个远程地址 该地址为服务端的远程地址 所以 与服务端的地址是一样的
// 在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类里面实现.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
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类是包含了一个主函数 并且 绑定了远程接口对象(详细介绍 请看代码注释).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
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格式
//绑定远程地址和接口对象
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() 方法 用于收集和存储数据.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
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 sqlLeagues = "" ;
try
{
// 创建一个url对象来指向 该网站链接 括号里()装载的是该网站链接的路径
URL url = new
URL(strUrl);
// InputStreamReader 是一个输入流读取器 用于将读取的字节转换成字符
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 以及里面的所有方法 (具体请看代码及注释).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
|
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类 简单的数据结构 用于页面采集到的数据 临时性的存储.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
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 页面上需要的数据.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
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() 方法 用于查询数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
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 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注册表上需找 服务端的地址 来获取对服务端的连接和访问 (详细请看 代码注释).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
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 ;
//同样定义一个远程地址 该地址为服务端的远程地址 所以 与服务端的地址是一样的
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网页数据采集器教程也就告于段落了,如果对此感兴趣的学友,可以订阅本博客或是关注一下! 欢迎常来学习和讨论.
原文地址:http://www.cnblogs.com/longwu/archive/2012/01/21/2328710.html