`
alienj
  • 浏览: 79828 次
  • 性别: Icon_minigender_1
  • 来自: 重庆
社区版块
存档分类
最新评论
阅读更多

第24章. Web服务


Seam 集成了JBossWS,允许标准JEE web服务充分利用Seam的上下文框架的优势, 包括支持对话web服务。本章通过必要的步骤允许web服务运行在一个Seam 环境。

 

24.1. 配置和打包

为了允许Seam拦截web服务请求,以便于可以为请求创建必要Seam上下文,一个特殊的SOAP(简单对象存取协议)处理器必须被配置; org.jboss.seam.webservice.SOAPRequestHandler是一个 SOAPHandler 实现,管理在一个web服务请求作用域期间的Seam的生命周期。


一个特殊的配置文件, standard-jaxws-endpoint-config.xml应该被放在包含web服务类jar文件的META-INF的目录下。这个文件包含下面的SOAP处理器配置:

 

<jaxws-config xmlns="urn:jboss:jaxws-config:2.0" 

 

              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 

 

              xmlns:javaee="http://java.sun.com/xml/ns/javaee"

 

              xsi:schemaLocation="urn:jboss:jaxws-config:2.0 jaxws-config_2_0.xsd">

 

   <endpoint-config>

 

      <config-name>Seam WebService Endpoint</config-name>

 

      <pre-handler-chains>

 

         <javaee:handler-chain>

 

            <javaee:protocol-bindings>##SOAP11_HTTP</javaee:protocol-bindings>

 

            <javaee:handler>

 

               <javaee:handler-name>SOAP Request Handler</javaee:handler-name>

 

               <javaee:handler-class>org.jboss.seam.webservice.SOAPRequestHandler</javaee:handler-class>

 

            </javaee:handler>

 

         </javaee:handler-chain>

 

      </pre-handler-chains>

 

   </endpoint-config>

 

</jaxws-config>

 

24.2. 对话的Web服务


那么对话是如何在web服务请求之间传播呢? Seam 使用一个SOAP头元素表示SOAP请求和响应消息,携带着对话ID在消费者与服务器之间传递。这里是一个包含对话ID的web服务的例子:

 

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" 

 

    xmlns:seam="http://seambay.example.seam.jboss.org/">

 

  <soapenv:Header>

 

    <seam:conversationId xmlns:seam='http://www.jboss.org/seam/webservice'>2</seam:conversationId>

 

  </soapenv:Header>

 

  <soapenv:Body>

 

    <seam:confirmAuction/>

 

  </soapenv:Body>

 

</soapenv:Envelope>    

 

正如你在上面SOAP消息中看见的,在SOAP头内有一个conversationId 元素,包含了一个请求的对话ID,在这里是2。不幸的是因为web服务由各种语言编写的各种web服务客户端消费,这由开发者实现对话ID在单一对话作用域内使用的单独web服务之间的传播。


注意,一个重要的事情是conversationId头元素必须合乎http://www.jboss.org/seam/webservice的一个命名空间的条件,否则Seam不能读取请求的对话ID 。这里是一个响应上述请求消息的例子:

 

<env:Envelope xmlns:env='http://schemas.xmlsoap.org/soap/envelope/'>

 

  <env:Header>

 

    <seam:conversationId xmlns:seam='http://www.jboss.org/seam/webservice'>2</seam:conversationId>

 

  </env:Header>

 

  <env:Body>

 

    <confirmAuctionResponse xmlns="http://seambay.example.seam.jboss.org/"/>

 

  </env:Body>

 

</env:Envelope>    

 

正如你看见的,响应消息包含与请求一样的conversationId元素。

 

24.2.1. 推荐策略


因为web服务必须由无状态会话bean或POJO实现,所以,对于对话web 服务,推荐web服务作为对话Seam组件的一个正面(facade)。

jboss seam reference 2.1(第24章) - *工* - 要有光,于是就有了光

如果web服务作为无状态会话被编写,那么也可以通过@Name注释使其成为Seam组件。这样做便于Seam双向注入 (或其他)功能用于web服务类自身。


24.3. web服务例子


让我们浏览一个web服务例子。这节的所有代码来自Seam的 /examples 目录下的seamBay例子应用程序, 并遵循前节所述的推荐策略。 首先让我们看一看web服务类和它的一个web服务方法:


@Stateless

 

@WebService(name = "AuctionService", serviceName = "AuctionService")

 

public class AuctionService implements AuctionServiceRemote

 

{

 

   @WebMethod

 

   public boolean login(String username, String password)

 

   {

 

      Identity.instance().setUsername(username);

 

      Identity.instance().setPassword(password);

 

      Identity.instance().login();

 

      return Identity.instance().isLoggedIn();

 

   }

 

……

 

}

正如你看见的,我们的web服务是一个无状态会话bean,并用javax.jws包的JWS注释注释了它,如JSR-181定义一样。 @WebService注释告诉容器该类实现了web服务,在login()方法上的@WebMethod注释指明该方法是一个web服务方法。@WebService 注释的Name和 serviceName属性是可选的。


如规范要求的一样,被暴露来作为web服务方法的每个方法必须在web服务类的远程接口中也被声明(当web服务是一个无状态会话bean时)。在上面的例子中, AuctionServiceRemote接口声明了与用@WebMethod注释一样的login()方法。


如你在上面代码中所见的, web服务实现了一个代理Seam内建的Identity组件的login()方法。按照我们推荐的策略,web服务作为一个简单的正面(facade)被编写,假冒Seam组件的真正工作。这样可以最大程度的重用web服务和客户端之间的业务逻辑。


让我看另外一个例子。这个web服务方法通过委托AuctionAction.createAuction()方法开始了一个新的对话:

 

   @WebMethod

 

   public void createAuction(String title, String description, int categoryId)

 

   {

 

      AuctionAction action = (AuctionAction) Component.getInstance(AuctionAction.class, true);

 

      action.createAuction();

 

      action.setDetails(title, description, categoryId);

 

   }

 

下面是来自AuctionAction的代码:


   @Begin

 

   public void createAuction()

 

   {

 

      auction = new Auction();

 

      auction.setAccount(authenticatedAccount);

 

      auction.setStatus(Auction.STATUS_UNLISTED);        

 

      durationDays = DEFAULT_AUCTION_DURATION;

 

   }

从这里我们可以看见,web服务如何通过作为一个正面(facade)并代理对话Seam组件的真正工作参与到长期运行对话。


24.4. 使用RESTEasy的RESTful HTTP web服务


Seam集成了实现了JAX-RS规范(JSR 311)的RESTEasy。 你可以决定要多么“深”地集成到你的Seam应用程序:

  • 无缝集成RESTEasy引导程序和配置,自动侦测资源和供应商。
  • SeamResourceServlet服务HTTP/REST请求,在web.xml中不需要外部的servlet和配置。
  • 编写资源作为Seam组件, 使用完全的Seam生命周期管理和拦截(双向注入)。

24.4.1. RESTEasy配置和请求服务


首先,得到RESTEasy库和jaxrs-api.jar包,与你的应用程序带的其他库一起部署。 还要部署集成的库jboss-seam-resteasy.jar 。


在启动时,所有注释了@javax.ws.rs.Path的类会被自动发现并注册成HTTP资源。 Seam用它内建的SeamResourceServlet自动访问并服务于HTTP请求。资源的URI(统一资源标识符)象下面这样被构建:

  • URI从SeamResourceServlet在web.xml中映射的模式(pattern开始,例如 /seam/resource,如果你按照常规例子。你可以改变这个设置,在不同的基本路径下暴露你RESTful资源。注意,这是一个全局改变,并且其他的Seam资源(例如 s:graphicImage)也是在这个基本路径下提供服务。
  • 然而,Seam集成的RESTEasy为这个基本路径增加了一个可配置字符串,默认是/rest。因此,举例来说,你的资源的完整路径会是/seam/resource/rest。 我们推荐你在你的应用程序中改变这个字符串,你可以添加一个版本号为准备将来REST API升级服务 (老的客户端会保持老的URI基本路径。) ,例如: /seam/resource/restv1。
  • 最后,实际的资源在定义的@Path下是可用的,如,一个用@Path("/customer")映射的资源在/seam/resource/rest/customer下是可用的。  


举一个例子,下面的资源定义会对使用URI http://your.hostname/seam/resource/rest/customer/123的任何GET请求返回一个纯文本表示:


@Path("/customer")

 

public class MyCustomerResource {

 

 

    @GET

 

    @Path("/{customerId}")

 

    @ProduceMime("text/plain")

 

    public String getCustomer(@PathParam("customerId") int id) {

 

         return ...;

 

    }

 

 }

 

如果这些默认是可以接受的,你不需要另外的配置,不必编辑web.xml 或任何其他设置。 然而,你可以在你的Seam 应用程序中配置RESTEasy 。 首先导入resteasy命名空间到你的XML配置文件头:

 

<components

 

   xmlns="http://jboss.com/products/seam/components"

 

   xmlns:resteasy="http://jboss.com/products/seam/resteasy"

 

   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

 

   xsi:schemaLocation=

 

     http://jboss.com/products/seam/resteasy

 

         http://jboss.com/products/seam/resteasy-2.1.xsd

 

     http://jboss.com/products/seam/components

 

         http://jboss.com/products/seam/components-2.1.xsd">

 

然后,你可以象前面提及的改变/rest前缀:

 

<resteasy:application-config resource-path-prefix="/restv1"/>

 

现在你的资源的完整路径是/seam/resource/restv1/{resource} ——注意 ,你的@Path定义和映射并没有改变。这是一种应用广泛的通用开关,用于HTTP API版本。


如果你喜欢在你的资源内映射完整路径,你可以禁用断裂的基本路径:

 

<resteasy:application-config strip-seam-resource-path="false"/>

 

例如,现在资源的路径利用@Path("/seam/resource/rest/customer")来映射。然而,我们反对禁用这个功能,因为你的资源类映射是捆绑到一个特殊的部署情节。


对任何部署的@javax.ws.rs.Path 资源和任何@javax.ws.rs.ext.Provider类,Seam会扫描你的类路径。你可以禁用扫描,并手动配置这些类:

 

<resteasy:application-config

 

     scan-providers="false"

 

     scan-resources="false"

 

     use-builtin-providers="true">

 

 

 

     <resteasy:resource-class-names>

 

         <value>org.foo.MyCustomerResource</value>

 

         <value>org.foo.MyOrderResource</value>

 

     </resteasy:resource-class-names>

 

 

     <resteasy:provider-class-names>

 

         <value>org.foo.MyFancyProvider</value>

 

     </resteasy:provider-class-names>

 

 

 </resteasy:application-config>

 

use-built-in-providers切换启用(默认)或禁用RESTEasy内建供应商。 我们建设你启用它们,因为它们提供纯文本、JSON和JAXB编组的开箱即用功能。

 

最后,你可以配置媒体类型和语言的URI扩展名:

 

<resteasy:application-config>

 

 

    <resteasy:media-type-mappings>

 

       <key>txt</key><value>text/plain</value>

 

    </resteasy:media-type-mappings>

 

 

    <resteasy:language-mappings>

 

       <key>deutsch</key><value>de-DE</value>

 

    </resteasy:language-mappings>

 

 

</resteasy:application-config>

 

这个定义将对附加的访问和访问语言头的值 text/plain和de-DE映射URI后缀为.txt和.deutsc。


24.4.2. 资源和供应商作为Seam组件


默认时RESTEasy管理任何资源和供应商实例。那意味着RESTEasy会实例化一个资源类并且服务于一个请求,然后摧毁它。这是默认的JAX-RS生命周期。供应商对整个应用程序实例化一次,实际上是单独的并且被假定是无状态的。


你可以编写资源和供应商作为Seam组件,得益于丰富的Seam管理的生命周期、双向注入拦截和安全等等。简单地让你的资源类成为一个Seam组件:

@Name("customerResource")

 

@Path("/customer")

 

public class MyCustomerResource {

 

 

    @In

 

    CustomerDAO customerDAO;

 

 

    @GET

 

    @Path("/{customerId}")

 

    @ProduceMime("text/plain")

 

    public String getCustomer(@PathParam("customerId") int id) {

 

         return customerDAO.find(id).getName();

 

    }

 

}

现在,当一个请求访问服务器时,Seam处理customerResource实例。这是一个事件作用域的Seam JavaBean组件,因此不同于默认的JAX-RS生命周期。然而,你完全得到了Seam注入支持和所有其它Seam组件以及你想用的上下文。目前也支持SESSION、 APPLICATION和STATELESS资源组件。请记住,为正确地处理服务边会话上下文,所有的HTTP 请求必须转换成一个有效会话标识符 (cookie, URI路径参数)。


对话作用域(Conversation-scoped资源组件和对话映射目前还不支持,但不久会实现的。


供应商类也是Seam组件, 它们必须是应用作用域(APPLICATION-scoped)或无状态的。

资源和供应商可以是EJBs或JavaBeans, 象所有其它Seam组件一样。

分享到:
评论

相关推荐

    Flex 3 CookBook中文 简体(带书签)

    Flex CookBook 中文 简体 第一章. ActionScript 语言基础 第二章. 自定义类 第三章....第四章....第五章....第六章....第七章....第八章....第九章....第十章....第十一章....第十二章....第十四章....第二十四章. Socket编程(目录)

    MyEclipse.6.Java.开发中文教程

    第一章 安装配置开发环境 ...第十四章.开发JSF应用 第十五章.开发XFire.Web.Service应用 第十六章.开发.EJB.应用 第十七章.MyEclipse.UML.建模 第十八章.图形界面开发--AWT,Swing,SWT 全部代码.rar

    Sybase ASE 15.7 开发文档:Web 服务用户指南

    第 1 章 了解 Adaptive Server Enterprise Web 服务 .......... 3 概述 .......... 3 Adaptive Server Enterprise Web 服务 .......... 4 ASE Web 服务的优点 .......... 4 存储过程和函数 .......... 4 SQL ..........

    嵌入式WEB服务器及远程测控应用详解.rar

    第四章:CGI介绍及表单提交方式 第五章:简单的 LED 测试 第六章:A/D测量及在网页中的显示 第七章: 基于 ZC301摄像头开源视频服务器代码移植 第八章: IP 自动获得的设置和测试 第九章:复杂 LED测试 第十章...

    网络服务器配置完全手册

    第5 章 Web 网站........................................................................................................................................65 5.1 WWW 服务概述.................................

    ASP.NET 3.5开发大全

    第14章.ASP.NET_XML和Web_Service 第15章.图形图像编程 第16章.ASP.NET_3.5和AJAX ...第24章.广告模块设计 第25章.新闻模块设计 第26章.投票模块设计 第27章.聊天模块设计 第28章.制作一个ASP.NET留言本

    D6 SOAP_WEB SERVICE程序设计.part1.rar

    delphi下soap编程指导 第一章 SOAP和Web Service的概念 第二章 组件模型、Internet/Intranet和SOAP 第三章 开发Web Service 第四章 什么是SOAP 第五章 SOAP和数据封装 ...第十四章 在Internet上使用Web Service

    Lotus.Domino.Web编程

    第1章 Domino Web开发综述 1 1.1 为什么使用Domino 1 1.2 Domino是怎样运行的 1 1.2.1 Domino与传统数据库的区别 1 1.2.2 Domino和Web 2 1.3 开发部件 2 1.4 其他工具 3 1.5 简单的Domino Web软件例子 10 参考信息 ...

    servser 2003完整教程part2

    第四章 管理 Active Directory 组对象和组策略....................................................................89 第一节 本地组...........................................................................

    SharePoint.2010.Web.Parts.实战

    **第二章** 中,作者详细介绍了如何在 SharePoint 2010 中使用和配置 Web Parts。这一部分主要涉及以下几点: - **Web Parts 的基本概念**:解释了 Web Parts 架构的基本组成,包括 Web Part 控件、Web Part 区域、...

    Java Web开发实战经典-基础篇课后习题答案及高级篇源码

    MLDN 李兴华 老师 Java Web基础篇课后习题答案,Java Web高级案例篇全部源码。 此源码从最基本的JSP页面到Model ...第十四章.Ajax开发技术:1,2,3,4题 第十五章.Structs基础开发:1题 第十六章.Structs常用标签:1题

    Java Web开发实战经典》

    套源码从最基本的JSP页面到Model 1到Model 2,文件上传,EL,JSTL,Ajax,Structs,一点一点的修改讲解。...第十四章.Ajax开发技术:1,2,3,4题 第十五章.Structs基础开发:1题 第十六章.Structs常用标签:1题

    JAVA WEB 开发详解:XML+XSLT+SERVLET+JSP 深入剖析与实例应用.part3

    3.5.4 第二个实例 94 3.6 解析名称空间 96 3.6.1 dom和名称空间 96 3.6.2 sax和名称空间 97 3.6.3 jdom和名称空间 98 3.6.4 dom4j和名称空间 98 3.7 小结 99 第4章 xsl转换 101 4.1 xslt概述 101 4.2 xalan...

    server2003完整教程part1

    第四章 管理 Active Directory 组对象和组策略....................................................................89 第一节 本地组...........................................................................

    spring.net中文手册在线版

    第二十四章. 与Visual Studio.NET集成 24.1.XML编辑与验证 24.2.XML Schema的版本 24.3.集成API文档 第六部分. 快速入门程序 第二十五章. IoC快速入门 25.1.简介 25.2.Movie Finder 25.2.1.开始建立MovieFinder应用...

    零基础学Java.Web开发

    7. **第十四章 Spring应用详解**: - Spring框架是Java企业级应用的核心,涵盖依赖注入、AOP、MVC等模块。 - 介绍Spring配置文件、Bean的声明和管理,以及Spring MVC的基本流程。 8. **第十五章 Hibernate应用...

    Web设计原理与编程技术.rar

    第一章 Internet与Web基础知识; 第二章 Web协议; 第三章 简单的Web文档; 第四章 JavaScript; 第五章 Web网站设计准则; 第六章 Java概述;...第十四章 JSP语法; 第十五章 JSP与JavaBean; 第十六章 JSP访问数据库;

    Java/JavaEE 学习笔记

    第十四章 标准I/O流与文件.............84 第十五章 网络编程.89 Tiger学习笔记..................94 第一章 Java5.0新特性.......................94 第二章 基础知识.....96 第三章 泛型...........101 第四章 ...

Global site tag (gtag.js) - Google Analytics