首页 网络舆情数据采集系统开发毕业论文

网络舆情数据采集系统开发毕业论文

举报
开通vip

网络舆情数据采集系统开发毕业论文 摘 要 互联网发展至今,传统媒体已经日渐落寞,作为新生代媒体,网络已经在这一领域占据了越来越重要的地位,而且这种趋势还在上涨。现今,越来越多的人通过互联网来表达自己对社会现状的态度和政治诉求等等,从互联网这一自由开放的媒体中了解民生,开展网络舆情信息采集和分析,已经各级政府部门目前面临的重要课题。 互联网作为新生代媒体,其发展势头迅猛,各大门户网站纷纷进军互联网领域抢占市场,竞争十分激烈,而其中新浪在这场竞争中表现得相当出色,新浪微博民众信息分享平台的首选。本论文就设计了一个专门针对新浪微博的舆情数据采集系统...

网络舆情数据采集系统开发毕业论文
摘 要 互联网发展至今,传统媒体已经日渐落寞,作为新生代媒体,网络已经在这一领域占据了越来越重要的地位,而且这种趋势还在上涨。现今,越来越多的人通过互联网来表达自己对社会现状的态度和政治诉求等等,从互联网这一自由开放的媒体中了解民生,开展网络舆情信息采集和分析,已经各级政府部门目前面临的重要课题。 互联网作为新生代媒体,其发展势头迅猛,各大门户网站纷纷进军互联网领域抢占市场,竞争十分激烈,而其中新浪在这场竞争中表现得相当出色,新浪微博民众信息分享平台的首选。本论文就设计了一个专门针对新浪微博的舆情数据采集系统,它包含如下几个功能:查询指定用户的微博信息、查询指定微博的评论信息和转发信息、查询指定用户的所有粉丝和搜索该用户的指定粉丝、查询指定用户的所有关注和搜索该用户的指定关注以及将上述信息保存到本地数据库中,供以后对数据进行分析。 该系统是基于新浪官方提供的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>. The latter option is usually preferable, as it makes less work for the collector and allows the entire cache to be reclaimed with less effort when memory is in high demand. Weak references are sometimes mistakenly used instead of soft references for building caches, but this will result in poor caching performance. In practice, weak references will get cleared fairly quickly after the object becomes weakly reachable -- usually before the cached object is needed again -- as minor garbage collections run frequently. For applications that rely heavily on caching for performance, soft references may be too blunt an instrument -- it certainly is not meant as a replacement for sophisticated caching frameworks that provide flexible expiration, replication, and transactional caching. But as a "cheap and dirty" caching mechanism, it is an attractive price-performer. Just as with weak references, a soft reference can be created with an associated reference queue, and the reference is enqueued when it is cleared by the garbage collector. Reference queues are not as useful with soft references as with weak references, but they could be used to raise a management alert that the application is starting to run low on memory. How the garbage collector handles References Weak and soft references both extend the abstract Reference class (as do phantom references, which will be discussed in a future article). Reference objects are treated specially by the garbage collector. When the garbage collector encounters a Reference in the course of tracing the heap, it does not mark or trace the referent object, but instead places the Reference on a queue of known live Reference objects. After the trace, the collector identifies the softly reachable objects -- these objects for which no strong references exist but soft references do. The garbage collector then assesses whether soft references need to be cleared at this time, based on the amount of memory reclaimed by the current collection and other policy considerations. Soft references that are to be cleared are enqueued if they have a corresponding reference queue; the remaining softly reachable objects (the ones that are not cleared) are then treated as a root set and the heap trace is continued using these new roots so that the objects reachable through live soft references can be marked. After processing the soft references, the set of weakly reachable objects is identified -- objects for which no strong or soft references exist. These are cleared and enqueued. All Reference types are cleared before they are enqueued, so the thread handling the post-mortem cleanup never has access to the referent object, only the Reference object. For this reason, when References are used in conjunction with a reference queue, it is common to subclass the appropriate reference type and either use it directly in your design (as with WeakHashMap, whose Map.Entry extends WeakReference) or to store references to entities that require cleanup. Performance costs of reference processing Reference objects introduce some additional costs into the garbage collection process. At each garbage collection, a list of live Reference objects must be constructed, and each reference must be processed appropriately, which adds some per-Reference overhead to each collection regardless of whether the referent is being collected at that time. Reference objects themselves are subject to garbage collection and can be collected before the referent, in which case they are not enqueued. Array-based collections Another form of object loitering arises when arrays are used to implement data structures such as stacks or circular buffers. The LeakyStack class in Listing 3 shows an implementation of a stack backed by an array. In the pop() method, after the top pointer is decremented, elements still maintains a reference to the object being popped off the stack. This means that a reference to that object is still reachable by the program even though the program never actually uses that reference again, which prevents that object from being garbage collected until that location is reused by a future push(). Listing 3. Object loitering in array-based collection public class LeakyStack { private Object[] elements = new Object[MAX_ELEMENTS]; private int size = 0; public void push(Object o) { elements[size++] = o; } public Object pop() { if (size == 0) throw new EmptyStackException(); else { Object result = elements[--size]; // elements[size+1] = null; return result; } } } The cure for object loitering in this case is to null out the reference after popping it from the stack, as shown in the commented-out line of code in Listing 3. However, this case -- where a class manages its own memory -- is one of the very few situations where explicitly nulling objects that are no longer needed is a good idea. Most of the time, aggressively nulling references believed to be unused results in no performance or memory utilization gain at all; it usually results in either worse performance or NullPointerExceptions. A linked implementation of this algorithm would not have this problem; in a linked implementation, the lifetime of the link node (and therefore the reference to the object being stored) would be automatically tied to the duration that the object is stored in the collection. Weak references could be used to fix this problem -- maintaining an array of weak references instead of strong references -- but in reality, LeakyStack manages its own memory and is therefore responsible for ensuring that references to objects no longer needed are cleared. Using arrays to implement a stack or a buffer is an optimization that reduces allocation but imposes a greater burden for the implementer to carefully manage the lifetime of references stored in the array. Summary Soft references, like weak references, can help applications prevent object loitering by enlisting the aid of the garbage collector in making cache eviction decisions. Soft references are suitable for use only if the application can tolerate the loss of the softly referenced object. 二、英文翻译: Java 理论和实践: 用软引用阻止内存泄漏 Brian Goetz (brian@quiotix.com), Principal Consultant, Quiotix 简介: 在 Java 理论和实践 的 前一期文章 中,Java™ 清洁工程师 Brian Goetz 探究了弱引用(weak references),它让您警告垃圾收集器,您想要维护一个对象的引用,而不会阻止该对象被垃圾收集。在本期文章中,他将解释 Reference 对象的另外一种形式,即软引用(soft references),用于帮助垃圾收集器管理内存使用和消除潜在的内存泄漏。 垃圾收集可以使 Java 程序不会出现内存泄漏,至少对于比较狭窄的 “内存泄漏” 定义来说如此,但是这并不意味着我们可以完全忽略 Java 程序中的对象生存期(lifetime)问题。当我们没有对对象生命周期(lifecycle)引起足够的重视或者破坏了管理对象生命周期的标准机制时,Java 程序中通常就会出现内存泄漏。例如,上一次 我们看到了,不能划分对象的生命周期会导致,在试图将元数据关联到瞬时对象时出现意外的对象保持。还有一些其他的情况可以类似地忽略或破坏对象生命周期管理,并导致内存泄漏。 对象游离 一种形式的内存泄漏有时候叫做对象游离(object loitering),是通过清单 1 中的 LeakyChecksum 类来说明的,清单 1 中有一个 getFileChecksum() 方法用于计算文件内容的校验和。getFileChecksum() 方法将文件内容读取到缓冲区中以计算校验和。一种更加直观的实现简单地将缓冲区作为 getFileChecksum() 中的本地变量分配,但是该版本比那样的版本更加 “聪明”,不是将缓冲区缓存在实例字段中以减少内存 churn。该 “优化”通常不带来预期的好处;对象分配比很多人期望的更便宜。(还要注意,将缓冲区从本地变量提升到实例变量,使得类若不带有附加的同步,就不再是线程安全的了。直观的实现不需要将 getFileChecksum() 声明为 synchronized,并且会在同时调用时提供更好的可伸缩性。) 清单 1. 展示 “对象游离” 的类 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 } } 这个类存在很多的问题,但是我们着重来看内存泄漏。缓存缓冲区的决定很可能是根据这样的假设得出的,即该类将在一个程序中被调用许多次,因此它应该更加有效,以重用缓冲区而不是重新分配它。但是结果是,缓冲区永远不会被释放,因为它对程序来说总是可及的(除非 LeakyChecksum 对象被垃圾收集了)。更坏的是,它可以增长,却不可以缩小,所以 LeakyChecksum 将永久保持一个与所处理的最大文件一样大小的缓冲区。退一万步说,这也会给垃圾收集器带来压力,并且要求更频繁的收集;为计算未来的校验和而保持一个大型缓冲区并不是可用内存的最有效利用。 LeakyChecksum 中问题的原因是,缓冲区对于 getFileChecksum() 操作来说逻辑上是本地的,但是它的生命周期已经被人为延长了,因为将它提升到了实例字段。因此,该类必须自己管理缓冲区的生命周期,而不是让 JVM 来管理。 软引用 在 前一期文章 中我们看到了,弱引用如何可以给应用程序提供当对象被程序使用时另一种到达该对象的方法,但是不会延长对象的生命周期。Reference 的另一个子类 —— 软引用 —— 可满足一个不同却相关的目的。其中弱引用允许应用程序创建不妨碍垃圾收集的引用,软引用允许应用程序通过将一些对象指定为 “expendable” 而利用垃圾收集器的帮助。尽管垃圾收集器在找出哪些内存在由应用程序使用哪些没在使用方面做得很好,但是确定可用内存的最适当使用还是取决于应用程序。如果应用程序做出了不好的决定,使得对象被保持,那么性能会受到影响,因为垃圾收集器必须更加辛勤地工作,以防止应用程序消耗掉所有内存。 高速缓存是一种常见的性能优化,允许应用程序重用以前的计算结果,而不是重新进行计算。高速缓存是 CPU 利用和内存使用之间的一种折衷,这种折衷理想的平衡状态取决于有多少内存可用。若高速缓存太少,则所要求的性能优势无法达到;若太多,则性能会受到影响,因为太多的内存被用于高速缓存上,导致其他用途没有足够的可用内存。因为垃圾收集器比应用程序更适合决定内存需求,所以应该利用垃圾收集器在做这些决定方面的帮助,这就是件引用所要做的。 如果一个对象惟一剩下的引用是弱引用或软引用,那么该对象是软可及的(softly reachable)。垃圾收集器并不像其收集弱可及的对象一样尽量地收集软可及的对象,相反,它只在真正 “需要” 内存时才收集软可及的对象。软引用对于垃圾收集器来说是这样一种方式,即 “只要内存不太紧张,我就会保留该对象。但是如果内存变得真正紧张了,我就会去收集并处理这个对象。” 垃圾收集器在可以抛出 OutOfMemoryError 之前需要清除所有的软引用。 通过使用一个软引用来管理高速缓存的缓冲区,可以解决 LeakyChecksum 中的问题,如清单 2 所示。现在,只要不是特别需要内存,缓冲区就会被保留,但是在需要时,也可被垃圾收集器回收: 清单 2. 用软引用修复 LeakyChecksum 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 } } 一种廉价的缓存 CachingChecksum 使用一个软引用来缓存单个对象,并让 JVM 处理从缓存中取走对象时的细节。类似地,软引用也经常用于 GUI 应用程序中,用于缓存位图图形。是否可使用软引用的关键在于,应用程序是否可从大量缓存的数据恢复。 如果需要缓存不止一个对象,您可以使用一个 Map,但是可以选择如何使用软引用。您可以将缓存作为 Map> 或 SoftReference> 管理。后一种选项通常更好一些,因为它给垃圾收集器带来的工作更少,并且允许在特别需要内存时以较少的工作回收整个缓存。弱引用有时会错误地用于取代软引用,用于构建缓存,但是这会导致差的缓存性能。在实践中,弱引用将在对象变得弱可及之后被很快地清除掉 —— 通常是在缓存的对象再次用到之前 —— 因为小的垃圾收集运行得很频繁。 对于在性能上非常依赖高速缓存的应用程序来说,软引用是一个不管用的手段,它确实不能取代能够提供灵活终止期、复制和事务型高速缓存的复杂的高速缓存框架。但是作为一种 “廉价(cheap and dirty)” 的高速缓存机制,它对于降低价格是很有吸引力的。 正如弱引用一样,软引用也可创建为具有一个相关的引用队列,引用在被垃圾收集器清除时进入队列。引用队列对于软引用来说,没有对弱引用那么有用,但是它们可以用于发出管理警报,说明应用程序开始缺少内存。 垃圾收集器如何处理 References 弱引用和软引用都扩展了抽象的 Reference 类(虚引用(phantom references)也一样,这将在以后的文章中介绍)。引用对象被垃圾收集器特殊地看待。垃圾收集器在跟踪堆期间遇到一个 Reference 时,不会标记或跟踪该引用对象,而是在已知活跃的 Reference 对象的队列上放置一个 Reference。在跟踪之后,垃圾收集器就识别软可及的对象 —— 这些对象上除了软引用外,没有任何强引用。垃圾收集器然后根据当前收集所回收的内存总量和其他策略考虑因素,判断软引用此时是否需要被清除。将被清除的软引用如果具有相应的引用队列,就会进入队列。其余的软可及对象(没有清除的对象)然后被看作一个根集(root set),堆跟踪继续使用这些新的根,以便通过活跃的软引用而可及的对象能够被标记。 处理软引用之后,弱可及对象的集合被识别 —— 这样的对象上不存在强引用或软引用。这些对象被清除和加入队列。所有 Reference 类型在加入队列之前被清除,所以处理事后检查(post-mortem)清除的线程永远不会具有 referent 对象的访问权,而只具有 Reference 对象的访问权。因此,当 References 与引用队列一起使用时,通常需要细分适当的引用类型,并将它直接用于您的设计中(与 WeakHashMap 一样,它的 Map.Entry 扩展了 WeakReference)或者存储对需要清除的实体的引用。 引用处理的性能成本 引用对象给垃圾收集过程带来了一些附加的成本。每一次垃圾收集,都必须构造活跃 Reference 对象的一个列表,而且每个引用都必须做适当的处理,这给每次收集添加了一些每个 Reference 的开销,而不管该 referent 此时是否被收集。Reference 对象本身服从于垃圾收集,并且可在 referent 之前被收集,在这样的情况下,它们没有加入队列。 基于数组的集合 当数组用于实现诸如堆栈或环形缓冲区之类的数据结构时,会出现另一种形式的对象游离。清单 3 中的 LeakyStack 类展示了用数组实现的堆栈的实现。在 pop() 方法中,在顶部指针递减之后,elements 仍然会保留对将弹出堆栈的对象的引用。这意味着,该对象的引用对程序来说仍然可及(即使程序实际上不会再使用该引用),这会阻止该对象被垃圾收集,直到该位置被未来的 push() 重用。 清单 3. 基于数组的集合中的对象游离 public class LeakyStack { private Object[] elements = new Object[MAX_ELEMENTS]; private int size = 0; public void push(Object o) { elements[size++] = o; } public Object pop() { if (size == 0) throw new EmptyStackException(); else { Object result = elements[--size]; // elements[size+1] = null; return result; } } } 修复这种情况下的对象游离的方法是,当对象从堆栈弹出之后,就消除它的引用,如清单 3 中注释掉的行所示。但是这种情况 —— 由类管理其自己的内存 —— 是一种非常少见的情况,即显式地消除不再需要的对象是一个好主意。大部分时候,认为不应该使用的强行消除引用根本不会带来性能或内存使用方面的收益,通常是导致更差的性能或者 NullPointerException。该算法的一个链接实现不会存在这个问题。在链接实现中,链接节点(以及所存储的对象的引用)的生命期将被自动与对象存储在集合中的期间绑定在一起。弱引用可用于解决这个问题 —— 维护弱引用而不是强引用的一个数组 —— 但是在实际中,LeakyStack 管理它自己的内存,因此负责确保对不再需要的对象的引用被清除。使用数组来实现堆栈或缓冲区是一种优化,可以减少分配,但是会给实现者带来更大的负担,需要仔细地管理存储在数组中的引用的生命期。 结束语 与弱引用一样,软引用通过利用垃圾收集器在作出缓存回收决策方面的帮助,有助于防止应用程序出现对象游离。只有当应用程序可以忍受大量软引用的对象时,软引用才适合使用。 毕业设计(论文)原创性声明和使用授权说明 原创性声明 本人郑重承诺:所呈交的毕业设计(论文),是我个人在指导教师的指导下进行的研究工作及取得的成果。尽我所知,除文中特别加以标注和致谢的地方外,不包含其他人或组织已经发表或公布过的研究成果,也不包含我为获得 及其它教育机构的学位或学历而使用过的材料。对本研究提供过帮助和做出过贡献的个人或集体,均已在文中作了明确的说明并表示了谢意。 作 者 签 名:       日  期:        ​​​​​​​​​​​​ 指导教师签名:        日  期:        使用授权说明 本人完全了解 大学关于收集、保存、使用毕业设计(论文)的规定,即:按照学校要求提交毕业设计(论文)的印刷本和电子版本;学校有权保存毕业设计(论文)的印刷本和电子版,并提供目录检索与阅览服务;学校可以采用影印、缩印、数字化或其它复制手段保存论文;在不以赢利为目的前提下,学校可以公布论文的部分或全部内容。 作者签名:        日  期:        ​​​​​​​​​​​​ 学位论文原创性声明 本人郑重声明:所呈交的论文是本人在导师的指导下独立进行研究所取得的研究成果。除了文中特别加以标注引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写的成果作品。对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。本人完全意识到本声明的法律后果由本人承担。 作者签名: 日期: 年 月 日 学位论文版权使用授权书 本学位论文作者完全了解学校有关保留、使用学位论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。本人授权      大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。 涉密论文按学校规定处理。 作者签名: 日期: 年 月 日 导师签名: 日期: 年 月 日 独 创 声 明 本人郑重声明:所呈交的毕业设计(论文),是本人在指导老师的指导下,独立进行研究工作所取得的成果,成果不存在知识产权争议。尽我所知,除文中已经注明引用的内容外,本设计(论文)不含任何其他个人或集体已经发表或撰写过的作品成果。对本文的研究做出重要贡献的个人和集体均已在文中以明确方式标明。 本声明的法律后果由本人承担。   作者签名: 二〇一〇年九月二十日   毕业设计(论文)使用授权声明 本人完全了解**学院关于收集、保存、使用毕业设计(论文)的规定。 本人愿意按照学校要求提交学位论文的印刷本和电子版,同意学校保存学位论文的印刷本和电子版,或采用影印、数字化或其它复制手段保存设计(论文);同意学校在不以营利为目的的前提下,建立目录检索与阅览服务系统,公布设计(论文)的部分或全部内容,允许他人依法合理使用。 (保密论文在解密后遵守此规定)   作者签名: 二〇一〇年九月二十日 基本要求:写毕业论文主要目的是培养学生综合运用所学知识和技能,理论联系实际,独立分析,解决实际问题的能力,使学生得到从事本专业工作和进行相关的基本训练。毕业论文应反映出作者能够准确地掌握所学的专业基础知识,基本学会综合运用所学知识进行科学研究的方法,对所研究的题目有一定的心得体会,论文题目的范围不宜过宽,一般选择本学科某一重要问题的一个侧面。 毕业论文的基本教学要求是: 1、培养学生综合运用、巩固与扩展所学的基础理论和专业知识,培养学生独立分析、解决实际问题能力、培养学生处理数据和信息的能力。2、培养学生正确的理论联系实际的工作作风,严肃认真的科学态度。3、培养学生进行社会调查研究;文献资料收集、阅读和整理、使用;提出论点、综合论证、总结写作等基本技能。 毕业论文是毕业生总结性的独立作业,是学生运用在校学习的基本知识和基础理论,去分析、解决一两个实际问题的实践锻炼过程,也是学生在校学习期间学习成果的综合性总结,是整个教学活动中不可缺少的重要环节。撰写毕业论文对于培养学生初步的科学研究能力,提高其综合运用所学知识分析问题、解决问题能力有着重要意义。 毕业论文在进行编写的过程中,需要经过开题报告、论文编写、论文上交评定、论文答辩以及论文评分五个过程,其中开题报告是论文进行的最重要的一个过程,也是论文能否进行的一个重要指标。 撰写意义:1.撰写毕业论文是检验学生在校学习成果的重要措施,也是提高教学质量的重要环节。大学生在毕业前都必须完成毕业论文的撰写任务。申请学位必须提交相应的学位论文,经答辩通过后,方可取得学位。可以这么说,毕业论文是结束大学学习生活走向社会的一个中介和桥梁。毕业论文是大学生才华的第一次显露,是向祖国和人民所交的一份有份量的答卷,是投身社会主义现代化建设事业的报到书。一篇毕业论文虽然不能全面地反映出一个人的才华,也不一定能对社会直接带来巨大的效益,对专业产生开拓性的影响。但是,实践证明,撰写毕业论文是提高教学质量的重要环节,是保证出好人才的重要措施。 2.通过撰写毕业论文,提高写作水平是干部队伍“四化”建设的需要。党中央要求,为了适应现代化建设的需要,领导班子成员应当逐步实现“革命化、年轻化、知识化、专业化”。这个“四化”的要求,也包含了对干部写作能力和写作水平的要求。 3.提高大学生的写作水平是社会主义物质文明和精神文明建设的需要。在新的历史时期,无论是提高全族的科学文化水平,掌握现代科技知识和科学管理方法,还是培养社会主义新人,都要求我们的干部具有较高的写作能力。在经济建设中,作为领导人员和机关的办事人员,要写指示、通知、总结、调查报告等应用文;要写说明书、广告、解说词等说明文;还要写科学论文、经济评论等议论文。在当今信息社会中,信息对于加快经济发展速度,取得良好的经济效益发挥着愈来愈大的作用。写作是以语言文字为信号,是传达信息的方式。信息的来源、信息的收集、信息的储存、整理、传播等等都离不开写作。 论文种类:毕业论文是学术论文的一种形式,为了进一步探讨和掌握毕业论文的写作规律和特点,需要对毕业论文进行分类。由于毕业论文本身的内容和性质不同,研究领域、对象、方法、表现方式不同,因此,毕业论文就有不同的分类方法。 按内容性质和研究方法的不同可以把毕业论文分为理论性论文、实验性论文、描述性论文和设计性论文。后三种论文主要是理工科大学生可以选择的论文形式,这里不作介绍。文科大学生一般写的是理论性论文。理论性论文具体又可分成两种:一种是以纯粹的抽象理论为研究对象,研究方法是严密的理论推导和数学运算,有的也涉及实验与观测,用以验证论点的正确性。另一种是以对客观事物和现象的调查、考察所得观测资料以及有关文献资料数据为研究对象,研究方法是对有关资料进行分析、综合、概括、抽象,通过归纳、演绎、类比,提出某种新的理论和新的见解。 按议论的性质不同可以把毕业论文分为立论文和驳论文。立论性的毕业论文是指从正面阐述论证自己的观点和主张。一篇论文侧重于以立论为主,就属于立论性论文。立论文要求论点鲜明,论据充分,论证严密,以理和事实服人。驳论性毕业论文是指通过反驳别人的论点来树立自己的论点和主张。如果毕业论文侧重于以驳论为主,批驳某些错误的观点、见解、理论,就属于驳论性毕业论文。驳论文除按立论文对论点、论据、论证的要求以外,还要求针锋相对,据理力争。 按研究问题的大小不同可以把毕业论文分为宏观论文和微观论文。凡届国家全局性、带有普遍性并对局部工作有一定指导意义的论文,称为宏观论文。它研究的面比较宽广,具有较大范围的影响。反之,研究局部性、具体问题的论文,是微观论文。它对具体工作有指导意义,影响的面窄一些。 另外还有一种综合型的分类方法,即把毕业论文分为专题型、论辩型、综述型和综合型四大类: 1.专题型论文。这是分析前人研究成果的基础上,以直接论述的形式发表见解,从正面提出某学科中某一学术问题的一种论文。如本书第十二章例文中的《浅析领导者突出工作重点的方法与艺术》一文,从正面论述了突出重点的工作方法的意义、方法和原则,它表明了作者对突出工作重点方法的肯定和理解。2.论辩型论文。这是针对他人在某学科中某一学术问题的见解,凭借充分的论据,着重揭露其不足或错误之处,通过论辩形式来发表见解的一种论文。3.综述型论文。这是在归纳、总结前人或今人对某学科中某一学术问题已有研究成果的基础上,加以介绍或评论,从而发表自己见解的一种论文。4.综合型论文。这是一种将综述型和论辩型两种形式有机结合起来写成的一种论文。如《关于中国民族关系史上的几个问题》一文既介绍了研究民族关系史的现状,又提出了几个值得研究的问题。因此,它是一篇综合型的论文。 写作步骤:毕业论文是高等教育自学考试本科专业应考者完成本科阶段学业的最后一个环节,它是应考者的 总结 性独立作业,目的在于总结学习专业的成果,培养综合运用所学知识解决实际 问题 的能力。从文体而言,它也是对某一专业领域的现实问题或 理论 问题进行 科学 研究 探索的具有一定意义的论说文。完成毕业论文的撰写可以分两个步骤,即选择课题和研究课题。 首先是选择课题。选题是论文撰写成败的关键。因为,选题是毕业论文撰写的第一步,它实际上就是确定“写什么”的问题,亦即确定科学研究的方向。如果“写什么”不明确,“怎么写”就无从谈起。 教育部自学考试办公室有关对毕业论文选题的途径和要求是“为鼓励理论与工作实践结合,应考者可结合本单位或本人从事的工作提出论文题目,报主考学校审查同意后确立。也可由主考学校公布论文题目,由应考者选择。毕业论文的总体要求应与普通全日制高等学校相一致,做到通过论文写作和答辩考核,检验应考者综合运用专业知识的能力”。但不管考生是自己任意选择课题,还是在主考院校公布的指定课题中选择课题,都要坚持选择有科学价值和现实意义的、切实可行的课题。选好课题是毕业论文成功的一半。 第一、要坚持选择有科学价值和现实意义的课题。科学研究的目的是为了更好地认识世界、改造世界,以推动社会的不断进步和发展 。因此,毕业论文的选题,必须紧密结合社会主义物质文明和精神文明建设的需要,以促进科学事业发展和解决现实存在问题作为出发点和落脚点。选题要符合科学研究的正确方向,要具有新颖性,有创新、有理论价值和现实的指导意义或推动作用,一项毫无意义的研究,即使花很大的精力,表达再完善,也将没有丝毫价值。具体地说,考生可从以下三个方面来选题。首先,要从现实的弊端中选题,学习了专业知识,不能仅停留在书本上和理论上,还要下一番功夫,理论联系实际,用已掌握的专业知识,去寻找和解决工作实践中急待解决的问题。其次,要从寻找科学研究的空白处和边缘领域中选题,科学研究。还有许多没有被开垦的处女地,还有许多缺陷和空白,这些都需要填补。应考者应有独特的眼光和超前的意识去思索,去发现,去研究。最后,要从寻找前人研究的不足处和错误处选题,在前人已提出来的研究课题中,许多虽已有初步的研究成果,但随着社会的不断发展,还有待于丰富、完整和发展,这种补充性或纠正性的研究课题,也是有科学价值和现实指导意义的。 第二、要根据自己的能力选择切实可行的课题。毕业论文的写作是一种创造性劳动,不但要有考生个人的见解和主张,同时还需要具备一定的客观条件。由于考生个人的主观、客观条件都是各不相同的,因此在选题时,还应结合自己的特长、兴趣及所具备的客观条件来选题。具体地说,考生可从以下三个方面来综合考虑。首先,要有充足的资料来源。“巧妇难为无米之炊”,在缺少资料的情况下,是很难写出高质量的论文的。选择一个具有丰富资料来源的课题,对课题深入研究与开展很有帮助。其次,要有浓厚的研究兴趣,选择自己感兴趣的课题,可以激发自己研究的热情,调动自己的主动性和积极性,能够以专心、细心、恒心和耐心的积极心态去完成。最后,要能结合发挥自己的业务专长,每个考生无论能力水平高低,工作岗位如何,都有自己的业务专长,选择那些能结合自己工作、发挥自己业务专长的课题,对顺利完成课题的研究大有益处。 致 谢 这次论文的完成,不止是我自己的努力,同时也有老师的指导,同学的帮助,以及那些无私奉献的前辈,正所谓你知道的越多的时候你才发现你知道的越少,通过这次论文,我想我成长了很多,不只是磨练了我的知识厚度,也使我更加确定了我今后的目标:为今后的计算机事业奋斗。在此我要感谢我的指导老师——***老师,感谢您的指导,才让我有了今天这篇论文,您不仅是我的论文导师,也是我人生的导师,谢谢您!我还要感谢我的同学,四年的相处,虽然我未必记得住每分每秒,但是我记得每一个有你们的精彩瞬间,我相信通过大学的历练,我们都已经长大,变成一个有担当,有能力的新时代青年,感谢你们的陪伴,感谢有你们,这篇论文也有你们的功劳,我想毕业不是我们的相处的结束,它是我们更好相处的开头,祝福你们!我也要感谢父母,这是他们给我的,所有的一切;感谢母校,尽管您不以我为荣,但我一直会以我是一名农大人为荣。 通过这次毕业设计,我学习了很多新知识,也对很多以前的东西有了更深的记忆与理解。漫漫求学路,过程很快乐。我要感谢信息与管理科学学院的老师,我从他们那里学到了许多珍贵的知识和做人处事的道理,以及科学严谨的学术态度,令我受益良多。同时还要感谢学院给了我一个可以认真学习,天天向上的学习环境和机会。 即将结束*大学习生活,我感谢****大学提供了一次在**大接受教育的机会,感谢院校老师的无私教导。感谢各位老师审阅我的论文。 毕业设计(论文)原创性声明和使用授权说明 原创性声明 本人郑重承诺:所呈交的毕业设计(论文),是我个人在指导教师的指导下进行的研究工作及取得的成果。尽我所知,除文中特别加以标注和致谢的地方外,不包含其他人或组织已经发表或公布过的研究成果,也不包含我为获得 及其它教育机构的学位或学历而使用过的材料。对本研究提供过帮助和做出过贡献的个人或集体,均已在文中作了明确的说明并表示了谢意。 作 者 签 名:       日  期:        ​​​​​​​​​​​​ 指导教师签名:        日  期:        使用授权说明 本人完全了解 大学关于收集、保存、使用毕业设计(论文)的规定,即:按照学校要求提交毕业设计(论文)的印刷本和电子版本;学校有权保存毕业设计(论文)的印刷本和电子版,并提供目录检索与阅览服务;学校可以采用影印、缩印、数字化或其它复制手段保存论文;在不以赢利为目的前提下,学校可以公布论文的部分或全部内容。 作者签名:        日  期:        ​​​​​​​​​​​​ 学位论文原创性声明 本人郑重声明:所呈交的论文是本人在导师的指导下独立进行研究所取得的研究成果。除了文中特别加以标注引用的内容外,本论文不包含任何其他个人或集体已经发表或撰写的成果作品。对本文的研究做出重要贡献的个人和集体,均已在文中以明确方式标明。本人完全意识到本声明的法律后果由本人承担。 作者签名: 日期: 年 月 日 学位论文版权使用授权书 本学位论文作者完全了解学校有关保留、使用学位论文的规定,同意学校保留并向国家有关部门或机构送交论文的复印件和电子版,允许论文被查阅和借阅。本人授权      大学可以将本学位论文的全部或部分内容编入有关数据库进行检索,可以采用影印、缩印或扫描等复制手段保存和汇编本学位论文。 涉密论文按学校规定处理。 作者签名: 日期: 年 月 日 导师签名: 日期: 年 月 日 独 创 声 明 本人郑重声明:所呈交的毕业设计(论文),是本人在指导老师的指导下,独立进行研究工作所取得的成果,成果不存在知识产权争议。尽我所知,除文中已经注明引用的内容外,本设计(论文)不含任何其他个人或集体已经发表或撰写过的作品成果。对本文的研究做出重要贡献的个人和集体均已在文中以明确方式标明。 本声明的法律后果由本人承担。   作者签名: 年 月 日   毕业设计(论文)使用授权声明 本人完全了解**学院关于收集、保存、使用毕业设计(论文)的规定。 本人愿意按照学校要求提交学位论文的印刷本和电子版,同意学校保存学位论文的印刷本和电子版,或采用影印、数字化或其它复制手段保存设计(论文);同意学校在不以营利为目的的前提下,建立目录检索与阅览服务系统,公布设计(论文)的部分或全部内容,允许他人依法合理使用。 (保密论文在解密后遵守此规定)   作者签名: 年 月 日 基本要求:写毕业论文主要目的是培养学生综合运用所学知识和技能,理论联系实际,独立分析,解决实际问题的能力,使学生得到从事本专业工作和进行相关的基本训练。毕业论文应反映出作者能够准确地掌握所学的专业基础知识,基本学会综合运用所学知识进行科学研究的方法,对所研究的题目有一定的心得体会,论文题目的范围不宜过宽,一般选择本学科某一重要问题的一个侧面。 毕业论文的基本教学要求是: 1、培养学生综合运用、巩固与扩展所学的基础理论和专业知识,培养学生独立分析、解决实际问题能力、培养学生处理数据和信息的能力。2、培养学生正确的理论联系实际的工作作风,严肃认真的科学态度。3、培养学生进行社会调查研究;文献资料收集、阅读和整理、使用;提出论点、综合论证、总结写作等基本技能。 毕业论文是毕业生总结性的独立作业,是学生运用在校学习的基本知识和基础理论,去分析、解决一两个实际问题的实践锻炼过程,也是学生在校学习期间学习成果的综合性总结,是整个教学活动中不可缺少的重要环节。撰写毕业论文对于培养学生初步的科学研究能力,提高其综合运用所学知识分析问题、解决问题能力有着重要意义。 毕业论文在进行编写的过程中,需要经过开题报告、论文编写、论文上交评定、论文答辩以及论文评分五个过程,其中开题报告是论文进行的最重要的一个过程,也是论文能否进行的一个重要指标。 撰写意义:1.撰写毕业论文是检验学生在校学习成果的重要措施,也是提高教学质量的重要环节。大学生在毕业前都必须完成毕业论文的撰写任务。申请学位必须提交相应的学位论文,经答辩通过后,方可取得学位。可以这么说,毕业论文是结束大学学习生活走向社会的一个中介和桥梁。毕业论文是大学生才华的第一次显露,是向祖国和人民所交的一份有份量的答卷,是投身社会主义现代化建设事业的报到书。一篇毕业论文虽然不能全面地反映出一个人的才华,也不一定能对社会直接带来巨大的效益,对专业产生开拓性的影响。但是,实践证明,撰写毕业论文是提高教学质量的重要环节,是保证出好人才的重要措施。 2.通过撰写毕业论文,提高写作水平是干部队伍“四化”建设的需要。党中央要求,为了适应现代化建设的需要,领导班子成员应当逐步实现“革命化、年轻化、知识化、专业化”。这个“四化”的要求,也包含了对干部写作能力和写作水平的要求。 3.提高大学生的写作水平是社会主义物质文明和精神文明建设的需要。在新的历史时期,无论是提高全族的科学文化水平,掌握现代科技知识和科学管理方法,还是培养社会主义新人,都要求我们的干部具有较高的写作能力。在经济建设中,作为领导人员和机关的办事人员,要写指示、通知、总结、调查报告等应用文;要写说明书、广告、解说词等说明文;还要写科学论文、经济评论等议论文。在当今信息社会中,信息对于加快经济发展速度,取得良好的经济效益发挥着愈来愈大的作用。写作是以语言文字为信号,是传达信息的方式。信息的来源、信息的收集、信息的储存、整理、传播等等都离不开写作。 论文种类:毕业论文是学术论文的一种形式,为了进一步探讨和掌握毕业论文的写作规律和特点,需要对毕业论文进行分类。由于毕业论文本身的内容和性质不同,研究领域、对象、方法、表现方式不同,因此,毕业论文就有不同的分类方法。 按内容性质和研究方法的不同可以把毕业论文分为理论性论文、实验性论文、描述性论文和设计性论文。后三种论文主要是理工科大学生可以选择的论文形式,这里不作介绍。文科大学生一般写的是理论性论文。理论性论文具体又可分成两种:一种是以纯粹的抽象理论为研究对象,研究方法是严密的理论推导和数学运算,有的也涉及实验与观测,用以验证论点的正确性。另一种是以对客观事物和现象的调查、考察所得观测资料以及有关文献资料数据为研究对象,研究方法是对有关资料进行分析、综合、概括、抽象,通过归纳、演绎、类比,提出某种新的理论和新的见解。 按议论的性质不同可以把毕业论文分为立论文和驳论文。立论性的毕业论文是指从正面阐述论证自己的观点和主张。一篇论文侧重于以立论为主,就属于立论性论文。立论文要求论点鲜明,论据充分,论证严密,以理和事实服人。驳论性毕业论文是指通过反驳别人的论点来树立自己的论点和主张。如果毕业论文侧重于以驳论为主,批驳某些错误的观点、见解、理论,就属于驳论性毕业论文。驳论文除按立论文对论点、论据、论证的要求以外,还要求针锋相对,据理力争。 按研究问题的大小不同可以把毕业论文分为宏观论文和微观论文。凡届国家全局性、带有普遍性并对局部工作有一定指导意义的论文,称为宏观论文。它研究的面比较宽广,具有较大范围的影响。反之,研究局部性、具体问题的论文,是微观论文。它对具体工作有指导意义,影响的面窄一些。 另外还有一种综合型的分类方法,即把毕业论文分为专题型、论辩型、综述型和综合型四大类: 1.专题型论文。这是分析前人研究成果的基础上,以直接论述的形式发表见解,从正面提出某学科中某一学术问题的一种论文。如本书第十二章例文中的《浅析领导者突出工作重点的方法与艺术》一文,从正面论述了突出重点的工作方法的意义、方法和原则,它表明了作者对突出工作重点方法的肯定和理解。2.论辩型论文。这是针对他人在某学科中某一学术问题的见解,凭借充分的论据,着重揭露其不足或错误之处,通过论辩形式来发表见解的一种论文。3.综述型论文。这是在归纳、总结前人或今人对某学科中某一学术问题已有研究成果的基础上,加以介绍或评论,从而发表自己见解的一种论文。4.综合型论文。这是一种将综述型和论辩型两种形式有机结合起来写成的一种论文。如《关于中国民族关系史上的几个问题》一文既介绍了研究民族关系史的现状,又提出了几个值得研究的问题。因此,它是一篇综合型的论文。 写作步骤:毕业论文是高等教育自学考试本科专业应考者完成本科阶段学业的最后一个环节,它是应考者的 总结 性独立作业,目的在于总结学习专业的成果,培养综合运用所学知识解决实际 问题 的能力。从文体而言,它也是对某一专业领域的现实问题或 理论 问题进行 科学 研究 探索的具有一定意义的论说文。完成毕业论文的撰写可以分两个步骤,即选择课题和研究课题。 首先是选择课题。选题是论文撰写成败的关键。因为,选题是毕业论文撰写的第一步,它实际上就是确定“写什么”的问题,亦即确定科学研究的方向。如果“写什么”不明确,“怎么写”就无从谈起。 教育部自学考试办公室有关对毕业论文选题的途径和要求是“为鼓励理论与工作实践结合,应考者可结合本单位或本人从事的工作提出论文题目,报主考学校审查同意后确立。也可由主考学校公布论文题目,由应考者选择。毕业论文的总体要求应与普通全日制高等学校相一致,做到通过论文写作和答辩考核,检验应考者综合运用专业知识的能力”。但不管考生是自己任意选择课题,还是在主考院校公布的指定课题中选择课题,都要坚持选择有科学价值和现实意义的、切实可行的课题。选好课题是毕业论文成功的一半。 第一、要坚持选择有科学价值和现实意义的课题。科学研究的目的是为了更好地认识世界、改造世界,以推动社会的不断进步和发展 。因此,毕业论文的选题,必须紧密结合社会主义物质文明和精神文明建设的需要,以促进科学事业发展和解决现实存在问题作为出发点和落脚点。选题要符合科学研究的正确方向,要具有新颖性,有创新、有理论价值和现实的指导意义或推动作用,一项毫无意义的研究,即使花很大的精力,表达再完善,也将没有丝毫价值。具体地说,考生可从以下三个方面来选题。首先,要从现实的弊端中选题,学习了专业知识,不能仅停留在书本上和理论上,还要下一番功夫,理论联系实际,用已掌握的专业知识,去寻找和解决工作实践中急待解决的问题。其次,要从寻找科学研究的空白处和边缘领域中选题,科学研究。还有许多没有被开垦的处女地,还有许多缺陷和空白,这些都需要填补。应考者应有独特的眼光和超前的意识去思索,去发现,去研究。最后,要从寻找前人研究的不足处和错误处选题,在前人已提出来的研究课题中,许多虽已有初步的研究成果,但随着社会的不断发展,还有待于丰富、完整和发展,这种补充性或纠正性的研究课题,也是有科学价值和现实指导意义的。 第二、要根据自己的能力选择切实可行的课题。毕业论文的写作是一种创造性劳动,不但要有考生个人的见解和主张,同时还需要具备一定的客观条件。由于考生个人的主观、客观条件都是各不相同的,因此在选题时,还应结合自己的特长、兴趣及所具备的客观条件来选题。具体地说,考生可从以下三个方面来综合考虑。首先,要有充足的资料来源。“巧妇难为无米之炊”,在缺少资料的情况下,是很难写出高质量的论文的。选择一个具有丰富资料来源的课题,对课题深入研究与开展很有帮助。其次,要有浓厚的研究兴趣,选择自己感兴趣的课题,可以激发自己研究的热情,调动自己的主动性和积极性,能够以专心、细心、恒心和耐心的积极心态去完成。最后,要能结合发挥自己的业务专长,每个考生无论能力水平高低,工作岗位如何,都有自己的业务专长,选择那些能结合自己工作、发挥自己业务专长的课题,对顺利完成课题的研究大有益处。 致 谢 这次论文的完成,不止是我自己的努力,同时也有老师的指导,同学的帮助,以及那些无私奉献的前辈,正所谓你知道的越多的时候你才发现你知道的越少,通过这次论文,我想我成长了很多,不只是磨练了我的知识厚度,也使我更加确定了我今后的目标:为今后的计算机事业奋斗。在此我要感谢我的指导老师——***老师,感谢您的指导,才让我有了今天这篇论文,您不仅是我的论文导师,也是我人生的导师,谢谢您!我还要感谢我的同学,四年的相处,虽然我未必记得住每分每秒,但是我记得每一个有你们的精彩瞬间,我相信通过大学的历练,我们都已经长大,变成一个有担当,有能力的新时代青年,感谢你们的陪伴,感谢有你们,这篇论文也有你们的功劳,我想毕业不是我们的相处的结束,它是我们更好相处的开头,祝福你们!我也要感谢父母,这是他们给我的,所有的一切;感谢母校,尽管您不以我为荣,但我一直会以我是一名农大人为荣。 通过这次毕业设计,我学习了很多新知识,也对很多以前的东西有了更深的记忆与理解。漫漫求学路,过程很快乐。我要感谢信息与管理科学学院的老师,我从他们那里学到了许多珍贵的知识和做人处事的道理,以及科学严谨的学术态度,令我受益良多。同时还要感谢学院给了我一个可以认真学习,天天向上的学习环境和机会。 即将结束*大学习生活,我感谢****大学提供了一次在**大接受教育的机会,感谢院校老师的无私教导。感谢各位老师审阅我的论文。 - 83 - _1430218751.vsd � � � +FriendTable() +getNextPage() : int +getPreviousPage() : int +getLastPage() : int +getFirstPage() : int +getTotolPage() : int +getCurrentPage() : int +getData(in status_ : List) : Object[][] +initResultData(in data : Object[][]) +getPageData() : Object[][] +initTable() +getColumn(in table : JTable, in width : int[]) : TableColumnModel +settingTable(in model : DefaultTableModel) +currentPage : int = 1 +pageCount : int = 30 +totalPage : int = 0 +totalRowCount : int = 0 +column : int = 0 +restCount : int +resultData : Object[][] +width : int[] = { 150, 100, 50, 150, 300, 50, 50, 50, 100 } +users : List +columnNames : String[] = { "id", "昵称", "性别", "注册时间", "个人描述", "关注数", "粉丝数", "微博数", "查看微博" } +model : FriendshipTableModel FriendTable _1430220518.vsd � � � +RepostTable() +getNextPage() : int +getPreviousPage() : int +getLastPage() : int +getFirstPage() : int +getTotolPage() : int +getCurrentPage() : int +getData(in status_ : List) : Object[][] +initResultData(in data : Object[][]) +getPageData() : Object[][] +initTable() +getColumn(in table : JTable, in width : int[]) : TableColumnModel +settingTable(in model : DefaultTableModel) +currentPage : int = 1 +pageCount : int = 30 +totalPage : int = 0 +totalRowCount : int = 0 +column : int = 0 +restCount : int +resultData : Object[][] +width : int[] = { 100, 100, 100, 400 } +reposts : List +columnNames : String[] = { "转发id", "转发时间", "转发者", "转发内容" } +model : DefaultTableModel RepostTable _1430511117.vsd � 系统用户 _1430512117.vsd � � � +searchFriends(in user_id : String, in screen_name : String) -rs : ResultSet -sqlHelper : SqlHelper SearchFriend _1431173246.vsd 网络舆情信息采集系统 用户粉丝查看 用户微博查看 用户关注查看 用户关注搜索 用户粉丝搜索 用户微博展示 用户微博存储 微博用户存储 微博用户存储 用户粉丝展示 用户关系存储 微博用户存储 用户关注展示 用户关系存储 微博转发查看 微博评论查看 微博评论展示 微博评论存储 微博转发展示 微博转发存储 _1430511997.vsd � � � +searchFollowers(in user_id : String, in screen_name : String) -sqlHelper : SqlHelper -rs : ResultSet SearchFollower _1430510932.vsd � 系统用户 查看微博 查看粉丝 查看关注 _1430220542.vsd � � � +getReposts() +run() +repostId : String -page : int = 1 -total : long = 1 -sqlHelper : SqlHelper RepostGrab _1430219343.vsd � � � +getComments() +run() +commentId : String -page : int = 1 -total : long = 1 -sqlHelper : SqlHelper CommentGrab _1430220170.vsd � � � +CommentView(in jf : JFrame, in title : String, in modal : boolean) +loadComment() -jd : JDialog -panel_comment : JPanel -previous : JButton -next : JButton -label : JLabel -commentList : CommentTable -commentView : JScrollPane CommentView _1430220490.vsd � � � +RepostView(in jf : JFrame, in title : String, in modal : boolean) +loadRepost() -jd : JDialog -panel_repost : JPanel -previous : JButton -next : JButton -label : JLabel -repostList : RepostTable -repostView : JScrollPane RepostView _1430219187.vsd � � � +CommentTable() +getNextPage() : int +getPreviousPage() : int +getLastPage() : int +getFirstPage() : int +getTotolPage() : int +getCurrentPage() : int +getData(in status_ : List) : Object[][] +initResultData(in data : Object[][]) +getPageData() : Object[][] +initTable() +getColumn(in table : JTable, in width : int[]) : TableColumnModel +settingTable(in model : DefaultTableModel) +currentPage : int = 1 +pageCount : int = 30 +totalPage : int = 0 +totalRowCount : int = 0 +column : int = 0 +restCount : int +resultData : Object[][] +width : int[] = { 100, 100, 100, 400 } +comments : List +columnNames : String[] = { "评论id", "评论时间", "评论者", "评论内容" } +model : DefaultTableModel CommentTable _1430215959.vsd � � � +getId() : String +setId(in id : String) +getScreenName() : String +setScreenName(in screenName : String) +getProvince() : int +setProvince(in province : int) +getCity() : int +setCity(in city : int) +getLocation() : String +setLocation(in location : String) +getDescription() : String +setDescription(in description : String) +getUrl() : String +setUrl(in url : String) +getProfileImageUrl() : String +setProfileImageUrl(in profileImageUrl : String) +getUserDomain() : String +setUserDomain(in userDomain : String) +getGender() : String +setGender(in gender : String) +getFollowersCount() : int +setFollowersCount(in followersCount : int) +getFriendsCount() : int +setFriendsCount(in friendsCount : int) +getStatusesCount() : int +setStatusesCount(in statusesCount : int) +getFavouritesCount() : int +setFavouritesCount(in favouritesCount : int) +getCreatedAt() : Date +setCreatedAt(in createdAt : Date) -id : String -screenName : String -province : int -city : int -location : String -description : String -url : String -profileImageUrl : String -userDomain : String -gender : String -followersCount : int -friendsCount : int -statusesCount : int -favouritesCount : int -createdAt : Date +users : List User_ _1430218278.vsd � � � +getFollowers() +run() +screen_name : String -page : int = 1 -total : long = 1 -client : HttpClient -sqlHelper : SqlHelper FollowerGrab _1430218600.vsd � � � +getFriends() +run() +screen_name : String -page : int = 1 -total : long = 1 -client : HttpClient -sqlHelper : SqlHelper FriendGrab _1430217963.vsd � � � +FollowerTable() +getNextPage() : int +getPreviousPage() : int +getLastPage() : int +getFirstPage() : int +getTotolPage() : int +getCurrentPage() : int +getData(in status_ : List) : Object[][] +initResultData(in data : Object[][]) +getPageData() : Object[][] +initTable() +getColumn(in table : JTable, in width : int[]) : TableColumnModel +settingTable(in model : DefaultTableModel) +currentPage : int = 1 +pageCount : int = 30 +totalPage : int = 0 +totalRowCount : int = 0 +column : int = 0 +restCount : int +resultData : Object[][] +width : int[] = { 150, 100, 50, 150, 300, 50, 50, 50, 100 } +users : List +columnNames : String[] = { "id", "昵称", "性别", "注册时间", "个人描述", "关注数", "粉丝数", "微博数", "查看微博" } +model : FriendshipTableModel FollowerTable _1430214597.vsd � � � +getUser() : User +setUser(in user : User) +getCreatedAt() : Date +setCreatedAt(in createdAt : Date) +getId() : String +setId(in id : String) +getMid() : String +setMid(in mid : String) +getIdstr() : long +setIdstr(in idstr : long) +getText() : String +setText(in text : long) +getSource() : Source +setSource(in source : Source) +isFavorited() : boolean +setFavorited(in favorited : boolean) +isTruncated() : boolean +setTruncated(in truncated : boolean) +getInReplyToStatusId() : long +setInReplyToStatusId(in inReplyToStatusId : long) +getInReplyToUserId() : long +setInReplyToUserId(in inReplyToUserId : long) +getInReplyToScreenName() : String +setInReplyToScreenName(in inReplyToScreenName : String) +getThumbnailPic() : String +setThumbnailPic(in thumbnailPic : String) +getBmiddlePic() : String +setBmiddlePic(in bmiddlePic : String) +getOriginalPic() : String +setOriginalPic(in originalPic : String) +getRetweetedStatus() : Status +setRetweetedStatus(in retweetedStatus : Status) +getGeo() : String +setGeo(in geo : String) +getLatitude() : double +setLatitude(in latitude : double) +getLongitude() : double +setLongitude(in longitude : double) +getRepostsCount() : int +setRepostsCount(in repostsCount : int) +getCommentsCount() : int +setCommentsCount(in commentsCount : int) +getAnnotations() : String +setAnnotations(in annotations : String) +getMlevel() : int +setMlevel(in mlevel : int) -user : User = null -createdAt : Date -id : String -mid : String -idstr : int -text : String -source : Source -favorited : boolean -truncated : boolean -inReplyToStatusId : long -inReplyToUserId : long -inReplyToScreenName : String -thumbnailPic : String -bmiddlePic : String -originalPic : String -retweetedStatus : Status -geo : String -latitude : double = -1 -longitude : double = -1 -repostsCount : int -commentsCount : int -annotations : String -mlevel : int -status : List Status_ _1430214616.vsd � � � +Home() -loadNorthPanel() -redrawpanel() +clearPanel() +loadWeibo() +loadFollower() +loadFriend() +main(in args : String[]) _1430208305.vsd � � � -getWeibo() +run() +screen_name : String = null -page : int = 1 -total : long = 1 -sqlHelper : SqlHelper WeiboGrab _1430213761.vsd � � � +WeiboTable() +getNextPage() : int +getPreviousPage() : int +getLastPage() : int +getFirstPage() : int +getTotolPage() : int +getCurrentPage() : int +getData(in status_ : List) : Object[][] +initResultData(in data : Object[][]) +getPageData() : Object[][] +initTable() +getColumn(in table : JTable, in width : int[]) : TableColumnModel +settingTable(in model : DefaultTableModel) +currentPage : int = 1 +pageCount : int = 30 +totalPage : int = 0 +totalRowCount : int = 0 +column : int = 0 +restCount : int +resultData : Object[][] +width : int[] = { 150, 100, 150, 300, 50, 50, 100, 100 } +status : List +columnNames : String[] = { "微博id", "发布者", "发布时间", "微博内容", "转发数", "评论数", "查看转发", "查看评论" } +model : WeiboTableModel WeiboTable
本文档为【网络舆情数据采集系统开发毕业论文】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
个人认证用户
不系舟红枫
从教近30年,经验丰富,教学水平较高
格式:doc
大小:5MB
软件:Word
页数:89
分类:工学
上传时间:2019-01-23
浏览量:17