`
yangzisai
  • 浏览: 85703 次
  • 性别: Icon_minigender_1
  • 来自: 东莞
社区版块
存档分类
最新评论

RSS开发过程

阅读更多
在本章中将会介绍3个实例,首先分别使用Struts和Hibernate开发两个实例,帮助读者理解Struts和Hibernate各自单独的使用方法,最后将Struts和Hibernate结合起来,完成最终的实例。

本章介绍的3个例子都与RSS阅读器有关,RSS是在线共享内容的一种简易方式(Really Simple Syndication)。通常用于新闻和其他按时间先后顺序排列的网站,例如Blog。一个RSS包含很多新闻条目,一个新闻条目的介绍可能包含新闻的全部介绍,或者仅仅是额外的内容和简短的介绍。这些条目通常都能链接到全部的内容。使用RSS订阅能更快速获取信息,用户可以在客户端借助于支持RSS的阅读软件(例如SharpReader、NewzCrawler和FeedDemon这些软件),在不打开网站页面的情况下阅读支持RSS输出的网站内容。除了软件形式的RSS阅读器,在线网站形式的RSS阅读器也得到了广泛的应用,本章的实例就是实现简单的RSS在线网站阅读器。

第一个实例是纯粹采用Struts技术的简单RSS阅读器,用户通过输入RSS的地址来阅读此RSS中的文章信息,实例中没有采用数据库,所以不需要用到Hibernate。第二个实例是RSS自动更新器,此实例没有前台界面,仅仅使用了Hibernate来定时地对数据库中的RSS信息进行更新操作。第三个实例结合利用Struts和Hibernate,实现了一个有后台数据库支持的RSS在线阅读器。

12.1  RSS知识
RSS(Really Simple Syndication)是一种利用XML文件来发布网站内容的技术,它是一种对网站内容进行快速阅读的方式。当RSS技术没有出现的时候,用户要阅读新闻等信息,必须访问许多不同的特定网站,这对于很多人来说是一件费时的事情,但是有了RSS技术之后,用户可以通过RSS阅读器(软件或者网站形式)订阅RSS格式的Feed,从这些Feed中阅读需要的信息。同时由于RSS数据流很小,所以此技术也提高了信息的可访问性。

最初的0.90版本RSS是由Netscape公司设计的,目的是用来建立一个整合了各主要新闻站点内容的门户,但是0.90版本的RSS规范过于复杂,而一个简化的RSS 0.91版本也随着Netscape公司对该项目的放弃而于2000年暂停。

不久,一家专门从事博客写作软件开发的公司UserLand接手了RSS 0.91版本,并把它作为其博客写作软件的基础功能之一继续开发,逐步推出了0.92、0.93和0.94版本。随着网络博客的流行,RSS作为一种基本的功能也被越来越多的网站和博客软件支持。

在UserLand公司接手并不断开发RSS的同时,很多的专业人士认识到需要通过一个第三方、非商业的组织,把RSS发展成为一个通用的规范,并进一步标准化。于是2001年一个联合小组在0.90版本RSS的开发原则下,以W3C新一代的语义网技术RDF(Resource Description Framework)为基础,对RSS进行了重新定义,发布RSS1.0,并将RSS定义为“RDF Site Summary”。但是这项工作没有与UserLand公司进行有效的沟通,UserLand公司也不承认RSS 1.0的有效性,并坚持按照自己的设想进一步开发出RSS的后续版本,到2002年9月发布了最新版本RSS 2.0,UserLand公司将RSS定义为“Really Simple Syndication”。目前RSS已经分化为RSS 0.9x/2.0和RSS 1.0两个阵营,由于分歧的存在和RSS 0.9x/2.0的广泛应用现状,RSS 1.0还没有成为标准化组织的真正标准。在本章的实例中只考虑使用RSS 2.0标准。

RSS格式是符合标准的XML格式,RSS 2.0的语法是非常简单并且严格的,如下示例所示。

<?xml version="1.0" encoding="ISO-8859-1" ?>

<rss version="2.0">

<channel>

  <title>W3Schools Home Page</title>

  <link>http://www.w3schools.com</link>

  <description>Free web building tutorials</description>

  <item>

     <title>RSS Tutorial</title>

     <link>http://www.w3schools.com/rss</link>

     <description>New RSS tutorial on W3Schools</description>

  </item>

  <item>

     <title>XML Tutorial</title>

     <link>http://www.w3schools.com/xml</link>

     <description>New XML tutorial on W3Schools</description>

  </item>

</channel>

</rss>

为网站提供RSS支持,就是为网站的内容生成如上所示的RSS格式的文件,可以手动编写此XML文件,也可以用工具自动生成此文件。

RSS文件的第一行表明了这是一个XML文件,并使用了XML 1.0标准和ISO-8859-1 (Latin-1/West European)字符集。

<?xml version="1.0" encoding="ISO-8859-1" ?>

第二行是RSS声明,说明这是一个RSS文件并且其版本为2.0。

<rss version="2.0">

<channel>元素定义了一个RSS的Feed,即频道。可以把一个Feed看作是一个网站,或者是网站的一个子内容。比如在新浪网的RSS“频道聚合”中,可以看到许多不同的Feed,对应了各个专门的新闻类别,如图12-1所示。

上图中的每个XML标记即对应了一个Feed,也就是这里所说的<channel>元素。

<channel>

  <title>W3Schools Home Page</title>

  <link>http://www.w3schools.com</link>

  <description>Free web building tutorials</description>



图12-1

<channel>元素包括了3个必须的子元素:

    <title>  定义频道的标题(比如“W3Schools Home Page”)。

    <link>  定义频道的超链接地址(比如“http://www.w3schools.com”)。

    <description>  对此频道的描述(比如“Free web building tutorials”)。

除了这些必须的元素之外,<channel>元素还有一些可选子元素,如表12-1所示。

表12-1                                                    <channel>的可选子元素

元  素  名
描    述
元  素  名
描    述

<category>
定义feed的类别
<managingEditor>
Feed作者的邮件地址

<cloud>
定义feed更新之后的动作
<pubDate>
Feed的发布时间

<copyright>
版权信息
<rating>
Feed的PICS率

<docs>
Feed格式文档的URL
<skipDays>
定义RSS阅读器应该忽略的更新时间

<generator>
指明生成Feed的程序
<skipHours>
定义RSS阅读器应该忽略的更新时间(小时)

<image>
Feed的显示图像
<textInput>
Feed显示时的文字输入

<language>
Feed使用的语言
<ttl>
指定Feed的最小缓存数

<lastBuildDate>
Feed最后被修改的时间
<webMaster>
网站管理员的邮件地址


每个<channel>元素可以包含一个或多个<item>元素。每个<item>元素定义了在RSS Feed中的一篇文章。

<item>

   <title>RSS Tutorial</title>

    <link>http://www.w3schools.com/rss</link>

    <description>New RSS tutorial on W3Schools</description>

</item>

<item>包括3个必须的子元素:

    <title>  定义此文章的标题(比如“RSS Tutorial”)。

    <link>  定义此文章的超链接地址(比如“http://www.w3schools.com/rss”)。

    <description>  对文章的描述(比如“New RSS tutorial on W3Schools”)。

除了这些必须的元素之外,<item>元素还有一些可选子元素,如表12-2所示。

表12-2                                                      <item>的可选子元素

元  素  名
描    述
元  素  名
描    述

<author>
文章作者
<guid>
文章的标示符

<category>
文章类别
<pubDate>
文章发布时间

<comments>
对文章的评论
<source>
文章的第三方源

<enclosure>
包含在文章中的其他类型文件
  

编写完成符合RSS格式的文件之后,就可以将此RSS文件发布在网上,并通过此RSS文件的URL来订阅。比如将上述的RSS文件发布到“www.w3schools.com/rss/myfirstrss.xml”之后,就可以通过此地址,订阅RSS Feed。

订阅RSS Feed可采用两种方式,第一种是使用RSS阅读软件,比如SharpReader,新浪点点通等。比如使用新浪点点通阅读器可以订阅多个Feed的内容,如图12-2所示。



图12-2

可以在其中添加Feed,如图12-3所示。

另一种是采用在线方式的RSS阅读器,比如Google Reader、Bloglines等。下面以Bloglines(www.bloglines.com)为例进行介绍,如图12-4所示。

同样可以在线的RSS阅读器中添加Feed,如图12-5所示。



图12-3



图12-4



12.2  利用Struts开发RSS在线阅读器
本节利用Struts实现一个简单的RSS在线阅读器。用户首先输入一个RSS Feed的地址,系统通过此地址得到Feed中所有的文章内容,并将文章的内容显示到页面上。由于此实例不需要数据库,所以没有采用Hibernate。

1.功能说明
(1)用户输入欲阅读的RSS Feed的地址,然后点击查看内容,系统找到用户输入的RSS文件,读取其中的内容,如图12-6所示。



图12-6

(2)若在此Feed中不存在文章,则显示“此Feed内目前没有包含文章”,如图12-7所示。



图12-7

(3)若Feed中存在文章,将文章的标题、作者和内容显示出来,并且将文章的列表作为文章的超链接,如图12-8所示。



图12-8

2.准备
此实例由于只采用了Struts,所以只要下载安装Struts,并将安装目录\lib目录下的各个.jar包和标签库中的tld文件导入工程。除了struts-config.xml和web.xml这两个配置文件之外。系统主要包括了以下主要部分:

(1)Item类:存放Feed中每一篇文章单元的内容,包括标题、作者、文章链接地址和文章内容。

(2)RssParser类:提供一个静态方法parseFeed()来解析feed中的内容,得到其中包含的所有文章。

(3)RssReaderAction类:根据用户输入的feed地址,调用RssParser中的方法得到所有的item,并将结果返回到页面。

(4)RssReardForm类:此form包含的主要成员为feed的地址,以及得到的一组item。

(5)Feed.jsp:此页面接受用户输入一个feed地址。

(6)List.jsp:此页面显示feed中包含的文章列表。

各部分集合之后如图12-9所示。



图12-9

3.实现
(1)首先,系统给用户展现一张Feed的输入页面(feed.jsp)。

<!-- 由于页面上采用中文,故需采用utf-8字符集 -->

<%@ page language="java" contentType="text/html; charset=utf-8"

    pageEncoding="utf-8"

%>

<!-- 声明页面上使用struts的html, logic, bean标签库 -->

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title>在线RSS阅读器</title>

</head>

<body>

<!-- 此form接受用户输入一个feed地址 -->

<html:form action="feed" method="post">

     <table border="0" cellspacing="0" cellpadding="0" align="left">

           <tr>

                 <td>请输入RSS Feed地址:</td>

                 <!-- 采用html:text标签来定义一个输入框 -->

                 <td><html:text property="address" /></td>

           </tr>

           <tr>

                 <!-- 采用html:submit来提交表单 -->

                 <td><html:submit property="login" value="查看内容" /></td>

           </tr>

    </table>

</html:form>

</body>

</html>

页面上定义了用于提交用户输入的Feed地址的form:

<html:form action="feed" method="post">

此form中包含一个输入框用,以得到用户输入的Feed地址:

<html:text property="address" />

当此form提交的时候,就会将此请求发送给“feed”对应的Action类去处理,即RssReaderAction。

(2)RssReaderAction类得到此请求之后,首先从Form中得到用户输入的Feed地址:

//得到对应的RssReaderForm

RssReaderForm rssReaderForm = (RssReaderForm) form;

//得到用户输入的rss feed地址

String address = rssReaderForm.getAddress();

然后用此地址作为参数调用RssParser类的parseFeed方法,此方法是一个静态方法,其作用是去访问此地址的RSS文件,并解析其中的文章内容,将里面所有的文章内容作为参数返回,返回值为List类型。

List items = RssParser.parseFeed(address);

通过上述的调用方式就得到了用户输入Feed地址中的文章列表(此列表有可能为空),接着,将得到的列表设置到form中,以供list.jsp页面显示。

rssReaderForm.setItems(items);

最后,RssReaderAction作跳转,前进到list.jsp页面。

return mapping.findForward("list");

下面是RssReaderAction类的完整代码。

import java.io.IOException;

import java.util.List;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts.action.Action;

import org.apache.struts.action.ActionForm;

import org.apache.struts.action.ActionForward;

import org.apache.struts.action.ActionMapping;

/**

* @author Chao Wu

*

* Description:

* <p>RssReaderAction类处理的主要工作是根据用户输入的feed地址,调用RssParser中的方法得到所有的item,并将

* 结果返回到页面

*

* Copyright:

* <p>

*/

public class RssReaderAction extends Action {

      /**

       * 此方法得到form的address属性,并调用RssParser的parseFeed方法,将得到的List赋到form中之后,做页面跳转

       * @param mapping

       * @param form

       * @param req

       * @param res

       * @return

       */

      public ActionForward execute(ActionMapping mapping, ActionForm form,

                  HttpServletRequest req, HttpServletResponse res)

                  throws IOException, ServletException {

             //得到对应的RssReaderForm

             RssReaderForm rssReaderForm = (RssReaderForm) form;

             //得到用户输入的rss feed地址

             String address = rssReaderForm.getAddress();

             //调用RssParser的parseFeed方法,解析此feed,若此feed不存在,或者发生了异常错误,返回为空List;

             //否则返回包含文章列表的List

             List items = RssParser.parseFeed(address);

             //将返回的item的列表赋到form中

             rssReaderForm.setItems(items);

             //跳转到list.jsp

             return mapping.findForward("list");

      }

}

下面是RssReaderForm类的完整代码。

import java.util.List;

import org.apache.struts.action.ActionForm;

/**

* @author Chao Wu

*

* Description:

* <p>此form包含的主要成员为feed的地址,以及得到的一组item

*

* Copyright:

* <p>

*/

public class RssReaderForm extends ActionForm {

       private static final long serialVersionUID = 1L;

       //从feed中得到的一组item

       private List items;

       //feed的地址

       private String address;

       //以下为items和address的get和set方法

       public String getAddress() {

             return address;

       }

       public void setAddress(String address) {

             this.address = address;

       }

       public List getItems() {

             return items;

       }

       public void setItems(List items) {

             this.items = items;

       }

}

(3)RssReaderAction处理完毕之后,就会前进到list.jsp页面,这张页面的主要作用就是显示解析出来的文章列表。页面上主要调用了以下的struts标签:

    Logic:empty标签  处理当文章列表为空的情况。

    Logic:notEmpty标签  当文章列表不为空的时候,显示文章列表。

    Logic:iterate标签  循环显示文章列表中的内容。

    Bean:write标签  显示文章的标题、链接、作者和内容。

List.jsp的内容如下所示。

<!-- 由于页面上采用中文,故需采用utf-8字符集 -->

<%@ page language="java" contentType="text/html; charset=utf-8"

    pageEncoding="utf-8"%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

<!-- 声明页面上使用struts的html, logic, bean标签库 -->

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>

<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic"%>

<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>

<!-- 此页面显示feed中包含的文章列表 -->

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title>在线RSS阅读器</title>

</head>

<body>

<!-- 若没有得到文章,则显示提示信息,使用logic:empty标签来实现此功能 -->

<logic:empty name="rssReaderForm" property="items">

      <center><strong>此Feed内目前没有包含文章</strong></center>

</logic:empty>

<!-- 若文章列表不为空,则循环显示每篇文章的题目、作者、链接和内容 -->

<logic:notEmpty name="rssReaderForm" property="items">

      <center><strong>文章列表:</strong></center>

      <br>

      <!-- 使用logic:iterate标签循环显示文章 -->

      <logic:iterate indexId="index" id="item" name="rssReaderForm" property="items">

            <table>

                    <tr>

                           <!-- 分别得到item的title, url和author信息 -->

                           <td noWrap class="allcapsCenter">

                           <strong>标题:</strong>

                           <A href="<bean:write name='item' property='url' />">

                                <bean:write   name="item" property="title" />

                           </A>

                               (<strong>by: </strong><bean:write name="item" property="author" />)

                           </td>

                    </tr>

                    <tr>

                          <!-- 显示文章内容 -->

                          <td noWrap class="allcapsCenter">

                          <bean:write name="item"   property="description" />

                    </td>

                    <tr>

                          </table>

                          <br>

    </logic:iterate>

</logic:notEmpty>

</TABLE>

</body>

</html>

其中下面代码的作用是从form中取出的items列表,判断其是否为空,如果为空的话,则显示字符串“此Feed内目前没有包含文章”。

<logic:empty name="rssReaderForm" property="items">

       <center><strong>此Feed内目前没有包含文章</strong></center>

</logic:empty>

显示效果如图12-10所示。



图12-10

若items列表不为空,则使用logic:iterate标签:

<logic:notEmpty name="rssReaderForm" property="items">

      <center><strong>文章列表:</strong></center>

      <br>

      <!-- 使用logic:iterate标签循环显示文章 -->

      <logic:iterate indexId="index" id="item" name="rssReaderForm" property="items">

在logic:iterate中嵌套的是每一篇文章的具体信息,iterate标签循环遍历form中的items集合,将集合中的对象命名为“item”。在嵌套的语句中,就可以用“item”的属性来得到需要显示的文章标题和作者等信息。

<A href="<bean:write name='item' property='url' />">

      <bean:write name="item" property="title" />

</A>

(<strong>by: </strong><bean:write name="item" property="author" />)

在上面的代码中,文章的链接地址用bean:write标签得到,并且嵌入在<a>标签中作为链接地址,从中可以看出,struts的标签可以嵌套在普通的html标签中。

通过这种方式,就可以在页面上显示Feed中包含的文章,如图12-11所示。



图12-11

(4)RssParser类用来解析RSS格式的XML文件,将其中的文章列表返回。定义Item来存放文章信息,每一个Item对象,对应了Feed中的一篇文章。Item类是一个简单的JavaBean,其中包含了4个成员:

    Title  文章标题。

    Description  文章内容。

    Author  作者。

    Url  全文链接地址。

这些成员的getter和setter方法,代码如下所示。

/**

* @author Chao Wu

*

* Description:

* <p>Item类存放Feed中每一篇文章单元的内容,包括标题、作者、文章链接地址和文章内容

*

* Copyright:

* <p>

*/

public class Item {

      private String title;      //文章标题

      private String description;   //文章内容

      private String author;     //作者

      private String url;        //全文链接地址

     

      //Item的构造函数

      public Item(String title, String description, String author, String url)

      {

            this.title = title;

            this.description = description;

            this.author = author;

            this.url = url;

      }

      //以下为title,description,author和url四个成员的get和set方法

      public String getAuthor() {

            return author;

      }

      public void setAuthor(String author) {

            this.author = author;

      }

      public String getDescription() {

            return description;

      }

      public void setDescription(String description) {

            this.description = description;

      }

      public String getTitle() {

            return title;

      }

      public void setTitle(String title) {

            this.title = title;

      }

      public String getUrl() {

            return url;

      }

      public void setUrl(String url) {

            this.url = url;

      }

}

RssParser类中提供了一个静态方法parseFeed()来解析Feed地址。

public static List parseFeed(String address)

此方法的主要思路为:RSS格式文件是标准的XML文件格式,所以可以通过标准的XML读取方式来访问其中的内容。在这里使用SAX方式来访问XML文件的内容。首先定义返回的文章列表。

List result = new ArrayList();

接着定义DocumentBuilderFactory,DocumentBuilder和Document,用以解析代表rss feed的XML文件,并通过DocumentBuilderFactory.newInstance()方法得到DocumentBuilderFactory对象。

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();

DocumentBuilder db;

Document doc;

然后利用DocumentBuilderFactory对象的newDocumentBuilder方法得到DocumentBuilder对象,此DocumentBuilder对象的作用是根据xml文件的url地址生成Document对象。

db = dbf.newDocumentBuilder();

doc对象包含需要解析的feed的xml文件。

doc = db.parse(address);

feed的xml文件的组成单位是item,从doc中取出所有的item。

NodeList nl = doc.getElementsByTagName("item");

接着遍历这些item,取得其中的title, author, description和url等信息。

for (int i = 0; i < nl.getLength(); i++) {

       Node node = nl.item(i);

       NodeList nl2 = node.getChildNodes();

       Node nodeTitle = nl2.item(1);

       Node nodeAuthor = nl2.item(2);

       Node nodeUrl = nl2.item(3);

       Node nodeDescription = nl2.item(4);

通过得到的title、author、description和url构造Item对象。

Item item = new Item(title, description, author, url);

最后将生成的item放到result中,以便返回。

result.add(item);

下面是此方法的完整代码。

/*

* Created on

*

* TODO To change the template for this generated file go to

* Window - Preferences - Java - Code Style - Code Templates

*/

import java.io.IOException;

import java.util.ArrayList;

import java.util.List;

import javax.xml.parsers.DocumentBuilder;

import javax.xml.parsers.DocumentBuilderFactory;

import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;

import org.w3c.dom.Node;

import org.w3c.dom.NodeList;

import org.xml.sax.SAXException;

/**

* @author Chao Wu

*

* Description:

* <p>RssParser类提供一个静态方法parseFeed()来解析某feed中的内容,得到其中包含的所有文章

*

* Copyright:

* <p>

*/

public class RssParser {

public static List parseFeed(String address) {

              //result包含从feed中得到的一组Item对象

              List result = new ArrayList();

              //定义DocumentBuilderFactory,DocumentBuilder和Document,用以解析代表rss feed的XML文件

              //通过DocumentBuilderFactory.newInstance()方法得到Document-
BzuilderFactory对象

              DocumentBuilderFactory dbf = DocumentBuilderFactory.newIns-
tance();

              DocumentBuilder db;

              Document doc;

              try {

                    //利用DocumentBuilderFactory对象的newDocumentBuilder方法得到DocumentBuilder对象

                   //此DocumentBuilder对象的作用是根据xml文件的url地址生成Document对象

              db = dbf.newDocumentBuilder();

              //doc对象包含需要解析的feed的xml文件

              doc = db.parse(address);

              //feed的xml文件的组成单位是item,从doc中取出所有的item

              NodeList nl = doc.getElementsByTagName("item");

              //遍历这些item,取得其中的title, author, description和url等信息

              for (int i = 0; i < nl.getLength(); i++) {

                      Node node = nl.item(i);

                      NodeList nl2 = node.getChildNodes();

                      Node nodeTitle = nl2.item(1);

                      Node nodeAuthor = nl2.item(2);

                      Node nodeUrl = nl2.item(3);

                      Node nodeDescription = nl2.item(4);

                      String title = nodeTitle.getFirstChild().getNodeValue();

                      String description = nodeDescription.getFirstChild(). getNodeValue();

                      String author = nodeAuthor.getFirstChild().getNode-
Value();

                      String url = nodeUrl.getFirstChild().getNodeValue();

                      //通过得到的title, author, description和url构造Item对象

                      Item item = new Item(title, description, author, url);

                      //将生成的item放到result中,以便返回

                      result.add(item);

                 }

          } catch (ParserConfigurationException e) {

                //处理ParserCOnfigurationException异常,输出异常信息

                e.printStackTrace();

          } catch (SAXException e) {

//          处理SAXException异常,输出异常信息

               e.printStackTrace();

          } catch (IOException e) {

//          处理IOException异常,输出异常信息

               e.printStackTrace();

          } finally {

               //将结果返回,result数组可能为空

               return result;

          }

     }

}

至此,整个开发过程就此完成。

最后将web.xml和struts-config.xml两个配置文件的内容展示如下。

Web.xml:

<?xml version="1.0" encoding="UTF-8"?>

<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http: //java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

       <display-name>WebRssReader</display-name>

       <!-- 指定使用struts的servlet --> 

       <servlet>

             <!-- 当有请求发送到名为action的servlet时,使用org.apache.struts. action.ActionServlet来处理此请求 -->

             <servlet-name>action</servlet-name>

             <servlet-class>org.apache.struts.action.ActionServlet</ser-
vlet-class>

              <init-param>

              <!-- struts的配置文件struts-config.xml所在位置 -->

                  <param-name>config</param-name>

                  <param-value>/WEB-INF/struts-config.xml</param-value>

              </init-param>

              <init-param>

                  <param-name>debug</param-name>

                  <param-value>2</param-value>

              </init-param>

              <init-param>

                  <param-name>detail</param-name>

                 <param-value>2</param-value>

              </init-param>

              <load-on-startup>2</load-on-startup>

       </servlet>

       <!-- 将url结尾为.do的请求发送到action所在的servlet -->

       <servlet-mapping>

              <servlet-name>action</servlet-name>

              <url-pattern>*.do</url-pattern>

       </servlet-mapping>

       <!-- 初始页面为feed.jsp页面 -->

      <welcome-file-list>

            <welcome-file>feed.jsp</welcome-file>

      </welcome-file-list>

      <!-- 声明struts的bean, html, logic, nested标签库 -->

      <taglib>

            <taglib-uri>/tags/struts-bean</taglib-uri>

            <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>

      </taglib>

      <taglib>

            <taglib-uri>/tags/struts-html</taglib-uri>

            <taglib-location>/WEB-INF/struts-html.tld</taglib-location>

      </taglib>

      <taglib>

            <taglib-uri>/tags/struts-logic</taglib-uri>

            <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>

      </taglib>

      <taglib>

            <taglib-uri>/tags/struts-nested</taglib-uri>

            <taglib-location>/WEB-INF/struts-nested.tld</taglib-location>

      </taglib>

</web-app>

Struts-config.xml:

<?xml version="1.0" encoding="ISO-8859-1" ?>

<!DOCTYPE struts-config PUBLIC

          "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"

          "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">

<!--

      NOTE: If you have a generator tool to create the corresponding Java classes

      for you, you could include the details in the "form-bean" declarations.

      Otherwise, you would only define the "form-bean" element itself, with the

      corresponding "name" and "type" attributes, as shown here.

-->

<struts-config>

       <!--  在此定义FormBean,FormBean的位置为RssReaderForm,命名为rssReaderForm -->

       <form-beans>

            <form-bean name="rssReaderForm" type="RssReaderForm" />

       </form-beans>

       <!-- 定义Action的ActionMapping -->

       <action-mappings>

             <!—Action中定义RssReaderAction对应的FormBean为rssReaderForm -->

             <action name="rssReaderForm" path="/feed" type="RssReaderAction">

                   <forward name="feed" path="/feed.jsp"></forward>

                   <forward name="list" path="/list.jsp"></forward>

             </action>

       </action-mappings>

</struts-config>

12.3  利用Hibernate完成RSS自动更新
本节单独使用Hibernate来操作数据库,通过这个实例,读者可以看到,Hibernate虽然一般用于Web应用的数据访问,但其功能是独立与前台的,无论是Web、Rich Client还是单机应用都可以利用Hibernate来做数据库操作。

本实例的功能是自动获取RSS的更新,系统的数据库中存放了一系列的RSS地址,程序定时地访问数据库,根据这些RSS地址,得到其中的文章列表。

系统主要包括了以下主要部分:

(1)Hibernate的配置文件:hibernate.cfg.xml。

(2)对应数据库feeds表的Feed对象,以及映射文件feed.hbm.xml。

(3)用于解析feed内容的RssParser类和Item类。

(4)用于自动更新的线程UpdateThread。

(5)测试类Test。

系统整体框架如图12-12所示。下面分析整个系统的各个组成部分。

(1)首先需要建立数据库,在MySQL中建立新的schema,命名为feed,并在其中建立表feeds,采用的ddl如下所示。

CREATE TABLE  'feed'.'feeds' (

  'url' varchar(80) NOT NULL default '',

  PRIMARY KEY  ('url')

) ENGINE=InnoDB DEFAULT CHARSET=utf8;



图12-12

表feeds仅包含一个字段,即RSS Feed的地址Url。

(2)新建一个Java工程,下载Hibernate,将其中的包导入到工程中,并且配置Hibernate。建立Hibernate配置文件——hibernate.cfg.xml,代码如下所示。

<?xml version="1.0" encoding="utf-8" ?>

<!DOCTYPE hibernate-configuration

    PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

      <session-factory name="java:/hibernate/HibernateFactory">

             <property name="show_sql">true</property>

             <property name="connection.driver_class">

                   org.gjt.mm.mysql.Driver

             </property>

             <property name="connection.url">

                  jdbc:mysql://localhost/feed

             </property>

             <property name="connection.username"></property>

                  <property name="connection.password"></property>

             <property name="dialect">

                  org.hibernate.dialect.MySQLDialect

             </property>

             <mapping resource="Feed.hbm.xml" />

      </session-factory>

</hibernate-configuration>

本工程只有一个映射文件Feed.hbm.xml。

(3)建立数据库feeds表对应的VO——Feed类,以及其映射文件。Feed类只包含一个成员,因为数据库对应的表也仅有一个字段。

/**

* @author Chao Wu

*

* Description:

* <p>Hibernate的VO类,每个Feed对象对应数据库feeds表中的一条记录

*

* Copyright:

* <p>

*/

public class Feed {     //VO是一个普通的JavaBean

      private String url; //Feed的地址

      //以下为url的get和set方法

      public String getUrl() {

            return url;

      }

      public void setUrl(String url) {

            this.url = url;

      }

}

Feed.hbm.xml配置了Feed类和feeds表之间的映射关系。

<?xml version="1.0"?>

<!DOCTYPE hibernate-mapping PUBLIC

    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

     <class name="Feed" table="feeds">

           <id name="url" column="url" />   

     </class>

</hibernate-mapping>

主键用id定义,在此处为url。

(4)RssParser类和Item类的功能与内容与前一个实例相同,在这里不再赘述。

(5)新建FeedUpdate类,此类的提供一个静态方法getFeedList()以更新某一个feed地址中的文章列表。

由于需要使用Hibernate进行数据库操作,所以首先要引入Hibernate所需要的包。

import org.hibernate.HibernateException;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

在getFeedList()方法中,首先根据hibernate.cfg.xml中的信息,生成SessionFactory对象,并利用SessionFactory对象生成到数据库的session连接。

SessionFactory sf = new Configuration().configure().buildSessionFactory();

Session session = sf.openSession();

接着定义一个事务transaction,将数据库操作包含在一个事务中。

Transaction tx = session.beginTransaction();

定义查询语句,从数据库中得到所有的Feed信息。

String sqlQuery = "select f from Feed f";

Query lQuery = session.createQuery(sqlQuery);

feedList = (ArrayList) lQuery.list();

最后将查询到的结果返回,完整的代码如下所示。

import java.util.ArrayList;

import java.util.List;

import org.hibernate.HibernateException;

import org.hibernate.Query;

import org.hibernate.Session;

import org.hibernate.SessionFactory;

import org.hibernate.Transaction;

import org.hibernate.cfg.Configuration;

/**

* @author Chao Wu

*

* Description:

* <p>FeedUpdate类提供一个静态方法getFeedList()来取得数据库中Feed数据

*

* Copyright:

* <p>

*/

public class FeedUpdate {

     //静态方法getFeedList(),从数据库中取出所有的Feed,并将结果作为一个List返回

     public static List getFeedList() {

           List feedList;

           try {

                  //Configruation根据hibernate.cfg.xml中的信息,生成Sessio-
nFactory对象

                  SessionFactory sf = new Configuration().configure().bui-
ldSessionFactory();

                  //利用SessionFactory对象生成到数据库的session连接

                  Session session = sf.openSession();

                  //开始一个事务transaction,数据库操作包含在一个事务中

                  Transaction tx = session.beginTransaction();

                  //查询字符串,得到feeds表中所有的记录

                  String sqlQuery = "select f from Feed f";

                  //根据查询语句,生成Query对象

                  Query lQuery = session.createQuery(sqlQuery);

                  //得到查询结果

                  feedList = (ArrayList) lQuery.list();

                  //提交事务

                  tx.commit();

                  //关闭session连接

                  session.close();

                  //返回得到结果

                  return feedList;

             } catch (HibernateException e) {

             //若发生HibernateException,则显示异常信息,并返回null

             e.printStackTrace();

             return null;

       }

    }

}

(6)利用Java多线程的功能,新建一个线程类UpdateThread,代码如下所示。

import java.util.List;

public class UpdateThread extends Thread {

      boolean keepRunning = true;

      long lRefreshInterval = 10000;

      public void run() {

            while (keepRunning) {

                  try {

                        List feedList = FeedUpdate.getFeedList();

                        // 如果getFeedList方法中发生了异常,返回的feedList为null,则程序返回

                        if (feedList == null) {

                               return;

                        }

                        // 打印List中包含的feed数量

                        System.out.println("Size of feedList: " + feedList.size());

                        // 对每个Feed,得到其中的所有文章

                        for (int i = 0; i < feedList.size(); i++) {

                               // 得到每一个Feed对象

                               Feed feed = (Feed) feedList.get(i);

                               // 得到其url地址

                               String address = feed.getUrl();

                               // 取得feed中所有的文章

                               List items = RssParser.parseFeed(address);

                               // 打印feed中包含的文章数量

                               System.out.println("Items in feed of '" + address + "': "

                                            + items.size());

                        }

                        Thread.sleep(lRefreshInterval);

                  } catch (InterruptedException e) {

                        e.printStackTrace();

                  }

            }

      }

      public void stopRunning() {

            keepRunning = false;

      }

}

其中UpdateThread类继承了Thread,所以可以作为单独的线程运行。

public class UpdateThread extends Thread {

在UpdateThread类中,定义了两个成员变量。其中keepRunning为线程运行的标志位,一开始设置为true,一旦希望线程停止,就将keepRunning设置为false。另一个变量lRefreshInterval制定了自动更新的时间间隔。

boolean keepRunning = true;

long lRefreshInterval = 10000;

UpdateThread类中重载了Thread类的Run方法。

public void run() {

……

      }

Run方法的内容是当此线程运行之后要做的行为,所以将主要的操作都放置在Run方法中。在Run方法中,首先调用UpdateFeed的getFeedList方法,得到数据库中的Feed列表。

List feedList = FeedUpdate.getFeedList();

然后对列表中的每一个feed地址,调用RssParser的parseFeed()方法得到其中的文章列表。

for (int i = 0; i < feedList.size(); i++) {

        // 得到每一个Feed对象

        Feed feed = (Feed) feedList.get(i);

        // 得到其url地址

        String address = feed.getUrl();

        // 取得feed中所有的文章

        List items = RssParser.parseFeed(address);

这样就实现了自动对数据库列表中Feed包含文章的自动更新。

在完成更新操作之后,调用Thread.sleep()方法让线程睡眠一段时间,等睡眠时间结束之后继续下一次的更新操作。

Thread.sleep(lRefreshInterval);

stopRunning方法设置keepRunning为false,当keepRunning为false的时候,线程不在继续。

public void stopRunning() {

      keepRunning = false;

}

(7)编写测试类,测试自动更新线程是否正常运行,代码如下所示。

import java.util.List;

/**

* @author Chao Wu

* Description:

* Copyright:

* <p>

*/

public class Test {

      public static void main(String[] args) {

            UpdateThread updateThread = new UpdateThread();

            updateThread.start();

      }

}

至此,完成了本实例。

http://book.csdn.net/bookfiles/377/10037714193.shtml
分享到:
评论

相关推荐

    rss,RSS开发过程

    RSS开发过程,本章的实例就是实现简单的RSS在线网站阅读器。

    RSS代码大全-详细介绍RSS开发过程

    RSS流行的代码大全以及RSS详细的开发教程,我感觉对正在学习Java WEB方面知识的人非常有用!!!

    RSS 订阅功能

    为 .NET web 版的 一个 RSS 订阅功能 ,链接 ACCESS 数据库 ,显示更新的 产品、新闻、展会等信息。可订阅到网易、QQ空间等。也可订阅到浏览器。功能简单 ,易懂。重点是代码,逻辑。

    android下开发的rss reader(源码)

    android下开发的rss reader,工程源码,适合初学者熟悉开发流程

    RSS RSSFEED

    RSS 或者RSS-FEED 教程全解,包括配置环境,开发流程,注意事项等有关的RSS开发技巧;

    《Android网络开发技术实战详解》 PDF

    《Android网络开发技术...在《Android网络开发技术实战详解》最后,通过4个大型综合实例,讲述了开发网络视频播放器系统、RSS阅读器系统、邮件系统、流量监控系统的基本过程,介绍了开发大型Android系统的常规流程。

    RSS阅读器相关jar包下载

    RSS阅读器,使用java语言进行RSS阅读器的开发,在编写代码过程中所使用的jar包

    Android_RSS阅读器设计与实现

    Android_RSS阅读器设计与实现 在本系统是根据Google Android 平台用户的喜好和其平台的特性而设计的,...本文概括的介绍了Google Android 开发的流程,并重点的介绍了基于Google Android 平台的新闻阅读器的开发过程。

    《Android网络开发与应用实战详解》 PDF

    并且在本书最后,通过3个综合实例,分别介绍了开发网络视频播放器系统、RSS阅读器系统、邮件系统的基本过程,介绍了开发大型Android系统的基本流程。 《Android网络开发与应用实战详解》适合Android程序员、研发...

    ANDROID经典项目开发实战.zip

    依次讲解了移动微信系统、移动邮件系统、移动微博系统、网络RSS阅读器、开发一个音乐播放器、魔塔游戏、NBA激情投篮、象棋游戏、暴走轨迹计步器、智能楼字灯光控制系统、网络防火墙系统、Map地图、QQ聊天记录查看器...

    android开发入门与实战(下)

    12.3.2 RSS阅读器UI和交互流程设计 12.4 RSS阅读器的实现 12.4.1 程序实体解析 12.4.2 实现一个自己的ContentHandler 12.4.3 Activity的实现 12.5 本章小结 第13章 Android综合案例二——基于GoogleMap开发个人移动...

    在实战中成长Windows Forms开发之路.pdf

    Windows Forms开发之路》以一个真实的软件项目——RSS阅读器为主线,全面阐释了使用C#进行Windows Forms应用软件开发的概念和技术,内容全面,结构合理,论述清晰,帮助你领悟C#以及面向对象的思想与精华,并将其...

    Web.2.0动态网站开发—PHP技术与应用.part3.rar

    第2部分(第4~11章)结合92个范例讲解PHP的Web开发技术,内容包括PHP开发入门、PHP基本语法、PHP流程控制、PHP函数和类、MySQL、PHP+MySQL数据库开发、PHP动态网站构建全过程、PHP开发中的常用技巧等;第3部分(第12~...

    android开发入门与实战源码

    本书内容上覆盖了用Android开发的大部分场景,从Android基础介绍、环境搭建、SDK介绍、Market使用,到应用剖析、组件介绍、实例演 示等方面。从技术实现上,讲解了5个Android平台下的完整综合实例及源代码分析,分别...

    Web.2.0动态网站开发—PHP技术与应用.part5.rar

    第2部分(第4~11章)结合92个范例讲解PHP的Web开发技术,内容包括PHP开发入门、PHP基本语法、PHP流程控制、PHP函数和类、MySQL、PHP+MySQL数据库开发、PHP动态网站构建全过程、PHP开发中的常用技巧等;第3部分(第12~...

    android开发入门与实战(上)

    12.3.2 RSS阅读器UI和交互流程设计 12.4 RSS阅读器的实现 12.4.1 程序实体解析 12.4.2 实现一个自己的ContentHandler 12.4.3 Activity的实现 12.5 本章小结 第13章 Android综合案例二——基于GoogleMap开发个人移动...

    《Google Android开发入门与实战》.pdf

    12.3.2 rss阅读器ui和交互流程设计 209 12.4 rss阅读器的实现 210 12.4.1 程序实体解析 210 12.4.2 实现一个自己的contenthandler 214 12.4.3 activity的实现 217 12.5 本章小结 220 第13章 ...

    android开发入门教程

    12.3.2 RSS阅读器UI和交互流程设计 12.4 RSS阅读器的实现 12.4.1 程序实体解析 12.4.2 实现一个自己的ContentHandler 12.4.3 Activity的实现 12.5 本章小结 第13章 Android综合案例二——基于GoogleMap开发个人移动...

    ASP.NET 3.5 + SQL Server 2005网站模块化开发全程实录

    然后以网站注册、登录和验证模块、网站交互留言模块、图片上传系统模块、网站流量与统计监测、网站投票与反馈模块、购物车模块、rss信息发布与聚合模块、sns问答模块、网站信息检索与搜索模块、缓存技术在网站中的...

    Google.Android开发入门与实战

    本书系统讲解了Android软件开发的基础知识,图文并茂地帮助读者学习和掌握SDK、开发流程以及常用的API等。书中以讲述实战实例为导向,用一个个典型应用生动地引领读者进行项目开发实践。作为一本既及时、又翔实、...

Global site tag (gtag.js) - Google Analytics