`
yangzisai
  • 浏览: 87610 次
  • 性别: 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 feed通常包括以下元素: 1. **频道(Channel)**:这是RSS文档的顶级元素,包含了关于整个RSS源的信息,如标题、描述、URL等。 2. **条目(Item)**:...

    android_RSS开发教程

    为了让开发者能够利用Android平台的便利性,本教程《android_RSS开发教程》将会详细介绍如何使用Android Developer Tools,进行RSS的读取、解析和显示。这不仅为Android平台提供了有效的信息获取方式,还对XML数据...

    RSS阅读器开发实战

    RSS阅读器开发实战是一个以Java语言为开发工具的项目,主要目标是实现一个能够解析、显示和管理RSS订阅源的应用程序。在这个项目中,开发者将深入理解RSS feed的结构和工作原理,同时掌握Java编程以及相关框架的使用...

    Laravel开发-laravel-rss

    在Laravel 5中,开发laravel-rss库是为了简化RSS feed的生成过程。这个库可能包含了以下关键知识点: 1. **Laravel基础知识**:理解Laravel框架的基础概念,如路由、控制器、模型、视图和数据库交互(Eloquent ORM...

    Rss.rar_flex_rss开发

    10. **测试与调试**:在开发过程中,使用Flex的调试工具和模拟器进行测试,确保应用在不同平台和浏览器上的兼容性。 综上所述,"Rss.rar_flex_rss开发"项目涵盖了RSS聚合原理、Flex编程、XML解析、数据绑定、用户...

    RSS阅读器 c# vs2008开发啊

    它提供了大量预定义类,如XML处理、数据库访问、网络通信等,简化了开发过程。 4. **RSS(Really Simple Syndication)**:RSS是一种XML格式,用于发布和订阅网站内容,如新闻标题、摘要和链接。RSS阅读器可以解析...

    android_RSS经典开发教程

    ### android_RSS经典开发教程 #### 一、RSS与Android平台概述 RSS(Really Simple Syndication)作为一种标准化的格式,用于聚合网站上的内容,并让用户能够订阅这些内容更新。随着移动互联网的发展,RSS阅读器...

    新浪RSS 阅读器 android源码

    源码分析有助于开发者理解RSS订阅和解析的过程,以及如何在Android环境下构建一个功能完善的新闻阅读应用。以下是对该源码中涉及的关键知识点的详细说明: 1. **RSS(Really Simple Syndication)**: RSS是一种XML...

    Laravel开发-laravel-rss-feed

    总之,"laravel-rss-feed"为Laravel开发人员提供了一种高效、灵活的方式来管理和提供RSS Feed,简化了与RSS源交互的过程。结合SimplePie的强大功能,这个包为构建功能丰富的RSS聚合应用提供了坚实的基础。通过深入...

    Android开发实例:rss阅读器 源码

    在Android平台上,RSS阅读器是一种常见的应用,它允许用户订阅并查看来自不同网站的RSS feed。...通过这个实例,开发者可以学习到Android应用开发的基本流程和技巧,为构建更复杂的项目打下坚实基础。

    java开发的rss系统源码

    Java开发的RSS系统源码是一个基于Java编程语言构建的新闻聚合和发布系统,它主要用于抓取、处理和展示RSS(Really Simple Syndication)格式的新闻 feed。RSS是一种XML格式,用于发布经常更新的内容,如博客文章、...

    php开发的RSS阅读器

    在实现RSS阅读器的过程中,开发者可能关注以下关键点: 1. **RSS解析**:首先,需要解析RSS源的XML结构,提取出标题、链接、描述、作者等信息。 2. **数据库设计**:设计合适的数据库模型,存储RSS源信息、用户订阅...

    RSS 在线阅读器开发

    开发RSS在线阅读器涉及到以下几个关键技术: 1. **RSS格式**:RSS是基于XML的,遵循RSS 2.0标准。例如: ```xml &lt;rss version="2.0"&gt; &lt;title&gt;W3Schools Home Page &lt;link&gt;http://www.w3schools.com&lt;/link&gt; ...

    ASP.NET2.0开发的RSS阅读器(PDF)

    ASP.NET 2.0是微软公司推出的一种基于.NET Framework的Web应用程序开发平台,它极大地简化了Web应用的构建过程,提供了丰富的控件、数据绑定机制和内置的安全特性。在这个环境中,开发一个RSS阅读器是一种常见的实践...

    c#编写RSS阅读器

    在IT行业中,C#是一种广泛使用的编程语言,尤其在开发Windows桌面应用、Web应用以及游戏等领域。本项目涉及的是一个"C#编写...通过深入研究项目中的代码,新手可以提升自己的编程技能,并逐步理解软件开发的整个流程。

Global site tag (gtag.js) - Google Analytics