精彩的人生

好好工作,好好生活

BlogJava 首页 新随笔 联系 聚合 管理
  147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

#

Building Web Services the REST Way

Roger L. Costello

I will first provide a brief introduction to REST and then describe how to build Web services in the REST style.

What is REST?

REST is a term coined by Roy Fielding in his Ph.D. dissertation [1] to describe an architecture style of networked systems. REST is an acronym standing for Representational State Transfer.

Why is it called Representational State Transfer?

The Web is comprised of resources. A resource is any item of interest. For example, the Boeing Aircraft Corp may define a 747 resource. Clients may access that resource with this URL:

http://www.boeing.com/aircraft/747
A representation of the resource is returned (e.g., Boeing747.html). The representation places the client application in a state. The result of the client traversing a hyperlink in Boeing747.html is another resource is accessed. The new representation places the client application into yet another state. Thus, the client application changes (transfers) state with each resource representation --> Representational State Transfer!

Here is Roy Fielding's explanation of the meaning of Representational State Transfer:

"Representational State Transfer is intended to evoke an image of how a well-designed Web application behaves: a network of web pages (a virtual state-machine), where the user progresses through an application by selecting links (state transitions), resulting in the next page (representing the next state of the application) being transferred to the user and rendered for their use."

Motivation for REST

The motivation for REST was to capture the characteristics of the Web which made the Web successful. Subsequently these characteristics are being used to guide the evolution of the Web.

REST - An Architectural Style, Not a Standard

REST is not a standard. You will not see the W3C putting out a REST specification. You will not see IBM or Microsoft or Sun selling a REST developer's toolkit. Why? Because REST is just an architectural style. You can't bottle up that style. You can only understand it, and design your Web services in that style. (Analogous to the client-server architectural style. There is no client-server standard.)

While REST is not a standard, it does use standards:
  • HTTP
  • URL
  • XML/HTML/GIF/JPEG/etc (Resource Representations)
  • text/xml, text/html, image/gif, image/jpeg, etc (MIME Types)

The Classic REST System

The Web is a REST system! Many of those Web services that you have been using these many years - book-ordering services, search services, online dictionary services, etc - are REST-based Web services. Alas, you have been using REST, building REST services and you didn't even know it.

REST is concerned with the "big picture" of the Web. It does not deal with implementation details (e.g., using Java servlets or CGI to implement a Web service). So let's look at an example of creating a Web service from the REST "big picture" perspective.

Parts Depot Web Services

Parts Depot, Inc (fictitious company) has deployed some web services to enable its customers to:
  • get a list of parts
  • get detailed information about a particular part
  • submit a Purchase Order (PO)
Let's consider how each of these services are implemented in a RESTful fashion.

Get Parts List

The web service makes available a URL to a parts list resource. For example, a client would use this URL to get the parts list:

http://www.parts-depot.com/parts
Note that "how" the web service generates the parts list is completely transparent to the client. All the client knows is that if he/she submits the above URL then a document containing the list of parts is returned. Since the implementation is transparent to clients, Parts Depot is free to modify the underlying implementation of this resource without impacting clients. This is loose coupling.

Here's the document that the client receives:

<?xml version="1.0"?>
<p:Parts xmlns:p="http://www.parts-depot.com" 
         xmlns:xlink="http://www.w3.org/1999/xlink">
      <Part id="00345" xlink:href="http://www.parts-depot.com/parts/00345"/>
      <Part id="00346" xlink:href="http://www.parts-depot.com/parts/00346"/>
      <Part id="00347" xlink:href="http://www.parts-depot.com/parts/00347"/>
      <Part id="00348" xlink:href="http://www.parts-depot.com/parts/00348"/>
</p:Parts>
[Assume that through content negotiation the service determined that the client wants the representation as XML (for machine-to-machine processing).] Note that the parts list has links to get detailed info about each part. This is a key feature of REST. The client transfers from one state to the next by examining and choosing from among the alternative URLs in the response document.

Get Detailed Part Data

The web service makes available a URL to each part resource. Example, here's how a client requests part 00345:

http://www.parts-depot.com/parts/00345
Here's the document that the client receives:

<?xml version="1.0"?>
<p:Part xmlns:p="http://www.parts-depot.com"   
        xmlns:xlink="http://www.w3.org/1999/xlink">
      <Part-ID>00345</Part-ID>
      <Name>Widget-A</Name>
      <Description>This part is used within the frap assembly</Description>
      <Specification xlink:href="http://www.parts-depot.com/parts/00345/specification"/>
      <UnitCost currency="USD">0.10</UnitCost>
      <Quantity>10</Quantity>
</p:Part>
Again observe how this data is linked to still more data - the specification for this part may be found by traversing the hyperlink. Each response document allows the client to drill down to get more detailed information.

Submit PO

The web service makes available a URL to submit a PO. The client creates a PO instance document which conforms to the PO schema that Parts Depot has designed (and publicized in a WSDL document). The client submits PO.xml as the payload of an HTTP POST.

The PO service responds to the HTTP POST with a URL to the submitted PO. Thus, the client can retrieve the PO any time thereafter (to update/edit it). The PO has become a piece of information which is shared between the client and the server. The shared information (PO) is given an address (URL) by the server and is exposed as a Web service.

Logical URLs versus Physical URLs

A resource is a conceptual entity. A representation is a concrete manifestation of the resource. This URL:
http://www.parts-depot.com/parts/00345
is a logical URL, not a physical URL. Thus, there doesn't need to be, for example, a static HTML page for each part. In fact, if there were a million parts then a million static HTML pages would not be a very attractive design.

[Implementation detail: Parts Depot could implement the service that gets detailed data about a particular part by employing a Java Servlet which parses the string after the host name, uses the part number to query the parts database, formulate the query results as XML, and then return the XML as the payload of the HTTP response.]

As a matter of style URLs should not reveal the implementation technique used. You need to be free to change your implementation without impacting clients or having misleading URLs.

REST Web Services Characteristics

Here are the characteristics of REST:
  • Client-Server: a pull-based interaction style: consuming components pull representations.
  • Stateless: each request from client to server must contain all the information necessary to understand the request, and cannot take advantage of any stored context on the server.
  • Cache: to improve network efficiency responses must be capable of being labeled as cacheable or non-cacheable.
  • Uniform interface: all resources are accessed with a generic interface (e.g., HTTP GET, POST, PUT, DELETE).
  • Named resources - the system is comprised of resources which are named using a URL.
  • Interconnected resource representations - the representations of the resources are interconnected using URLs, thereby enabling a client to progress from one state to another.
  • Layered components - intermediaries, such as proxy servers, cache servers, gateways, etc, can be inserted between clients and resources to support performance, security, etc.

Principles of REST Web Service Design

1. The key to creating Web Services in a REST network (i.e., the Web) is to identify all of the conceptual entities that you wish to expose as services. Above we saw some examples of resources: parts list, detailed part data, purchase order.

2. Create a URL to each resource. The resources should be nouns, not verbs. For example, do not use this:

http://www.parts-depot.com/parts/getPart?id=00345
Note the verb, getPart. Instead, use a noun:

http://www.parts-depot.com/parts/00345
3. Categorize your resources according to whether clients can just receive a representation of the resource, or whether clients can modify (add to) the resource. For the former, make those resources accessible using an HTTP GET. For the later, make those resources accessible using HTTP POST, PUT, and/or DELETE.

4. All resources accessible via HTTP GET should be side-effect free. That is, the resource should just return a representation of the resource. Invoking the resource should not result in modifying the resource.

5. No man/woman is an island. Likewise, no representation should be an island. In other words, put hyperlinks within resource representations to enable clients to drill down for more information, and/or to obtain related information.

6. Design to reveal data gradually. Don't reveal everything in a single response document. Provide hyperlinks to obtain more details.

7. Specify the format of response data using a schema (DTD, W3C Schema, RelaxNG, or Schematron). For those services that require a POST or PUT to it, also provide a schema to specify the format of the response.

8. Describe how your services are to be invoked using either a WSDL document, or simply an HTML document.

Summary

This article described REST as an architectural style. In fact, it's the architectural style of the Web. REST describes what makes the Web work well. Adhering to the REST principles will make your services work well in the context of the Web.

In a future article I will write about the evolution of the Web using the REST principles.

Acknowledgement

Thanks to Robert Leftwich and Philip Eskelin for their very helpful comments in creating this document.

References

[1] http://www.ebuilt.com/fielding/pubs/dissertation/top.htm


原文:http://www.xfront.com/REST-Web-Services.html

posted @ 2006-08-31 17:17 hopeshared 阅读(490) | 评论 (0)编辑 收藏

市长热线:12345   65128088      
反扒热线:64011327            
火警:119                
交通伤急救热线:68455655   68455665  
中毒援助热线:83163388   83160233  
抗癌互助热线:68276491            
查号台:114                
移动电话话费查询台:1861                
铁路查询售票信息:2586                
市燃气集团公司24小时热线电话:65940469   66510382
北京市煤气公司急修:65022414            
北京市供电局报修中心:63129999            
公证咨询专线:98148              
节水服务热线:64200960   64200972  
特快专递服务台:185                
报时:12117              
气象综合信息服务台:211                
首都公众信息网:263                
秘书台:269                
青春热线:64015039            
人工信息服务台:160                
道路交通事故咨询热线:26688122            
法律服务专线:1600148            
老年痴呆症咨询热线:8008208220          
市政热线:63088467            
匪警:110                
医疗急救台:120                
道路交通报警台:122                
紧急避孕热线:62173454            
移动电话服务台:222                
铁路车票定票热线:63217188            
北京市热力公司急修:65005943            
天然气急修:64269603            
施工扰民投诉电话:68413817   68017755  
中国政法大学环境法研究和服务中心热线电话:62228836            
水上搜救专用电话:12395              
天气预报台:12121              
语音信箱:166                
妇女热线:64033383   64073800  
北京公共交通李素丽服务热线:96166
小公共汽车营运服务监督电话:68351150   68351570  
火车票新订票热线:51016666  51016688  
复婚热线:62383388            
违规用水举报电话:64247906            
中华骨髓库信息热线:16895999            
市地税局举报电话:12366
免费宠物热线:160101011
公共卫生投诉电话:65066969
拆迁举报电话:64409883
市公安局监督养犬举报电话:69738604
道路质量监督电话:87501879
劳保咨询热线:12333
土地矿产法律免费热线:16829999
单亲孩子援助热线:62356688
热水器抢修服务热线:1600110
市重大动物疫病指挥部办公室:62015024   62016809
危改热线:weigai@bjjs.gov.cn
北京新闻广播“新闻热线”:8006101006
民工维权热线电话:12333
西站24小时举报电话:63984059
燃气报修热线:96777
自来水集团报修中心:66189955
电梯安全问题投诉电话:12365
加油卡更换咨询电话:64678605
食品安全监察处:82691421  12315
黑车、黑导游举报电话:96310
北京通信公司北京客户服务中心:10060
北京通信公司话费传真号码:65263399
北京市电信公司客户服务热线:96388
金银建出租汽车调度中心:96103
汽车援救电话:63489198
驾驶员违章积分短信查询热线:9626899122
城八区闯红灯咨询电话:9516888114
北京西站问讯处:51826273
北京南站问讯处:51837262
北京北站问讯处:51866223
铁路信息查询台:962585
火车票订票热线:962586
客票中心订票热线:51827188
北京火车站订票热线:51016666
posted @ 2006-08-25 12:31 hopeshared 阅读(395) | 评论 (0)编辑 收藏

使用TreeViewer贡献视图(根据《Eclipse入门到精通》中的例子进行的改编)


作者:李红霞 2005-8-13

本文章允许转载,但请要求注明文章作者及出处


一 创建插件项目
创建一个插件项目example.my.treeview,这个例子将向eclipse贡献一个视图,这个视图采用树(Treeviewer)来实现。

下图是本例的文件清单
<抱歉,图片传不上来>
+ example.my.treeview
+ src
  + example.my.treeview
    - TreeviewPlugin.java
  + exampe.my.treeview.data
    - CityEntity.java
    - CountryEntity.java
    - DataFactory.java
    - PeopleEnrity.java
  + example.my.treeview.internal
    - ITreeEntry.java
    - TreeViewerContentProvider.java
    - TreeViewerLabelProvider.java
    - TreeViewPart.java
  + JRE System Library
  + Plug-in dependencies
  + META-INF
    - MENIFEST.MF
  - build.properties
  - plugin.xml

二 准备数据模型
首先我们准备数据模型,这些数据模型都保存在example.my.treeview.data这个包中

我们定义一个接口ItreeEntry,这个接口将定义树中每个节点共同特征(名称和子节点),代码如下

package example.my.treeview.internal;
import java.util.List;
public interface ITreeEntry {
     public String getName();
     public void setName(String name);
     //设置得到子节点的集合
     public void setChildren(List children);
     public List getChildren();
}

这里涉及的实体一共有3个,以下是他们的代码

package example.my.treeview.data;
import java.util.List;
import example.my.treeview.internal.ITreeEntry;
public class CityEntity implements ITreeEntry{
     private Long id;//唯一识别码
     private String name;//城市名
     private List peoples;//城市中的人
     public CityEntity(){}
     public CityEntity(String name){this.name=name;}
     public Long getId() {return id;}
     public void setId(Long id) {this.id = id;}
     public String getName() {return name;}
     public void setName(String name) {this.name = name;}
     public List getChildren() {return peoples;}
     public void setChildren(List peoples) {
           this.peoples = peoples;
     }
}




package example.my.treeview.data;
import java.util.List;
import example.my.treeview.internal.ITreeEntry;
public class CountryEntity implements ITreeEntry{
  //唯一识别码,在数据库里常为自动递增的ID列
     private Long id;      
private String name;//国家名
//此国家所包含的城市的集合,集合元素为City对象
     private List cities;      
     //两个构造函数
     public CountryEntity(){}
     public CountryEntity(String name){this.name = name;}
  //相应的get和set方法
     public List getChildren() {return cities;}
     public void setChildren(List cities) {this.cities = cities;}
     public Long getId() {return id;}
     public void setId(Long id) {this.id = id;}
     public String getName() {return name;}
     public void setName(String name) {this.name = name;}
}



package example.my.treeview.data;
import java.util.List;
import example.my.treeview.internal.ITreeEntry;
public class PeopleEntity implements ITreeEntry{
     private String name;
     public PeopleEntity(){}
     public PeopleEntity(String name){this.name=name;}
     public List getChildren(){return null;}
     public void setChildren(List children){}
     public String getName() {return name;}
     public void setName(String name) {this.name = name;}
}


三 创建树中的数据结构

代码如下

package example.my.treeview.data;
import java.util.ArrayList;
public class DataFactory {
     public static Object createTreeData(){
           //生成人的数据对象
           PeopleEntity p1 = new PeopleEntity("李红霞");
           PeopleEntity p2 = new PeopleEntity("金利军");
           PeopleEntity p3 = new PeopleEntity("何涛");
           //生成城市的数据对象
           CityEntity city1=new CityEntity("湖北");
           CityEntity city2=new CityEntity("北京");
           CityEntity city3=new CityEntity("湖南");
           //生成国家的数据对象
           CountryEntity c1 = new CountryEntity("美国");
           CountryEntity c2 = new CountryEntity("中国");
           //将数据对象连接起来
           //人和城市的关系
           {
                 ArrayList list = new ArrayList();
                 list.add(p1);
                 city1.setChildren(list);
           }
           {
                 ArrayList list = new ArrayList();
                 list.add(p2);
                 city2.setChildren(list);
           }
           {
                 ArrayList list = new ArrayList();
                 list.add(p3);
                 city3.setChildren(list);
           }
           //城市和国家的关系
           {
                 ArrayList list = new ArrayList();
                 list.add(city1);
                 c1.setChildren(list);
           }
           {
                 ArrayList list = new ArrayList();
                 list.add(city2);
                 list.add(city3);
                 c2.setChildren(list);
           }
           //将国家置于一个对象之下,
//这个对象可以是List也可以是数组
           {
                 ArrayList list = new ArrayList();
                 list.add(c1);
                 list.add(c2);
                 return list;
           }
     }
}

四 标签器和内容器
TreeViewer和TableViewer一样,是用内容器和标签器来控制记录对象的显示,并且使用内容器和标签器的语句也是一样的。

下面是标签器的代码

package example.my.treeview.internal;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.swt.graphics.Image;
/**
* @author hopeshared
* 标签提供器,控制纪录在树中显示的文字和图像等
*/
public class TreeViewerLabelProvider
implements ILabelProvider{
     //纪录显示 的文字,不能返回null
     public String getText(Object element){
           ITreeEntry entry = (ITreeEntry)element;
           return entry.getName();
     }
     //纪录显示的图像
     public Image getImage(Object element){
           return null;
     }
     //以下方法暂不用,空实现
     public void addListener(ILabelProviderListener listener){}
     public void dispose(){}
     public boolean isLabelProperty(Object e, String p){return false;}
     public void removeListener(ILabelProviderListener listen){}
}


下面是内容器的代码

package example.my.treeview.internal;
import java.util.List;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.Viewer;
/**
* @author hopeshared
* 内容器,由它决定哪些对象应该输出在TreeViewer里显示
*/
public class TreeViewerContentProvider
implements ITreeContentProvider{
     //由这种方法决定树的哪一级显示哪些对象
     public Object[] getElements(Object inputElement)
     {
           if(inputElement instanceof List){
                 List list = (List)inputElement;
                 return list.toArray();
           }else{
                 return new Object[0];//生成一个空的数组
           }
     }
     //判断某节点是否有子节点,如果有子节点,
//这时节点前都有一个“+”号图标
     public boolean hasChildren(Object element){
           ITreeEntry entry = (ITreeEntry)element;
           List list = entry.getChildren();
           if(list==null||list.isEmpty()){return false;
           }else{return true;}
     }
     //由这个方法来决定父节点应该显示哪些子节点
     public Object[] getChildren(Object parentElement){
           ITreeEntry entry = (ITreeEntry)parentElement;
           List list = entry.getChildren();
           if(list==null || list.isEmpty()){return new Object[0];
           }else{return list.toArray();}            
     }
     //以下方法空实现
     public Object getParent(Object element){return null;}
     public void dispose(){}
     public void inputChanged(Viewer v, Object oldInput, Object newInput){}
}

五 修改清单文件
下面给出的是plugin.xml文件代码

<?xml version="1.0" encoding="UTF-8"?>
<?eclipse version="3.0"?>
<plugin>
  <extension point="org.eclipse.ui.views">
    <view
    class="example.my.treeview.internal.TreeViewPart"
id="example.my.treeview.treeview"
name="my first tree view plugin"/>
  </extension>
</plugin>

六 插件的实现
在清单文件中已经指出了这个视图的实现类是example.my.treeview.internal.TreeViewPart,下面给出这个文件的代码

package example.my.treeview.internal;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import example.my.treeview.data.DataFactory;
public class TreeViewPart extends ViewPart{
     public void createPartControl(Composite parent){
           Composite topComp = new Composite(parent, SWT.NONE);
           topComp.setLayout(new FillLayout());
           TreeViewer tv = new TreeViewer(topComp, SWT.BORDER);
           tv.setContentProvider(new TreeViewerContentProvider());
           tv.setLabelProvider(new TreeViewerLabelProvider());
           Object inputObj = DataFactory.createTreeData();
           tv.setInput(inputObj);
     }
     public void setFocus(){}
}

七 运行结果
<抱歉,图片上传失败>


八 给节点增加动作
增加一个ActionGroup类

package example.my.treeview.internal;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.ui.actions.ActionGroup;
/**
* @author hopeshared
* 生成菜单Menu,并将两个Action传入
*/
public class MyActionGroup extends ActionGroup{
     private TreeViewer tv;
     public MyActionGroup(TreeViewer treeViewer){
           this.tv = treeViewer;
     }
     //生成菜单Menu,并将两个Action传入
     public void fillContextMenu(IMenuManager mgr){
           //加入两个Action对象到菜单管理器
           MenuManager menuManager = (MenuManager)mgr;
           menuManager.add(new OpenAction());
           menuManager.add(new RefreshAction());
           //生成Menu并挂在树Tree上
           Tree tree = tv.getTree();
           Menu menu = menuManager.createContextMenu(tree);
           tree.setMenu(menu);
     }
     //打开Action类
     private class OpenAction extends Action{
           public OpenAction(){
                 setText("打开");
           }
           //继承自Action的方法,动作代码写在此方法中
           public void run(){
                 IStructuredSelection selection = (IStructuredSelection)tv.getSelection();
                 ITreeEntry obj = (ITreeEntry)(selection.getFirstElement());
                 if(obj != null){
                       MessageDialog.openInformation(null, null, obj.getName());
                 }
           }
     }
     //刷新的Action类
     private class RefreshAction extends Action{
           public RefreshAction(){
                 setText("刷新");
           }
           //继承自Action的方法,动作代码写在此方法中
           public void run(){
                 tv.refresh();
           }
     }
}

接着,修改TreeViewPart.java,代码如下

……
Object inputObj = DataFactory.createTreeData();
           //-------------加入动作开始
           MyActionGroup actionGroup = new MyActionGroup(tv);
           actionGroup.fillContextMenu(new MenuManager());
           //-------------加入动作结束
           tv.setInput(inputObj);
……


结果如下图所示
<抱歉,图片上传不成功>


九 自定义扩展点
我们想将这个视图的显示内容与视图框架分开,这样,我们需要修改视图显示内容的时候只要重新贡献一次显示内容就可以了。
9.1 添加shema文件
这个sheme文件是采用可视化编辑器进行编辑,然后pde自动生成的,代码如下

<?xml version='1.0' encoding='UTF-8'?>
<!-- Schema file written by PDE -->
<schema targetNamespace="example.my.treeview">
<annotation>
    <appInfo>
      <meta.schema plugin="example.my.treeview" id="datafactory" name="Data Factory"/>
    </appInfo>
    <documentation>
      [Enter description of this extension point.]
    </documentation>
  </annotation>
<element name="extension">
    <complexType>
      <sequence><element ref="factory"/></sequence>
      <attribute name="point" type="string" use="required">
        <annotation><documentation></documentation></annotation></attribute>
      <attribute name="id" type="string">
        <annotation><documentation></documentation></annotation></attribute>
      <attribute name="name" type="string">
        <annotation><documentation></documentation>
          <appInfo><meta.attribute translatable="true"/></appInfo></annotation>
      </attribute>
    </complexType>
  </element>
  <element name="factory">
    <complexType>
      <attribute name="id" type="string">
        <annotation><documentation></documentation></annotation></attribute>
      <attribute name="name" type="string">
        <annotation><documentation></documentation></annotation></attribute>
      <attribute name="class" type="string" use="required">
        <annotation><documentation></documentation></annotation></attribute>
    </complexType>
  </element>
  <annotation>
    <appInfo><meta.section type="since"/></appInfo>
<documentation>[Enter the first release in which this extension point appears.]
</documentation>
  </annotation>
  <annotation>
    <appInfo><meta.section type="examples"/></appInfo>
    <documentation>[Enter extension point usage example here.]</documentation>
  </annotation>
  <annotation>
    <appInfo><meta.section type="apiInfo"/></appInfo>
    <documentation>[Enter API information here.]</documentation></annotation>
  <annotation>
    <appInfo><meta.section type="implementation"/></appInfo>
<documentation>
[Enter information about supplied implementation of this extension point.]
    </documentation></annotation>
  <annotation>
    <appInfo><meta.section type="copyright"/></appInfo>
    <documentation></documentation></annotation>
</schema>

9.2 创建接口文件
ItreeEntry.java之前就已经创建好了,不需要修改。现在添加另一个接口文件,代码如下:

package example.my.treeview.internal;
public interface IDataFactory {
     public Object createTreeData();
}


于是我们修改DataFactory.java,使它实现这个接口。
9.3 修改清单文件
我们来修改清单文件,加入扩展点声明,并扩展它,代码如下

……
<extension-point id="datafactory" name="Data Factory"
schema="schema/datafactory.exsd"/>
<extension point="example.my.treeview.datafactory">
<factoryclass="example.my.treeview.data.DataFactory"/>
</extension>
……


9.4 修改TreeviewPlugin.java
增加一个方法Object loadDataFactory(),代码如下

……
public static Object loadDataFactory(){
       IPluginRegistry r=Platform. getPluginRegistry();
       String pluginID="example.my.treeview";
       String extensionPointID="datafactory";
       IExtensionPoint p=r.getExtensionPoint( pluginID, extensionPointID);
       IConfigurationElement[] c=p.getConfigurationElements();
       if( c != null) {
             for( int i= 0; i <c.length; i++) {
                   IDataFactory data = null;
                   try { data=( IDataFactory)c
.createExecutableExtension("class");
                         if( data != null){ return data.createTreeData(); }
                   } catch( CoreException x) { }}}
       return new Object();
  }
……

9.5 修改TreeViewPart.java

Object inputObj = DataFactory.createTreeData();
替换为
Object inputObj = TreeviewPlugin.loadDataFactory();

9.6 其他辅助文件
其实TreeViewerLabelProvider.java和TreeViewerContentProvider.java可以看成是对DataFactory这个扩展点的辅助文件

9.7运行
跟之前的实现没有区别,但是我们向eclipse贡献了一个扩展点


十 参考资料
《Eclipse入门到精通》
www.sohozu.com 《自己动手编写Eclipse扩展点》
EclipseCon2005_Tutorial1.pdf 《Contributing to Eclipse: Understanding and WritingPlug- ins》


图片:
 

图片:
 


经过一个多小时的努力。。。(嘿嘿,以前没有仔细研究Property什么的,今天弄了一下)

终于出现了property并且可以修改属性页中的值




代码

example.my.treeview.rar


哦,补充一下,由于模型(就是treeviewer中的初始数据)是写死的,改的property其实是修改了内存中的对象的值。假如用emf做模型持久化,就会保存修改。但是目前是不能保存修改的。


关于本文的讨论还是很多的,也有很多有用的信息。见http://www.eclipseworld.org/bbs/read.php?tid=168
本文第一次发表是在社区之中,本来也没觉得有转到blog的必要,但是后来发觉自己的记忆力越来越差,曾经作过的都忘记的差不多了,为了避免丢失,还是存在这里备份比较好。
posted @ 2006-07-25 13:54 hopeshared 阅读(3503) | 评论 (1)编辑 收藏

总是写不好ppt,为什么呢?
先把ppt的写法总结放在这里,这样就不容易忘记了。

1. 选择合适的模板,通常选择根内容相关,简单清新的模板就可以了。当然,也要看ppt是用来做什么的。
2. 标题简单明了,突出核心内容。
3. 第一页一般为Outline或者Agenda。我经常犯的错误是第一页命名为Outline,但是Outline其实跟Introduction是一个抽象级别的。
4. 每页的Items都要在一个抽象级别。
5. 每个子Item都要从同一个角度来划分
6. 通常在Introduction中介绍Challeges。如果Challeges不太多Solutions也不复杂,那么可以将两者合并作为一个Topic。如果Challeges太多在Introduction中讲不清楚,那么可以在Introduction之后列一个Challeges的Topic。
7. Introduction中应列出问题,现状,目前的挑战以及High Level的解决办法。
8. ppt的一般结构是:本项目的意义,难度,如何解决,演示。
9. Introduction之后应该紧接着介绍项目中“创造”的概念。
10. Solution应该是紧接在Challeges后面的一个Topic,它仍然是抽象的描述解决方法。更具体的涉及到技术细节的应归结为Approach或者Technics紧跟在Solution之后作为补充。
11. 实现本系统用到了其他的成熟技术。那么应该首先说明遇到了什么问题(why),如何来解决(how),有多少种解决方法(what),为什么选择你使用的这种(why)。我想可能要补充上如何来用它吧。
12. 具体的技术细节应该是在Scenarios之前。
13. Scenarios应该用少量的文字配合大量的图片来表达,不应该出现技术
14. 项目的关键特性要结合Demo体现出来
15. ppt中的结构图应该采用立体感强的图片来表示。ppt中出现的图片都应该有很强的表现力(千言万语尽在图中)。
16. 作为ppt还有一点跟paper不一样,那就是,不再需要Reference。而Conclusion&Future work则应该提炼成精简的Sumerize。

最后,ppt的灵魂就是逻辑,逻辑,还是逻辑。一定要有逻辑。

经常作总结,是增强逻辑性,条理性的最有效途径。

sigh,谁让我一向不用逻辑思考问题呢,555

posted @ 2006-07-21 14:06 hopeshared 阅读(8801) | 评论 (10)编辑 收藏

作者:Brian McBride
发表时间:2000年9月2日
原文链接: http://www.hpl.hp.co.uk/people/bwm/rdf/jena/rssinjena.htm
译者:dlee
翻译时间:2001年5月26日

    RSS 1.0 是最近宣布的一个格式,顺从于 W3C 的 RDF (资源定义框架),用来分发(distributing) 站点摘要 (site summary) 和企业联合 (syndication) 元数据。一个站点摘要文档的例子可以在规范中找到。Jena 是一套实验性的用来处理 RDF 的 Java API。这篇笔记描述了一个应用程序使用 Jena 来将一个站点摘要文档翻译成 HTML。整个程序的源代码作为 RenderToHTML 可以在 Jena 发布的例子包里得到。

    这篇文章和例子代码基于 RSS 规范候选发布版本1 (Release Candidate 1 version)。
    这个应用程序以创建一个 RDF 模型开始,实际上在内存中是一个 RDF statement 的集合。然后解析站点摘要文档,使用一个 RDF 解析器,并加载 statement 到新创建的模型中。

      Model model = new ModelMem();
      model.read(" http://www.xml.com/xml/news.rss");

    在写出一个样板 HTML 头后,程序列出和处理在输入流中的每个 channel。在 RDF 术语中,channel 是具有一个 rdf:type 属性的 rss:channel 的资源。我们使用 Jena API 来列出具有一个有这个值的 rdf:type 属性的所有的资源。在下面的代码中,假设输出是一个接收 HTML 输出的 PrintWriter。

      ResIterator channels =  model.listSubjectsWithProperty(RDF.type, RSS.channel);
      while (channels.hasNext()) {
          renderChannel(channels.next(), out);
      }

    为了呈现 (render) 一个 channel,程序首先写出它的 title,description 和相关的 image 和 textinput 字段 (如果有的话)。getProperty 方法用来得到 channel 的 title,link 和 description 属性,随后这些可以被呈现为 HTML。

      void renderChannel(Resource channel, PrintStream out)
             throws RDFException {
          String url = null;
          String title = null;
          String desc = null;

          url = channel.getProperty(RSS.link).getString();
          title = channel.getProperty(RSS.title).getString();
          desc = channel.getProperty(RSS.description).getString();

    一个 channel 可以有一个相关联的 image 和 textinput,测试是否存在这些属性和是否需要调用合适的方法来呈现它们是很简单的。

      if (channel.hasProperty(RSS.image)) {
          renderImage(channel.getProperty(RSS.image) .getResource(), out);
      }
      if (channel.hasProperty(RSS.textinput)) {
          renderImage(channel.getProperty(RSS.textinput) .getResource(), out);
      }

    为了处理一个 image,同样的调用被用来确定 image 的属性。

      String url = null;
      String title = null;

      // does the image have a link?
      if (image.hasProperty(RSS.link)) {
          url = image.getProperty(RSS.link).getString();
      }

      // does the image have a title?
      if (image.hasProperty(RSS.title)) {
          title = image.getProperty(RSS.title).getString();
      } image.getProperty(SSF.title).getString();

    然后这个 image 可以被呈现成为 output stream。textinput 以 相似的方法处理。

    channel 有一个 items 属性,它的值为一个 RDF sequence。因此使用 getProperty 方法得到这个 sequence 就很简单的了。然后迭代每一个元素以呈现它。

      if (channel.hasProperty(RSS.items)) {
          Seq items = channel.getProperty(RSS.items).getSeq();
          for (int i=1; i<= items.size(); i++) {
              renderItem(items.getResource(i), out);
          }
      }

    以相同的模式呈现每一个 items。首先得到需要呈现的 items 的属性,然后写出 HTML。

      void renderItem(Resource item, PrintWriter out) {
          String url = item.getProperty(RSS.link).getString();
          String title = item.getProperty(RSS.title).getString();
          String desc = item.getProperty(RSS.description) .getString();
          ...
      }

    使用 Jena 来处理 RSS 1.0 流是简单和直接的。

    Brian McBride
    HP实验室,2000年9月2日
    修改于2000年12月2日
posted @ 2006-07-20 10:36 hopeshared 阅读(597) | 评论 (0)编辑 收藏

仅列出标题
共30页: First 上一页 5 6 7 8 9 10 11 12 13 下一页 Last