跳转到主要内容

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

这是您第一次登陆到 developerWorks,已经自动为您创建了您的概要文件。 选择您概要文件中可以公开的信息的信息(如姓名、国家/地区,以及公司),这些信息同时也会与您所发布的内容相关联。 您可以随时更新您的 IBM 账号。

所有提交的信息确保安全。

  • 关闭 [x]

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

所有提交的信息确保安全。

  • 关闭 [x]

使用 Atom 服务文档创建侧栏

Atom 服务文档并不仅仅用于获取站点的提要

Nicholas Chase (ibmquestions@nicholaschase.com), 自由撰稿人, Backstop Media
Nicholas Chase 曾经参与多家公司的网站开发,包括 Lucent Technologies、Sun Microsystems、Oracle 和 Tampa Bay Buccaneers。Nick 曾经做过高中物理教师、低放射性废弃设备管理员、在线科幻杂志的编辑、多媒体工程师、Oracle 教员以及一家交互通信公司的首席技术官。他出版了多部著作,包括 XML Primer Plus(Sam's)。

简介: Atom 服务文档并不仅仅用于告知读者从哪获取站点的提要。本文向大家展示了如何使用这种自省文档(introspection document)创建侧栏,侧栏中可以显示服务器要提供的一切内容。本文使用的是 Blogapps 服务器,该服务器支持 Atom 发布协议 1.0 规范的 10 号草案,不过本文中的实现适用于任何遵守 APP 1.0 规范的服务器。要使用实际的代码,还需要熟悉 Java 编程,不过可以将 Atom 概念应用于任何编程语言。

发布日期: 2007 年 8 月 06 日
级别: 中级
访问情况 : 2620 次浏览
评论: 


服务文档

服务通过 Atom 服务文档告知我们哪些内容可用。每一个服务表示一个或多个工作空间,每个工作空间表示一个或多个集合(collection)。集合由一些资源个体组成。例如,可以在 http://local hosts:8080/roller/app 上检索 Blogapps 服务文档。(如清单 1 所示)。


清单 1. 服务文档
                
<?xml version="1.0" encoding="UTF-8"?>
<app:service xmlns:app="http://purl.org/atom/app#" 
              xmlns:atom="http://www.w3.org/2005/atom">
  <app:workspace>
    <atom:title>AdminBlog</atom:title>
    <app:collection 
          href="http://localhost:8080/roller/app/adminblog/entries">
      <atom:title>Weblog Entries</atom:title>
      <app:categories app:fixed="yes" 
            app:scheme="http://localhost:8080/roller/adminblog/">
        <atom:category atom:term="/General" atom:label="General" />
        <atom:category atom:term="/Status" atom:label="Status" />
      </app:categories>
      <app:accept>entry</app:accept>
    </app:collection>
    <app:collection 
         href="http://localhost:8080/roller/app/adminblog/resources">
      <atom:title>Media Files</atom:title>
      <app:accept>image/*</app:accept>
    </app:collection>
  </app:workspace>
  <app:workspace>
...
  </app:workspace>
</app:service>

通过这个文档,我们可以创建一个包含侧栏的 servlet,侧栏中将显示出所有可用的服务和提要,连同到它们的 HTML 版本的链接。


基本 servlet

第一步,创建基本的 servlet,包括侧栏的空间(如清单 2 所示)。


清单 2. 基本 servlet
                
package com.backstop.atom;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.File;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.w3c.dom.Node;

public class SideBarServlet extends javax.servlet.http.HttpServlet 
                                   implements javax.servlet.Servlet {

   String APPNS = "http://purl.org/atom/app#"; 
   String AtomNS = "http://www.w3.org/2005/atom";
   String AtomNS2 = "http://www.w3.org/2005/Atom";

   protected void doGet(HttpServletRequest request, 
                        HttpServletResponse response) 
                             throws ServletException, IOException {

      response.getWriter().print(
                         "<div style='width:25%; float: right;'>");   
      Document doc = URLContents.getContentsAsXMLDoc(
                                "http://localhost:8080/roller/app" );
      Element root = (Element)doc.getDocumentElement();
            
      NodeList workspaces = root.getElementsByTagNameNS(APPNS, 
                                                        "workspace");

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

         Element thisWorkspace = (Element)workspaces.item(i);
         response.getWriter().print(
             "<div style='border: 1px solid green; padding: 5px;'>");

         String wsTitle = 
                    thisWorkspace.getElementsByTagNameNS(AtomNS, 
                                   "title").item(0).getTextContent();
         response.getWriter().print(
                             "<h3 class='wstitle'>"+wsTitle+"</h3>");

         response.getWriter().print("</div>");
      }
      response.getWriter().print("</div>");         

   }     
}

类包含了所有需要的导入语句和表示名称空间的变量。(Blogapps 有一个很小的 bug,即服务文档有一个稍微有误的名称空间;如果没有修正该 bug,则需要同时声明两个版本:http://www.w3.org/2005/atom 和 http://www.w3.org/2005/Atom)

下一步,添加实际的工作空间到侧栏。为此,遍历文档中的工作空间元素。所有这些文档都受到 Blogapps 服务器的密码保护,因此为了简单起见,我将元素的实际检索移动到了一个单独的工具类 URLContents 中。可以从本文提供的源代码中找到这个类。(如果您要自己实现这个检索,请确保将 DocumentBuilderFactory 设置为名称空间感知(namespace-aware))。

有了 XML 文档对象之后,遍历各个工作空间元素,并在页面上为每个元素都创建一个 div。对于每个元素,提取标题元素的文本并将其放入页面,如图 1 所示。


图 1. 工作空间
工作空间

接下来看看如何添加集合。


添加 collections

在页面中添加集合的操作所涉及的过程大致相同。有了各个工作空间之后,就可以检索其中的各个集合了(如清单 3 所示)。


清单 3. 遍历集合
                
...
         response.getWriter().print(
                  "<h3 class='wstitle'>"+wsTitle+"</h3>");

         NodeList collections = 
            thisWorkspace.getElementsByTagNameNS(APPNS, "collection");

         for (int j = 0; j < collections.getLength(); j++){

            Element thisCollection = (Element)collections.item(j);

            String colTitle = 
                    thisCollection.getElementsByTagNameNS(AtomNS, 
                                    "title").item(0).getTextContent();
            String feedURL = thisCollection.getAttribute("href");

            response.getWriter().print(
                                 "<h4 class='collection'>"+colTitle);
            response.getWriter().print(" -- <a href='"+feedURL+
               "'><img border='0' src='images/feed-icon.gif' /></a>");
            response.getWriter().print("</h4>");
         }
         response.getWriter().print("</div>");
      }
      response.getWriter().print("</div>");         

   }
}

对于每一个集合,除了显示其标题外还有一些其他事情。每个集合还包含了一个 href 属性,用于表示该集合的 Atom 提要的位置。要利用这点,提取该信息并添加一个提要图标,并将其链接到提要的 URL。最后的结果类似于图 2。


图 2. 添加提要
添加提要

添加类别

我们还可以为每个集合中的内容添加一个类别提示(如清单 4 所示)。


清单 4. 添加类别
                
...
            response.getWriter().print(" -- <a href='"+feedURL+
               "'><img border='0' src='images/feed-icon.gif' /></a>");
            response.getWriter().print("</h4>");

            NodeList categories = 
                        thisCollection.getElementsByTagNameNS(AtomNS, 
                                                          "category");
            if (categories.getLength() > 0){
               response.getWriter().print(
                                   "Categories in this collection: ");
            }
            for (int k = 0; k < categories.getLength(); k++){
               Element thisCategory = (Element)categories.item(k);
               String catName = thisCategory.getAttributeNS(AtomNS, 
                                                             "label");
               if (k > 0){
                  response.getWriter().print(", ");
               }
               response.getWriter().print(catName);
            }

         }
         response.getWriter().print("</div>");
      }
      response.getWriter().print("</div>");
        
   }     
}

结果类似图 3 所示。


图 3. 添加类别
添加类别

链接到 HTML 版本

最后一步,加入该信息的 HTML 表示的链接。遗憾的是,该信息并没有实际存在于服务文档中。要检索它,我们还要看看提要本身(如清单 5 所示)。


清单 5. 检索提要信息
                
...
         for (int j = 0; j < collections.getLength(); j++){
            Element thisCollection = (Element)collections.item(j);
            String colTitle = 
                    thisCollection.getElementsByTagNameNS(AtomNS, 
                                    "title").item(0).getTextContent();
            String feedURL = thisCollection.getAttribute("href");
            String webURL = getWebURL(feedURL);

            response.getWriter().print(
               "<h4 class='collection'><a href='"+webURL+"'>"+>
                                                     colTitle+"</a>");
  ... 
         }
         response.getWriter().print("</div>");
      }
      response.getWriter().print("</div>");         

   }

   private String getWebURL(String feedURL){

      String webURL = "";

      Document doc = URLContents.getContentsAsXMLDoc(feedURL);
      Element root = (Element)doc.getDocumentElement();

      NodeList links = root.getElementsByTagNameNS(AtomNS2, "link");
      for (int i = 0; i < links.getLength(); i++){
         Element thisLink = (Element)links.item(i);
         if (thisLink.getAttribute("rel").equals("alternate") && 
                             thisLink.getParentNode().equals(root)){
             webURL = thisLink.getAttribute("href");
         }
      }
      return webURL;
   }
}
            

在本例中,我们通过服务文档检索提要 URL,然后检索实际文档,其中包含一个链接元素,比如 <link rel="alternate" href="http://localhost:8080/roller/adminBlog" /> 表示提要所表示数据的 HTML 版本。然后便可以将该信息加入到侧栏中。最后的结束类似于图 4。


图 4. 添加类别
添加类别

结束语

服务文档并不仅仅用于自省;经过精心规划,我们可以使用服务文档提供实际的内容和到内容的链接。



下载

描述名字大小下载方法
Atom 侧栏示例x-atomsidebar-source.zip3KBHTTP

关于下载方法的信息


参考资料

学习

获得产品和技术

  • Blogapps 服务器:下载这个服务器,其中包含了各种有用的 RSS 和 Atom 工具及例子。

  • IBM 试用版软件:使用可从 developerWork 直接下载的试用软件构建您的下一个开发项目。

讨论

关于作者

Nicholas Chase 曾经参与多家公司的网站开发,包括 Lucent Technologies、Sun Microsystems、Oracle 和 Tampa Bay Buccaneers。Nick 曾经做过高中物理教师、低放射性废弃设备管理员、在线科幻杂志的编辑、多媒体工程师、Oracle 教员以及一家交互通信公司的首席技术官。他出版了多部著作,包括 XML Primer Plus(Sam's)。

关于报告滥用的帮助

报告滥用

谢谢! 此内容已经标识给管理员注意。


关于报告滥用的帮助

报告滥用

报告滥用提交失败。 请稍后重试。


developerWorks:登录


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 使用条款

 


当您初次登录到 developerWorks 时,将会为您创建一份概要信息。您在 developerWorks 概要信息中选择公开的信息将公开显示给其他人,但您可以随时修改这些信息的显示状态。您的姓名(除非选择隐藏)和昵称将和您在 developerWorks 发布的内容一同显示。

请选择您的昵称:

当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

(长度在 3 至 31 个字符之间)


单击提交则表示您同意developerWorks 的条款和条件。 使用条款.

 


为本文评分

评论

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=XML
ArticleID=245447
ArticleTitle=使用 Atom 服务文档创建侧栏
publish-date=08062007
author1-email=ibmquestions@nicholaschase.com
author1-email-cc=dwxed@us.ibm.com