摘 要
互联网发展至今,传统媒体已经日渐落寞,作为新生代媒体,网络已经在这一领域占据了越来越重要的地位,而且这种趋势还在上涨。现今,越来越多的人通过互联网来表达自己对社会现状的态度和政治诉求等等,从互联网这一自由开放的媒体中了解民生,开展网络舆情信息采集和分析,已经各级政府部门目前面临的重要课题。
互联网作为新生代媒体,其发展势头迅猛,各大门户网站纷纷进军互联网领域抢占市场,竞争十分激烈,而其中新浪在这场竞争中表现得相当出色,新浪微博民众信息分享平台的首选。本论文就设计了一个专门针对新浪微博的舆情数据采集系统,它包含如下几个功能:查询指定用户的微博信息、查询指定微博的评论信息和转发信息、查询指定用户的所有粉丝和搜索该用户的指定粉丝、查询指定用户的所有关注和搜索该用户的指定关注以及将上述信息保存到本地数据库中,供以后对数据进行分析。
该系统是基于新浪官方提供的API来开发的,采用Java和Mysql实现软件的开发,Java实现软件的界面和数据展示,Mysql实现数据的存储。工作时,它根据用户输入的信息,采用多线程方式去采集用户数据,主界面弹出等待提示框,给用户提供良好的用户体验。在展示数据的时候,考虑到微博数据的庞大,该系统采用了分页技术来展示数据,而且对界面进行了美化,给用户提供一个美观的界面浏览。
【关键词】网络舆情 新浪微博 Java Mysql 微博API
ABSTRACT
Since the development of Internet, traditional media has already lonely, as a new generation of media, the network has become more and more important in this field, and the trend is still rising. Nowadays, more and more people through the Internet to express themselves on the social status of the attitude and political appeal and so on, to understand the people's livelihood from the Internet which is a free and open media, network public opinion information collection and analysis, an important issue has been at all levels of government departments are currently facing.
Internet as a new generation of media, the momentum of rapid development, the major portals have to enter the field of Internet to seize the market, competition is very fierce, and Sina in this competition performed very well, Sina micro-blog public information sharing platform of choice. This thesis is to design a specific Sina micro-blog public opinion data acquisition system, which includes the following functions: query specifies the user's micro-blog, micro-blog information query specifies the comment information and forwarding information, query specifies the user all the fans and search the user specified fans, query specifies all of the user's attention and search the the specified user attention and the information is saved to a local database, for later data analysis.
The system is based on API to Sina official development, developed using Java and Mysql software, Java software interface and data display, Mysql data storage. When working, it according to the input information of a user, using multiple threads to collect user data, the main interface pops up wait for a prompt box, to provide users with a good user experience. In the display of the data when the micro-blog, considering the huge data, the system uses the paging technique to display data, and the interface is beautiful, to provide users with a beautiful interface to browse.
【Key words】Network public opinion Sina micro-blog Java Mysql Micro-blog API
毕业设计(论文)原创性声明和使用授权说明
原创性声明
本人郑重承诺:所呈交的毕业设计(论文),是我个人在指导教师的指导下进行的研究工作及取得的成果。尽我所知,除文中特别加以标注和致谢的地方外,不包含其他人或组织已经发表或公布过的研究成果,也不包含我为获得 及其它教育机构的学位或学历而使用过的材料。对本研究提供过帮助和做出过贡献的个人或集体,均已在文中作了明确的说明并表示了谢意。
作 者 签 名: 日 期:
指导教师签名: 日 期:
使用授权说明
本人完全了解 大学关于收集、保存、使用毕业设计(论文)的
规定
关于下班后关闭电源的规定党章中关于入党时间的规定公务员考核规定下载规定办法文件下载宁波关于闷顶的规定
,即:按照学校要求提交毕业设计(论文)的印刷本和电子版本;学校有权保存毕业设计(论文)的印刷本和电子版,并提供目录检索与阅览服务;学校可以采用影印、缩印、数字化或其它复制手段保存论文;在不以赢利为目的前提下,学校可以公布论文的部分或全部内容。
作者签名: 日 期:
学位论文原创性声明
本人郑重声明:所呈交的论文是本人在导师的指导下独立进行研究所取得的研究成果。除了文中特别加以标注引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写的成果作品。对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。本人完全意识到本声明的法律后果由本人承担。
作者签名:
日期: 年 月 日
学位论文版权使用授权书
本学位论文作者完全了解学校有关保留、使用学位论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。本人授权 大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。
涉密论文按学校规定处理。
作者签名:
日期: 年 月 日
导师签名: 日期: 年 月 日
目 录
1前 言
3第一章 系统相关技术概述
3第一节 Java技术概述
3一、Java简要介绍
3二、GUI图形用户界面
4三、多线程
4四、JDBC数据库连接
5第二节 新浪微博Java SDK
5一、微博Java SDK概述
5二、授权认证
6第三节 Mysql技术概述
6一、Mysql概述
6二、Mysql的特性
7第四节 本章小结
8第二章 需求分析
8第一节 系统功能需求
8一、系统目标
8二、功能分析
9三、系统层次模块图
10第二节 系统性能要求
10第三节 运行环境
11第四节 系统用例图
11第五节 本章小结
12第三章 系统设计
12第一节 系统结构分析
12一、系统结构图
13第二节 系统功能模块分析
13一、系统模块设计
13二、各子功能模块分析
14第三节 系统数据库设计
14一、系统数据库对象
14二、系统数据表
17第四节 系统各模块设计
17一、启动模块的设计
19二、查看微博的设计
21三、查看粉丝的设计
23四、查看关注的设计
24五、查看评论的设计
25六、查看转发的设计
27第五节 本章小结
28第四章 系统实现
28第一节 开发环境的搭建
28一、Java开发环境的搭建
30二、数据库环境的搭建
30第二节 各功能模块的具体实现
31一、授权认证的实现
32二、启动模块的实现
32三、查看微博的实现
39四、查看粉丝的实现
41五、查看关注的实现
42六、查看评论的实现
43七、查看转发的实现
45第五章 系统效果展示
45一、主界面效果展示
46二、查看微博的效果展示
46三、查看粉丝的效果展示
47四、查看关注的效果展示
48五、查看评论的效果展示
49六、查看转发的效果展示
50结 论
51致 谢
52参考文献
53附 录
53一、英文原文:
59二、英文翻译:
前 言
截至目前,国内关于网络舆情的概念还没有一个统一的定义,来自天津社科院的王来华认为:舆情在其狭义上是指民众受中介性社会事项,刺激而产生的社会政治态度;而网络舆情,则主要指使用网络者或俗称“网民”的社会政治态度[1]。我个人也比较认同王来华教授的观点。网络舆情形成迅速,对社会影响巨大。随着因特网在全球范围内的飞速发展,网络媒体已被公认为是继报纸、广播、电视之后的“第四媒体”,网络成为反映社会舆情的主要载体之一。网络环境下的舆情信息的主要来源有:新闻评论、BBS、博客、微博。网络舆情表达快捷、信息多元,方式互动,具备传统媒体无法比拟的优势。在我国,网民以往都是呈原子状态的个体分散在全国各区域,而如今,一个由“网络化用户”构成的“网众”群体已悄然崛起,并以数以亿计的庞大用户群体构成了一个“压力集团”,截至目前,这个集团的数量与力量还呈现出上升的态势[2]。
结合网络舆情的特性和我国的基本国情,网民通过互联网来表达自己的观点诉求已成为我国公民参与政治生活的重要部分。当某一社会事件被迅速关注进而升温成为社会焦点或公共性事件时,国内网民便纷纷通过微博、BBS、新闻等形式发表自己的看法。那么,站在政府的角度上,由数量庞大的“网众”聚集的舆论压力和行动力量是不容忽视的,这些舆论已经不再局限于言论范畴的“说”,而是转化为社会行动范畴内的“做”了。正是基于这样的形式,网络舆情数据采集分析成为各级政府部门面临的不可或缺的重要课题。
经过这几年发展,新浪微博[3]在国内社交平台市场的竞争中算是领先一步,他占据了大部分用户群体。结合国内对舆情信息的采集分析工作的迫切需求,本文的作品就设计了一个专门针对新浪微博的舆情数据采集系统,它包含如下几个功能:查询指定用户的微博信息、查询指定微博的评论信息和转发信息、查询指定用户的所有粉丝和搜索该用户的指定粉丝、查询指定用户的所有关注和搜索该用户的指定关注;该作品不仅给用户做了数据的展现,还实现了数据的存储,每次查询的用户信息、微博信息等等都被永久的存储在本地数据库中。舆情数据采集是舆情信息监控的基础,所以本系统还是存在很重要的意义的。另外,对政府部门来说,他们可以通过研究这些舆情数据,就能了解民众的政治态度,民众的需求,只有更彻底的了解民生,才能更好的制定政策,为人民服务;对于各商家来说,他们可以通过对这些舆情数据的研究,了解消费者对他们产品的评价,就能有针对性的对产品进行改善,这样既能提升产品的质量,获得消费者的信赖,又能增加收益,达到双赢的目的;对于研究所来说,他们可以对这些数据进行数据挖掘,实现其相应的价值。
第一章 系统相关技术概述
第一节 Java技术概述
一、Java简要介绍
Java由Sun Microsystems公司于1995年5月推出的一门面向对象的程序设计语言,用它编写的应用程序具有跨平台的特征。Java框架下包含三大平台:JavaSE、JavaEE和 JavaME。JavaSE是Java平台标准版的简称,用于开发服务器、桌面和嵌入式设备中的Java应用程序;JavaEE一种用来简化企业解决
方案
气瓶 现场处置方案 .pdf气瓶 现场处置方案 .doc见习基地管理方案.doc关于群访事件的化解方案建筑工地扬尘治理专项方案下载
的开发、部署和管理相关的复杂问题的体系结构,JavaEE的基础是JavaSE;JavaME是一个用来为移动平台提供的基于Java环境开发的技术
规范
编程规范下载gsp规范下载钢格栅规范下载警徽规范下载建设厅规范下载
的集合。Java技术凭借着它的高效性、安全性、通用性和平台移植性,目前被广泛应用于个人PC、移动电话、科学超级计算机、游戏控制台和互联网等领域。在全球云计算和移动互联网的产业环境下,Java[4]更具备了显著优势和广阔前景。
二、GUI图形用户界面
随着互联网的飞速发展,Java 技术也得到了越来越广泛的应用。而无论我们是采用 JavaSE、JavaEE 还是 JavaME开发,图形用户界面都是我们不能逃避的问题。现在的用户总希望我们开发的软件功能丰富强大而又操作简单,这就需要开发者注重界面的友好性,GUI就成了Java开发者不可或缺的重要课题。Java使用AWT和Swing类库来完成图形用户界面的编程,其中AWT的全称是抽象窗口工具集(Abstract Window Toolkit),它是Sun公司最早提供的GUI库,这个GUI库提供了一些基本功能,但这个GUI库的功能比较有限,所以后来又提供了Swing库[5]。Java开发者通过使用AWT和Swing提供的组件库,程序只需创建所需的图形组件,并用合适的布局管理器来组织这些组件按照特定的方式排列,就可以开发出非常完美的用户界面。如果想要实现用户与界面之间的交互,开发者还应为程序添加事件监听,让事件处理来完成响应用户动作。本论文作品主要用到了Swing库中的JButton、JLable、JTextField、JTable、JScrollPanel、JFrame、JPanel等组件,用到了AWT库中的BorderLayout、FlowLayout等布局管理器组件。
三、多线程
多线程是Java的一大特色,那么什么是多线程呢,下面用一个简单的例子来解释:我们可以在操作系统中同时运行多个任务,一个任务就是一个程序,每个运行中的程序我们称为一个进程,在这个程序运行时,内部可能包含了多个顺序执行流,每个顺序执行流就是一个线程。既然有多线程,那么必然会有单线程,所谓单线程就是说程序内部只有一条顺序执行流;则多线程就可以理解为程序内部有多条顺序执行流,而且多个顺序执行流之间互不干扰。Java的多线程有两种实现方式:继承Thread类和实现Runnable接口。本论文作品的多线程体现在给用户良好的用户体验方面:当用户点击一项功能时,如果该功能是一项很费时的操作,那么程序就会单开一个线程去完成这个费时的操作,主线程弹出用户等待提示框,当操作完成时,提示框自动消失。
四、JDBC数据库连接
JDBC[6]是Java连接数据库的一项技术,它是用来执行SQL语句的Java API,它的全称是Java Database Connectivity。通过使用JDBC API,Java程序可以非常方便的操作各种主流数据库,由于Java语言的跨平台特性,所以使用JDBC API所编写的程序不仅可以实现跨数据库,还可以跨平台,具有非常优秀的可移植性。JDBC连接数据库的步骤如下(以Mysql数据库为例):
① 加载JDBC驱动程序
Class.forName(com.mysql.jdbc.Driver);
② 创建数据库连接
String url = "jdbc:mysql://127.0.0.1:3306/weibo_sina";
String user = "root";
String password = "123456";
Connection ct = null;
ct = DriverManager.getConnection(url, user, password);
③ 预编译并执行SQL语句
PreparedStatement ps = null;
ps = ct.prepareStatement(sql);
ps.executeUpdate();
④ 关闭JDBC对象
public void close() {
try {
if (rs != null)
rs.close();
if (ps != null)
ps.close();
if (ct != null)
ct.close();
} catch (Exception e) {
e.printStackTrace();
}
}
本论文作品主要通过Mysql数据库来存储获取的微博、用户等信息。
第二节 新浪微博Java SDK
一、微博Java SDK概述
微博Java SDK是新浪为Java开发者提供的专门用于访问新浪微博的接口,通过微博Java SDK,第三方微博应用可以很方便的访问微博提供的API接口,获取到需要的信息。微博Java SDK的整体架构包含如下几个:
① src:weibo4j封装了大部分接口,包括授权,timeline,用户等常见接口
weibo4j.http包含了https请求的封装
weibo4j.model包含了user,status等实体类
weibo4j.org.json 完成json解析的各种方法
weibo4j.util 包含了请求api接口时候所需要的工具类
② examples:里面包含了封装接口的各个测试demo
二、授权认证
要调用新浪微博SDK就需要先完成授权认证,只有授权的应用才有资格去访问微博的API。授权认证[7]的步骤如下:
① 注册应用。要调用新浪微博API,就需要先到新浪微博开放平台去注册并创建一个应用,地址是:http://open.weibo.com/development。新浪官方会给每一个应用一个专属的App Key和App Secret。Key跟Secret的使用方式跟其他一些
协议
离婚协议模板下载合伙人协议 下载渠道分销协议免费下载敬业协议下载授课协议下载
中的公钥私钥的方案相类似,你可以使用你所熟悉的编程语言将key和secret结合,为你发出的每个请求添加签名,以此来向新浪微博开放平台表明自己身份的合法性。
② 填写配置文件。到config.properties文件中填写好client_ID、client_SERCRET和redirect_URI三个参数,他们分别填写你的应用的App Key、App Secret和回调地址。
③ 获取code参数。运行OAUTH4CODE类,获取code,即用户授权登陆后,地址栏上出现的code。
④ 通过code换取access_token。获取到access_token后,表示我们的应用已经授权成功,我们就可以通过access_token来访问新浪微博API的接口。
第三节 Mysql技术概述
一、Mysql概述
MySQL[8]是一个小型关系型数据库管理系统,开发者为瑞典MySQL AB公司,现已被Oracle公司收购。Mysql与目前市场上的其他大型数据库(Oracle、DB2、SQL Server)相比,存在功能小、规模有限等不足。但这些不足丝毫没有减少它的受欢迎度,相反,这些不足反而成就了它小巧、查询快捷、健壮易用的优点,让Mysql成为了目前大多数中小型企业的首选,由于Mysql是一款开源软件,这个可以大大降低企业的开销成本,这一特点也是Mysql如此受欢迎的原因之一。
二、Mysql的特性
MySQL作为一个小型关系型数据库管理系统,它有如下特性来让用户选择它作为自己应用的数据库:
① 使用C和C++编写,并使用了多种编译器进行测试,保证源代码的可移植性;
② 支持AIX、FreeBSD、HP-UX、Linux、Mac OS、Novell Netware、OpenBSD、OS/2 Wrap、Solaris、Windows等多种操作系统 ;
③ 为多种编程语言提供了API。这些编程语言包括C、C++、Eiffel、Java、Perl、PHP、Python、Ruby和Tcl等;
④ 支持多线程,充分利用CPU资源;
⑤ 优化的SQL查询算法,有效地提高查询速度;
⑥ 既能够作为一个单独的应用程序应用在客户端服务器网络环境中,也能够作为一个库而嵌入到其他的软件中提供多语言支持,常见的编码如中文的GB 2312、BIG5,日文的Shift_JIS等都可以用作数据表名和数据列名 ;
⑦ 提供TCP/IP、ODBC和JDBC等多种数据库连接途径 ;
⑧ 提供用于管理、检查、优化数据库操作的管理工具;
⑨ 可以处理拥有上千万条记录的大型数据库;
第四节 本章小结
在本章中,主要对网络舆情数据采集系统开发涉及到的技术理论知识进行了基本介绍,其中主要介绍了Java中的GUI图形用户界面的实现机制,JDBC数据库连接原理和步骤、Java多线程的原理和实现方式、新浪微博Java SDK的概述和授权步骤,最后对Mysql数据库进行了简要的介绍。
第二章 需求分析
需求分析工作是软件工程[9]生命周期中的第一步,也是起决定性的一步,在需求分析阶段我们需要全面了解整个系统的功能和性能方面的要求,为软件设计打下坚实的基础。需求分析阶段的目标主要有:获得目标系统的物理模型,了解目标系统的运行原理及机制;抽象出目标系统的逻辑模型,对物理模型进行筛选,得到与软件系统有关的部分;建立目标系统的逻辑模型,得出数据流图和数据字典;补充目标系统的逻辑模型,对目标系统的用户界面、至今尚未考虑的细节进行说明。
第一节 系统功能需求
一、系统目标
网络舆情很客观的反应民众的需求与政治态度,政府迫切需要了解舆情,正式基于这样的需求,本系统应运而生,完成微博信息的收集并实现数据的展示功能,为后面的舆情分析打下基础。
二、功能分析
开发软件首先做的是开发过程中最主要的就是系统的需求分析[10],需求分析同时也是软件生存周期中关键的一步。根据软件工程学中开发软件的要求,对系统全部功能和相关的技术进行具体的分析,分析时采用结构化的分析方法,自顶向下、逐层分解问题。结合政府需求和实际的具体分析,要求本系统具有以下功能:
① 查看用户的微博
根据用户输入的微博用户昵称关键字,系统单开一个线程向新浪服务器发出用户微博查询请求,系统解析服务器返回的结果,然后系统将返回的微博信息分页显示。
② 查看用户的粉丝
根据用户输入的微博用户昵称关键字,系统单开一个线程向新浪服务器发出用户粉丝查询请求,系统解析服务器返回的结果,然后系统将返回的粉丝信息分页显示。
③ 搜索指定用户粉丝
在查看用户粉丝的时候,有些用户粉丝可能特别多,分页后就会存在很多页,那么就会很难找某个具体的粉丝。鉴于这种情况,本系统就特定做了一个粉丝搜索功能,搜索出包含用户输入的关键字的粉丝展示出来。
④ 查看用户的关注
根据用户输入的微博用户昵称关键字,系统单开一个线程向新浪服务器发出用户关注查询请求,系统解析服务器返回的结果,然后系统将返回的关注信息分页显示。
⑤ 搜索指定用户关注
在查看用户关注的时候,有些用户关注的人可能特别多,分页后就会存在很多页,那么就会很难找某个具体的关注。鉴于这种情况,本系统就特定做了一个关注搜索功能,搜索出包含用户输入的关键字的关注展示出来。
⑥ 查看微博的转发情况
根据用户点击的微博id,系统单开一个线程向新浪服务器发出微博转发情况查询请求,系统解析服务器返回的结果,然后系统将返回的微博转发信息分页显示。
⑦ 查看微博的评论情况
根据用户点击的微博id,系统单开一个线程向新浪服务器发出微博评论情况查询请求,系统解析服务器返回的结果,然后系统将返回的微博评论信息分页显示。
⑧ 存储微博、用户、关系、评论、转发信息
在上述功能中获取到服务器返回的信息解析后就需要把这些信息存储起来,本系统是采用Mysql数据库来存储这些信息。
三、系统层次模块图
本系统总的结构模块包括:用户微博查看、用户粉丝查看、用户关注查看,每个模块下面又包括具体的某些功能,详细的系统模块功能如图2.1所示:
图2.1系统层次模块图
第二节 系统性能要求
本系统的性能要求如下:
① 安全性。该系统涉及到用户的个人信息,所以要求该系统具备较强的安全性,对用户的信息进行保护。
② 稳定性。系统应该在一般情况下稳定运行。
第三节 运行环境
本系统对运行环境的要求如下:
硬件环境:
① CPU:Intel(R) Core(TM)2 1.73GHz
② 内存:2G
③ 硬盘:100G
④ 显卡:128MB独立显卡
软件环境:
① 操作系统:Windows XP、Windows 7、Windows 8
② 数据库:Mysql 5.5
③ 相关应用软件:JDK、Eclipse
第四节 系统用例图
系统用例图[11]如图2.2所示:
图2.2 系统数据流图
第五节 本章小结
在本章中,主要是在开发网络舆情数据采集系统之前对该系统进行了需求分析,其中主要介绍了该系统的开发目标、功能需求、系统的性能要求、运行环境、系统的层次结构、系统的用例图等。当我们做好系统的需求分析后,就能对该系统做总体设计了。
第三章 系统设计
软件的需求分析做好后,就可以根据用户需求分析阶段得到的目标系统的逻辑模型确定一个合理的软件系统的体系结构。包括划分组成系统的模块,模块间的调用关系及模块间的接口关系,软件系统所用的数据结构或者数据库结构。在概要设计的基础上,开发者需要进行软件系统的详细设计。在详细设计[12]中,描述实现具体模块所涉及到的主要算法、数据结构、类的层次结构及调用关系,需要说明软件系统各个层次中的每一个程序(每个模块或子程序)的设计考虑,以便进行编码和测试。应当保证软件的需求完全分配给整个软件。
第一节 系统结构分析
目前企业开发软件主要采用两种模式:B/S模式和C/S模式。B/S模式即为浏览器/服务器(Browser/Server)模式,这种模式的优点体现在平台稳定,业务扩展、系统升级简单方便,开发成本低廉等。C/S模式即为客户端/服务器(Client/Server)模式,这种模式的优点体现在具有强壮的数据操纵和事务处理能力、数据的完全性和完整性约束等。根据B/S和C/S模式的各自特点,并结合该系统的特点(该系统主要面向新浪微博,从新浪服务器获取数据来处理),因此选择C/S模式比较合适。
一、系统结构图
本系统的结构图如图3.1所示:
图3.1 系统结构图
第二节 系统功能模块分析
一、系统模块设计
系统模块设计如表3.1所示:
表3.1 系统模块设计表
功能名称
输入项
输出项
执行方式
功能描述
查看微博
用户输入的微博用户昵称
该用户的所有微博
后台运行
查看指定用户的所有微博信息
查看粉丝
用户输入的微博用户昵称
该用户的所有粉丝
后台运行
查看指定用户的所有粉丝信息
查看关注
用户输入的微博用户昵称
该用户的所有关注
后台运行
查看指定用户的所有关注信息
查看评论
用户选择的微博id
这条微博的所有评论
后台运行
查看指定微博的所有评论信息
查看转发
用户选择的微博id
这条微博的所有转发
后台运行
查看指定微博的所有转发信息
二、各子功能模块分析
网络舆情数据采集系统涉及到微博和用户两个实体:微博和用户。在确立了系统的总体功能后,便可以设计各个子模块的功能。
① 系统根据用户昵称查出用户微博列表后,还可以查看每一条微博的评论和转发信息。微博模块的功能模块如图3.2所示:
图3.2 微博子模块功能图
② 系统根据用户昵称查出用户粉丝、关注列表,或者搜索用户后,可以查询每一个人微博用户的微博信息。用户子模块的功能如图3.3所示:
图3.3 用户子模块功能图
第三节 系统数据库设计
一、系统数据库对象
网络舆情数据采集系统主要涉及的对象有:微博、用户、评论、转发。那么,该系统的数据库[13]对象就可以主要分为:微博表、用户表、关系表、评论表、转发表。该系统的数据库表设计如表3.2所示:
表3.2 系统数据库对象表
名称
类型
说明
User
基本表
存储微博用户的基本信息
Weibo
基本表
存储微博的基本信息
Friendship
基本表
存储微博用户之间的关系信息(关注)
Comment
基本表
存储微博的评论信息
Repost
基本表
存储微博的转发信息
二、系统数据表
网络舆情数据系统主要有5张表:微博表、用户表、关系表、评论表和转发表[14],每张表的具体字段如下:
① 微博表,用来保存新浪微博的微博信息。包含微博id、微博内容、发布时间等字段,其中主键是微博id,user_id是关联用户表的外键。微博表的详细设计表如表3.3所示:
表3.3 微博表详细
字段列名
字段类型
字段大小
字段说明
id
varchar
50
微博id
mid
varchar
50
微博MID
text
varchar
5000
微博内容
createdAt
varchar
100
创建时间
repostsCount
int
转发数
commentsCount
int
评论数
user_id
varchar
50
发布者id
② 用户表,用来保存微博的用户信息。包含用户id、用户昵称、用户注册时间等字段,其中用户id是主键。用户表的详细设计表如表3.4所示:
表3.4 用户表详细
字段列名
字段类型
字段大小
字段说明
id
varchar
50
用户id
screenName
varchar
50
用户昵称
province
int
省份编码(参考省份编码表)
city
int
城市编码(参考城市编码表)
location
varchar
100
地址
description
varchar
500
个人描述
url
varchar
100
用户博客地址
profileImageUrl
varchar
1000
自定义图像
userDomain
varchar
100
用户个性化URL
gender
varchar
5
性别,m-- 男,f-- 女,n-- 未知
followersCount
int
粉丝数
friendsCount
int
关注数
statusesCount
int
微博数
favouritesCount
int
收藏数
biFollowersCount
int
互粉数
createdAt
varchar
100
创建时间
③ 关系表,用来保存微博用户之间的关注信息。里面主要包含两个用户的id,主键是两个id的组合键,两个id分别关联到用户表,关系表的详细设计表如表3.5所示:
表3.5 关系表详细
字段列名
字段类型
字段大小
字段说明
user_id
varchar
50
A用户id
f_user_id
varchar
50
B用户id(A关注B)
④ 评论表,用来保存某一条微博的评论信息。里面主要包含评论id、评论内容、评论时间等字段,其中评论id是主键,微博id关联到微博表,用户id关联到用户表,评论表的详细设计表如表3.6所示:
表3.6 评论表详细
字段列名
字段类型
字段大小
字段说明
id
varchar
50
评论id
text
varchar
500
评论内容
createdAt
varchar
100
评论时间
weibo_id
varchar
50
被评论的微博id
user_id
varchar
50
评论者的用户id
⑤ 转发表,用来保存某一条微博的转发信息。里面主要包含转发id、转发内容、转发时间等字段,其中转发id是主键,微博id关联到微博表,用户id关联到用户表,转发表的详细设计表如表3.7所示:
表3.7 转发表详细
字段列名
字段类型
字段大小
字段说明
id
varchar
50
转发微博id
mid
varchar
50
转发微博MID
text
varchar
5000
转发微博内容
createdAt
varchar
100
转发时间
weibo_id
varchar
50
被转发的微博id
user_id
varchar
50
转发者id
第四节 系统各模块设计
既然分析好了各功能模块的具体功能,又设计好了数据库,接下来我们就来做每个功能模块的详细设计。
一、启动模块的设计
① Home.java是该系统的启动界面,也是系统的主界面,该类主要定义了界面的组件,以及生成界面的方法,具体的类图如图3.5所示:
图3.5 主界面类图
② User_.java定义了一个用户对象,代表一个注册的新浪微博用户。里面包含了用户id、用户昵称、用户性别、用户描述、用户微博数、粉丝数、关注数、注册时间等信息。具体的用户信息见图3.6:
图3.6 用户对象类图
二、查看微博的设计
① Status_.java定义了一个微博对象,包括微博id、微博内容、发布时间、评论数、转发数、发布者信息等。具体结构见图3.7:
图3.7 微博对象类图
② WeiboGrab.java是一个抓取微博类,该类主要用来调用新浪API[15]获取指定用户的微博列表,具体的类图见图3.8:
图3.8 抓取微博信息类类图
③ WeiboTable.java是用来处理微博数据,把这些数据生成列表视图,并带有分页功能,里面还带有对Java列表界面的修改,生成美观的外表。具体的类图如图3.9所示:
图3.9 微博列表生成类类图
三、查看粉丝的设计
① FollowerTable.java是用来处理粉丝数据,把这些数据生成列表视图,并带有分页功能,里面还带有对Java列表界面的修改,生成美观的外表。具体的类图如图3.10所示:
图3.10 粉丝列表生成类类图
② FollowerGrab.java是一个抓取粉丝类,该类主要用来调用新浪API获取指定用户的粉丝列表,具体的类图见图3.11:
图3.11 粉丝抓取类类图
③ SearchFollower.java是一个搜索粉丝的类,该类主要用来搜索某个用户的所有粉丝中某个具体的粉丝,具体的类图见图3.12:
图3.12 粉丝搜索类
四、查看关注的设计
① FriendTable.java是用来处理关注数据,把这些数据生成列表视图,并带有分页功能,里面还带有对Java列表界面的修改,生成美观的外表。具体的类图如图3.13所示:
图3.13 关注列表生成类类图
② FriendGrab.java是一个抓取关注类,该类主要用来调用新浪API获取指定用户的关注列表,具体的类图见图3.14:
图3.14 关注抓取类类图
③ SearchFriend.java是一个搜索关注的类,该类主要用来搜索某个用户的所有关注中某个具体的关注,具体的类图见图3.15:
图3.15 关注搜索类
五、查看评论的设计
① CommentTable.java是用来处理评论数据,把这些数据生成列表视图,并带有分页功能,里面还带有对Java列表界面的修改,生成美观的外表。具体的类图如图3.16所示:
图3.16 评论列表生成类类图
② CommentGrab.java是一个抓取微博的评论列表类,该类主要用来调用新浪API获取某条指定微博的所有评论列表,具体的类图见图3.17:
图3.17 评论抓取类类图
③ CommentView.java是微博的评论显示界面,他用来把某条具体微博的所有评论信息分页显,里面还带有对Java列表界面的修改,生成美观的外表。具体的类图如图3.18所示:
图 3.18 评论列表显示类类图
六、查看转发的设计
① RepostTable.java是用来处理转发数据,把这些数据生成列表视图,并带有分页功能,里面还带有对Java列表界面的修改,生成美观的外表。具体的类图如图3.19所示:
图3.19 转发列表生成类类图
② RepostGrab.java是一个抓取微博转发情况的类,该类主要用来调用新浪API获取指定指定微博的转发列表,具体的类图见图3.20:
图3.20 转发抓取类类图
③ RepostView.java是微博的转发显示界面,他用来把某条具体微博的所有转发信息分页显,里面还带有对Java列表界面的修改,生成美观的外表。具体的类图如图3.21所示:
图 3.21 转发列表显示类类图
第五节 本章小结
在本章中,是在网络舆情数据采集系统的需求分析基础上,对该系统做了一个系统设计,包括总体设计和详细设计,确定了一个合理的软件系统的体系结构,并设计了体系结构下各模块的具体数据结构。其中主要介绍了该系统的系统结构、系统模块划分、各自模块具体功能,以及该系统数据库表的确立,还设计好了查看微博、查看粉丝、查看关注、查看评论、查看转发模块的具体数据结构,当我们做好系统设计工作后,接下就该对系统做具体实现了。
第四章 系统实现
在前面阶段已经确定好了各模块的数据结构、算法分析和模块实现等方面的设计要求,现在就可以开始做编码工作了,分别实现各模块的功能,从而实现对目标系统的功能、性能、接口、界面等方面的要求。
第一节 开发环境的搭建
在开始做具体的编码工作之前,我们必须的搭建好开发环境,本系统的开发环境比较简单,只需要搭建Java开发环境、数据库开发环境就行了。
一、Java开发环境的搭建
1、JDK环境变量的配置
安装好JDK后,我们必须得进行环境变量的配置,其配置步骤如下:
① 编辑Path变量,在变量值中加入值:D:\programe files\Java\jsk1.7.0_09\bin。一般把这个值加到原有值得最前面并用分号隔开,这样配置后你在任何路径下编写的Java程序都能调用到jdk的javac和java等命令。效果图如图4.1所示:
图4.1 配置path变量图
②编辑classpath环境变量,其中设置值为:.;D:\program files\Java\jdk1.7.0_09\lib\dt.jar;D:\program files\Java\jdk1.7.0_09\lib\tools.jar。效果图如图4.2所示:
图4.2 配置classpath变量图
③ 测试是否配置成功,打开命令提示符,然后输入javac/java –version等命令,回车正常输出信息就表示配置成功。效果如图4.3所示:
图4.3 测试是否配置成功图
2、Eclipse的安装
配置好JDK环境变量后,我们还需要一款集成开发环境工具,方便我们快捷高效的开发,Eclipse就是这样一款软件,目前,Eclipse是大多数软件开发企业的首选开发工具。Eclipse的安装非常方便,我们只需要去官网下载压缩包,然后解压运行即可。Eclipse的软件界面如图4.4所示:
图4.4 eclipse的开发界面
二、数据库环境的搭建
安装数据库之前得先去Mysql官网下载安装文件,然后安装,安装过程中得注意自己设置的密码和端口号,mysql服务器默认的端口号是3306,我设置的root用户密码是123456。数据库安装好之后还需要安装一款图形界面的数据库管理工具,本人推荐使用Navicat,Navicat的应用界面如图4.5所示:
图4.5 navicat应用界面
第二节 各功能模块的具体实现
一、授权认证的实现
① 注册应用。到新浪微博开放平台去注册并创建一个应用,地址是:http://open.weibo.com/development。新浪官方会给每一个应用一个专属的App Key和App Secret。我事先已经注册了应用并获得了App Key和App Secret,如图4.6所示:
图4.6 应用基本信息
② 下载SDK。到新浪官方下载各种开发语言对应的SDK版本,下载地址:http://open.weibo.com/wiki/SDK。我是用Java语言开发的应用,所以下载的是Java版本的SDK。
③ 填写配置文件。把下载得SDK导入到项目中去,找到config.properties文件,打开并填写好其中的client_ID、client_SERCRET和redirect_URI三个参数,他们分别填写你的应用的App Key、App Secret和回调地址。代码如下:
client_ID=3002009818
client_SERCRET=a6a0f2f9883151611365504c45e8a2a5
redirect_URI=http://www.csdn.net/
④ 获取code参数。运行OAuth4Code.java类,获取code,即用户授权登陆后,地址栏上出现的code。这里需要注意一下,我们需要在原代码上稍加修改,后则运行会报错,修改后的代码如下:
Oauth oauth = new Oauth();
BareBonesBrowserLaunch.openURL(oauth.authorize("code"));
System.out.println(oauth.authorize("code"));
运行代码后会弹出一个浏览器网页:http://www.csdn.net/?code=*******。记录下网址中的code=后的代码。
⑤ 通过code换取access_token。获取到code后,接下来把code复制到控制台中,然后点击Enter键,会输入一些信息,记录下其中的access_token。获取到access_token后,表示我们的应用已经授权成功,我们就可以通过access_token来访问新浪微博API的接口。
二、启动模块的实现
启动模块主要就是应用程序的启动界面,后面的大部分功能都是在该界面完成展示的,该界面主要包括功能按钮区和数据展示区两部分,实现过程中涉及到的关键技术是:“设置该应用程序的背景图和图标”。JFrame是由这么几部分组成:最底下一层JRootPane,上面是glassPane(一个JPanel)和layeredPane(一个JLayeredPane),而layeredPane又由contentPane(一个JPanel)和menuBar构成。要在JFrame上添加背景图片,常见做法是加在layeredPane上面,并将contentPane设置成透明的即可。下面就是实现的关键代码:
// 给JFrame添加背景图片
ImageIcon imageBg = new ImageIcon("images/bg_panel_center.jpg");
JLabel bg = new JLabel(imageBg);
this.getLayeredPane().add(bg, new Integer(Integer.MIN_VALUE));
// 注意这里是关键,将背景标签添加到JFrame的LayeredPane面板里
bg.setBounds(0, 0, 1000, 600); // 设置背景标签的位置
Container cp = this.getContentPane();
((JPanel) cp).setOpaque(false);
// 注意这里,将内容面板设为透明,这样LayeredPane面板中的背景才能显示出来。
// 设置应用程序图标
BufferedImage imageIcon = ImageIO.read(new File("images/icon.png"));
this.setIconImage(imageIcon);
三、查看微博的实现
查看微博模块的实现过程就是:用户输入一个微博昵称,然后点击查看微博,系统就会去访问新浪微博服务器,得到该用户的所有微博,然后系统将这些微博以列表形式分页展示出来。
在访问新浪服务器的过程是一项非常耗时的工作,如果不采取一些措施,让用户一直等待访问结果,会给用户造成不好的用户体验。所有,本系统采用多线程方式,在访问服务器的时候弹出进度条框,让用户知道正在进行后台数据的处理。这项技术的实现过程是:访问服务器时,单开一条线程去获取数据,又开一个线程弹出提示框,在提示线程里面又有个监视线程,用来监视两个线程的工作情况,当获取数据线程完成工作后,立马关闭提示框线程。
在这个模块的实现过程中涉及到的关键技术有:数据列表样式的设置、分页的实现、提示框的实现和访问微博列表的实现。下面逐一说明它们的关键代码:
① 数据列表样式的设置
//设置
表格
关于规范使用各类表格的通知入职表格免费下载关于主播时间做一个表格详细英语字母大小写表格下载简历表格模板下载
的外观
public void settingTable(DefaultTableModel model) {
this.setModel(model);
this.setRowHeight(30);
// 设置表头的背景色
this.getTableHeader().setBackground(new Color(200, 200, 200));
// 设置表头的文字颜色
this.getTableHeader().setForeground(new Color(0, 0, 0));
this.getTableHeader().setFont(new Font("宋体", Font.BOLD, 14));
this.setFont(new Font("宋体", Font.PLAIN, 14));
this.setOpaque(false);
DefaultTableCellRenderer render = new DefaultTableCellRenderer();
render.setForeground(java.awt.Color.ORANGE);
render.setOpaque(false);
render.setHorizontalAlignment(JLabel.CENTER);
this.setDefaultRenderer(Object.class, render);
// 向单元格中添加按钮
this.getColumnModel().getColumn(6).setCellEditor(new ButtonEditor(this));
this.getColumnModel().getColumn(6).setCellRenderer(new ButtonRender());
this.getColumnModel().getColumn(7).setCellEditor(new ButtonEditor(this));
this.getColumnModel().getColumn(7).setCellRenderer(new ButtonRender());
this.setRowSelectionAllowed(false);
this.setColumnModel(getColumn(this, width));
}
② 分页的实现
// JTable表分页信息相关变量
public int currentPage = 1;
public int pageCount = Config.pageCount;
public int totalPage = 0;
public int totalRowCount = 0;
public int column = 0;
public int restCount;
public Object[][] resultData;
// JTable表信息相关变量
public List
status = Status_.status;
public WeiboTableModel model = null;
// 获取下一页
public int getNextPage() {
if (this.currentPage != this.totalPage) {
return ++currentPage;
}
return -1;
}
// 获取上一页
public int getPreviousPage() {
if (this.currentPage != 1) {
return --currentPage;
}
return -1;
}
// 获取总页数
public int getTotolPage() {
return this.totalPage;
}
// 获取当前页
public int getCurrentPage() {
return this.currentPage;
}
// 获得原始数据集
public Object[][] getData(List status_) {
if (status_.size() > 0) {
Object[][] data = new Object[status_.size()][4];
for (int i = 0; i < status_.size(); i++) {
Status_ statu = status_.get(i);
// 把List集合的数据赋给Object数组
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String time = format.format(statu.getCreatedAt());
Object[] a = { statu.getId(), statu.getUser().getScreenName(), time, statu.getText(),
statu.getRepostsCount(), statu.getCommentsCount(), "查看转发", "查看评论" };
data[i] = a;// 把数组的值赋给二维数组的一行
}
return data;
}
return null;
}
// 初始化结果集
public void initResultData(Object[][] data) {
if (data != null) {
resultData = data;// 总的结果集
column = data[0].length;// 表的列数
totalRowCount = data.length;// 表的长度
totalPage = totalRowCount % pageCount == 0 ? totalRowCount / pageCount : totalRowCount / pageCount + 1;// 结果集的总页数
restCount = totalRowCount % pageCount == 0 ? 5 : totalRowCount % pageCount;// 最后一页的数据数
}
}
// 获取分页数据
public Object[][] getPageData() {
Object[][] currentPageData = new Object[pageCount][column];
if (this.getCurrentPage() < this.totalPage) {
for (int i = pageCount * (this.getCurrentPage() - 1); i < pageCount * (this.getCurrentPage() - 1) + pageCount; i++) {
for (int j = 0; j < column; j++) {
currentPageData[i % pageCount][j] = resultData[i][j];
}
}
} else {
if (pageCount * (this.getCurrentPage() - 1) >= totalRowCount)
this.currentPage--;
for (int i = pageCount * (this.getCurrentPage() - 1); i < pageCount * (this.getCurrentPage() - 1) + restCount; i++) {
for (int j = 0; j < column; j++) {
currentPageData[i % pageCount][j] = resultData[i][j];
}
}
}
return currentPageData;
}
// 初始化表格数据
public void initTable() {
Object[][] data = getData(status);
if (data != null) {
initResultData(data);
model = new WeiboTableModel(getPageData(), columnNames);
} else {
// 如果结果集中没有数据,那么就用空来代替数据集中的每一行
Object[][] nothing = { {}, {}, {}, {}, {}, {}, {}, {} };
model = new WeiboTableModel(nothing, columnNames);
totalRowCount = 0;
}
settingTable(model);
}
③ 提示框的实现
protected void initDiag() {
final ImageIcon image = new ImageIcon("images/please_wait.gif");
panel = new JPanel() {
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.drawImage(image.getImage(), -5, -5, 250, 100, this);
}
};
panel.setOpaque(false);
panel.repaint();
clueDiag = new JDialog(parentFrame, "正在执行,请等待...", true);
clueDiag.getContentPane().add(panel);
(new DisposeDialog()).start();// 启动关闭提示框线程
}
public void run() {
// 显示提示框
int left = 580;
int top = 180;
clueDiag.setSize(new Dimension(250, 100));
clueDiag.setLocation(left, top);
clueDiag.show();
}
class DisposeDialog extends Thread {
public void run() {
try {
currentThread.join();// 等待事务处理线程结束
} catch (InterruptedException e) {
System.out.println("Exception:" + e);
}
clueDiag.dispose(); // 关闭提示框
}
}
④ 访问微博列表的实现
// 向sina服务器读取指定用户的微博列表
private void getWeibo() {
Timeline tm = new Timeline();
tm.client.setToken(Config.access_token);
for (; page <= total; page++) {
try {
StatusWapper status = tm.getUserTimelineByName(screen_name, new Paging(page, Config.pageCount_sina), 0, 0);
if (status.getTotalNumber() % Config.pageCount_sina == 0) {
total = status.getTotalNumber() / Config.pageCount_sina;
} else {
total = status.getTotalNumber() / Config.pageCount_sina + 1;
}
} catch (WeiboException e) {
e.printStackTrace();
}
}
}
四、查看粉丝的实现
查看粉丝模块的实现过程是:用户输入一个微博昵称,然后点击查看粉丝,系统就会去访问新浪微博服务器,得到该用户的所有粉丝,然后系统将这些粉丝以列表形式分页展示出来。 该模块还有一个粉丝搜索功能,其实现过程是:用户输入一个微博昵称,然后点击搜索粉丝,系统就会根据用户输入的昵称去访问本地数据库,如果查询到有与关键字相似的用户,则提取出来并展示出来,如果没有就展示为空。
该模块的实现涉及了下面几段关键代码:访问粉丝列表的实现和搜索粉丝列表的实现,下面逐一说明它们的关键代码:
① 访问粉丝列表的实现
client.setToken(Config.access_token);
for (; page <= total; page++) {
try {
UserWapper users = User.constructWapperUsers(client.get(WeiboConfig.getValue("baseURL")
+ "friendships/followers.json", new PostParameter[] {
new PostParameter("screen_name", screen_name),
new PostParameter("count", Config.pageCount_sina),
new PostParameter("cursor", (page - 1) * Config.pageCount_sina) }));
for (User u : users.getUsers()) {
System.out.println(u.toString());
}
System.out.println("总数 == " + users.getTotalNumber());
if (users.getTotalNumber() % Config.pageCount_sina == 0) {
total = users.getTotalNumber() / Config.pageCount_sina;
} else {
total = users.getTotalNumber() / Config.pageCount_sina + 1;
}
} catch (WeiboException e) {
e.printStackTrace();
}
}
② 搜索粉丝列表的实现
try {
String sql_follower = "select * from user,friendship where friendship.f_user_id = '" + user_id+ "' and user.screenName LIKE '%" + screen_name + "%' and user.id = friendship.user_id ;";
rs = sqlHelper.queryFriendship(sql_follower);
while (rs.next()) {
User_ user = new User_();
user.setId(rs.getString("id"));
user.setScreenName(rs.getString("screenName"));
user.setGender(rs.getString("gender"));
String time = rs.getString("createdAt");
Date date = new Date(time);
user.setCreatedAt(date);
user.setDescription(rs.getString("description"));
user.setFriendsCount(rs.getInt("friendsCount"));
user.setFollowersCount(rs.getInt("followersCount"));
user.setStatusesCount(rs.getInt("friendsCount"));
User_.users.add(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlHelper.close();
Home.demo.clearPanel();
Home.demo.loadFollower();
}
五、查看关注的实现
查看关注模块的实现过程是:用户输入一个微博昵称,然后点击查看关注,系统就会去访问新浪微博服务器,得到该用户的所有关注,然后系统将这些关注以列表形式分页展示出来。该模块还有一个关注搜索功能,其实现过程是:用户输入一个微博昵称,然后点击搜索关注,系统就会根据用户输入的昵称去访问本地数据库,如果查询到有与关键字相似的用户,则提取出来并展示出来,如果没有就展示为空。
该模块的实现涉及了下面几段关键代码:访问关注列表的实现和搜索关注列表的实现,下面就逐一说明它们的关键代码:
① 访问关注列表的实现
client.setToken(Config.access_token);
for (; page <= total; page++) {
try {
UserWapper users = User.constructWapperUsers(client.get(WeiboConfig.getValue("baseURL")
+ "friendships/friends.json", new PostParameter[] {
new PostParameter("screen_name", screen_name),
new PostParameter("count", Config.pageCount_sina),
new PostParameter("cursor", (page - 1) * Config.pageCount_sina) }));
for (User u : users.getUsers()) {
if (users.getTotalNumber() % Config.pageCount_sina == 0) {
total = users.getTotalNumber() / Config.pageCount_sina;
} else {
total = users.getTotalNumber() / Config.pageCount_sina + 1;
}
} catch (WeiboException e) {
e.printStackTrace();
}
}
② 搜索关注列表的实现
try {
String sql_follower = "select * from user,friendship where friendship.f_user_id = '" + user_id+ "' and user.screenName LIKE '%" + screen_name + "%' and user.id = friendship.user_id ;";
rs = sqlHelper.queryFriendship(sql_follower);
while (rs.next()) {
User_ user = new User_();
user.setId(rs.getString("id"));
user.setScreenName(rs.getString("screenName"));
user.setGender(rs.getString("gender"));
String time = rs.getString("createdAt");
Date date = new Date(time);
user.setCreatedAt(date);
user.setDescription(rs.getString("description"));
user.setFriendsCount(rs.getInt("friendsCount"));
user.setFollowersCount(rs.getInt("followersCount"));
user.setStatusesCount(rs.getInt("friendsCount"));
User_.users.add(user);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
sqlHelper.close();
Home.demo.clearPanel();
Home.demo.loadFollower();
}
六、查看评论的实现
查看评论模块的实现过程是:当用户查看微博后,可以选择查看每条微博的评论情况,然后系统就会凭借点击的这条微博的id去访问新浪服务器获取这条微博的评论信息并将他们展示成列表分页显示。这个过程中,系统会保存这些评论信息和评论者信息到本地数据库。该模块的实现涉及了下面一段关键代码:访问评论列表的实现,它的关键代码如下:
Comments cm = new Comments();
cm.client.setToken(Config.access_token);
for (; page <= total; page++) {
try {
CommentWapper comment = cm.getCommentById(commentId, new Paging(page, Config.pageCount_sina), 0);
for (Comment c : comment.getComments()) {
System.out.println(c.toString());
}
System.out.println(comment.getTotalNumber());
if (comment.getTotalNumber() % Config.pageCount_sina == 0) {
total = comment.getTotalNumber() / Config.pageCount_sina;
} else {
total = comment.getTotalNumber() / Config.pageCount_sina + 1;
}
} catch (WeiboException e) {
e.printStackTrace();
}
}
七、查看转发的实现
查看转发模块的实现过程是:当用户查看微博后,可以选择查看每条微博的转发情况,然后系统就会凭借点击的这条微博的id去访问新浪服务器获取这条微博的转发信息并将他们展示成列表分页显示。这个过程中,系统会保存这些转发信息和转发者信息到本地数据库。该模块的实现涉及了下面一段关键代码:访问转发列表的实现,它的关键代码如下:
Timeline tm = new Timeline();
tm.client.setToken(Config.access_token);
for (; page <= total; page++) {
try {
StatusWapper status = tm.getRepostTimeline(repostId, new Paging(page, Config.pageCount_sina));
for (Status s : status.getStatuses()) {
System.out.println(s.toString());
}
System.out.println(status.getTotalNumber());
if (status.getTotalNumber() % Config.pageCount_sina == 0) {
total = status.getTotalNumber() / Config.pageCount_sina;
} else {
total = status.getTotalNumber() / Config.pageCount_sina + 1;
}
} catch (WeiboException e) {
e.printStackTrace();
}
}
第五章 系统效果展示
截至目前,本系统的设计与开发就已经完成了,那现在我们就来看看本系统的运行效果如何,就当作测试下系统。
一、主界面效果展示
启动模块主要负责应用程序启动的界面,启动界面如图5.1所示:
图5.1 应用程序启动界面
下面就详细解释一下该界面的实现:该界面分为上、下两个部分,上面是功能展示区,包含该系统的主要几个功能模块:查看微博、查看粉丝和查看关注,其中有个信息输入框,主要用来提示用户输入想要浏览的微博用户的用户昵称。如果系统用户没有输入昵称就直接点击功能按钮,系统就会弹出提示狂提醒用户输入昵称,如图5.2所示:
图5.2 输入提示警告
二、查看微博的效果展示
用户输入一个微博昵称,然后点击查看微博,系统就会把该用户的所有微博以列表形式分页展示出来,查看微博界面如图5.3所示:
图5.3 查看微博界面
在获取微博的这段时间里,系统会弹出进度条框,让用户知道正在进行后台数据的处理,具体见图5.4。
图5.4 进度条提示框
三、查看粉丝的效果展示
用户输入一个微博昵称,然后点击查看粉丝,系统就会把该用户的所有粉丝以列表形式分页展示出来,查看粉丝界面如图5.5所示:
图5.5 查看粉丝界面
该模块还有一个粉丝搜索功能,用户输入一个微博昵称,然后点击搜索粉丝,系统就会根据用户输入的昵称去访问本地数据库,如果查询到有与关键字相似的用户,则提取出来并展示出来,如果没有就展示为空。搜索粉丝的效果图如图5.6所示:
图5.6 搜索粉丝效果图
四、查看关注的效果展示
用户输入一个微博昵称,然后点击查看关注,系统就会把该用户的所有关注以列表形式分页展示出来,查看关注界面如图5.7示:
图5.7查看关注界面
该模块还有一个关注搜索功能,其实现过程是:用户输入一个微博昵称,然后点击搜索关注,系统就会根据用户输入的昵称去访问本地数据库,如果查询到有与关键字相似的用户,则提取出来并展示出来,如果没有就展示为空。搜索关注的效果图如图5.8所示:
图5.8 搜索关注效果图
五、查看评论的效果展示
当用户查看微博界面点击某条微博后面对应的查看评论按钮,系统就会弹出评论展示框,显示出这条微博的所有评论信息。评论界面如图5.9所示:
图5.9 查看评论界面
六、查看转发的效果展示
当用户查看微博界面点击某条微博后面对应的查看转发按钮,系统就会弹出转发展示框,显示出这条微博的所有转发信息。转发界面如图5.10示:
图5.10看转发界面
附 录
1、 英文原文:
Java theory and practice: Plugging memory leaks with soft references
Soft references provide for quick-and-dirty caching
Brian Goetz (brian@quiotix.com), Principal Consultant, Quiotix
Summary: In the previous installment of Java theory and practice, Java™ sanitation engineer Brian Goetz examined weak references, which let you put the garbage collector on notice that you want to maintain a reference to an object without preventing it from being garbage collected. This month, he explains another form of Reference object, soft references, which can also enlist the aid of the garbage collector in managing memory usage and eliminating potential memory leaks.
Garbage collection might make Java programs immune to memory leaks, at least for a sufficiently narrow definition of "memory leak," but that doesn't mean we can totally ignore the issue of object lifetime in Java programs. Memory leaks in Java programs usually arise when we pay insufficient attention to object lifecycle or subvert the standard mechanisms for managing object lifecycle. For example, last time we saw how failing to demarcate an object's lifecycle could cause unintentional object retention when trying to associate metadata with transient objects. There are other idioms that can similarly ignore or subvert object lifecycle management and can also lead to memory leaks.
Object loitering
A form of memory leak, sometimes called object loitering, is illustrated by the LeakyChecksum class in Listing 1, which provides a getFileChecksum() method to calculate the checksum of a file's contents. The getFileChecksum() method reads the contents of the file into a buffer to compute the checksum. A more straightforward implementation would simply allocate the buffer as a local variable within getFileChecksum(), but this version is more "clever" than that, instead caching the buffer in an instance field to reduce memory churn. This "optimization" often does not deliver the expected savings; object allocation is cheaper than many give it credit for. (Also note that promoting the buffer from a local variable to an instance variable renders the class no longer thread-safe without additional synchronization; the straightforward implementation would not require getFileChecksum() to be declared synchronized and would offer better scalability when called concurrently.)
Listing 1. Class that exhibits "object loitering"
// BAD CODE - DO NOT EMULATE
public class LeakyChecksum {
private byte[] byteArray;
public synchronized int getFileChecksum(String fileName) {
int len = getFileSize(fileName);
if (byteArray == null || byteArray.length < len)
byteArray = new byte[len];
readFileContents(fileName, byteArray);
// calculate checksum and return it
}
}
This class has plenty of problems, but let's focus on the memory leak. The decision to cache the buffer most likely followed from the assumption that it would be called many times within a program and that it would therefore be more efficient to reuse the buffer rather than reallocate it. But as a result, the buffer is never released because it is always reachable by the program (unless the LeakyChecksum object is garbage collected). Worse, while it can grow, it cannot shrink, so LeakyChecksum permanently retains a buffer as large as the largest file processed. At the very least, this puts pressure on the garbage collector and requires more frequent collections; keeping a large buffer around for the purpose of computing future checksums may not be the most efficient use of available memory.
The cause of the problem in LeakyChecksum is that the buffer is logically local to the getFileChecksum() operation, but its lifecycle has been artificially prolonged by promoting it to an instance field. As a result, the class has to manage the lifecycle of the buffer itself rather than letting the JVM do it.
Soft references
In the previous installment, we saw how weak references can provide an application with an alternate means of reaching an object while it is used by the program, but without prolonging its lifetime. Another subclass of Reference, soft references, fulfills a different but related purpose. Where weak references allow the application to create references that do not interfere with garbage collection, soft references allow the application to enlist the aid of the garbage collector by designating some objects as "expendable." While the garbage collector does a good job at figuring out what memory the application is using and not using, it is up to the application to decide the most appropriate use for the available memory. If the application makes poor decisions as to what objects to retain, performance can suffer as the garbage collector has to work harder to prevent the application from running out of memory.
Caching is a common performance optimization, allowing the application to reuse the results of a previous calculation instead of recalculating it. Caching is a trade-off between CPU utilization and memory usage, and the ideal balance for this trade-off depends on how much memory is available. With too little caching, the desired performance benefit will not be achieved; with too much, performance may suffer because too much memory is being expended on caching and therefore not enough is available for other purposes. Because the garbage collector is generally in a better position than the application to determine the demand for memory, it makes sense to enlist the garbage collector's help in making these decisions, which is what soft references do for us.
If the only remaining references to an object are weak or soft references, then that object is said to be softly reachable. The garbage collector does not aggressively collect softly reachable objects the way it does with weakly reachable ones -- instead it only collects softly reachable objects if it really "needs" the memory. Soft references are a way of saying to the garbage collector, "As long as memory isn't too tight, I'd like to keep this object around. But if memory gets really tight, go ahead and collect it and I'll deal with that." The garbage collector is required to clear all soft references before it can throw OutOfMemoryError.
We can fix the problems in LeakyChecksum by using a soft reference to manage the cached buffer, as shown in Listing 2. Now the buffer is retained as long as the memory is not badly needed, but it can be reclaimed by the garbage collector if necessary:
Listing 2. Fixing LeakyChecksum with a soft reference
public class CachingChecksum {
private SoftReference bufferRef;
public synchronized int getFileChecksum(String fileName) {
int len = getFileSize(fileName);
byte[] byteArray = bufferRef.get();
if (byteArray == null || byteArray.length < len) {
byteArray = new byte[len];
bufferRef.set(byteArray);
}
readFileContents(fileName, byteArray);
// calculate checksum and return it
}
}
A poor man's cache
CachingChecksum used a soft reference to cache a single object and let the JVM handle the details of when to evict the object from the cache. Similarly, soft references are also often used in GUI applications for caching bitmap graphics. The key to whether a soft reference can be used is whether an application can recover from the loss of the data being cached.
If you need to cache more than a single object, you might use a Map, but you have a choice as to how to employ soft references. You could manage the cache as a Map> or as a SoftReference