查看原始edoc: http://www.beansoft.biz/weblogic/docs92/webserv/jws.html

英文对照

eDocs 首页 >  > WebLogic Server 的 Web Service 编程 > JWS 文件编程

WebLogic Server 的 Web Service 编程

上一页 下一页 在新窗口中打开目录

在此处开始内容

JWS 文件编程

下列部分提供有关实现 Web Service 的 JWS 文件编程的信息:


JWS 文件和 JWS 批注的概述

编写 WebLogic Web Service 的一种方法是从头开始对标准 JSR-921 EJB 或 Java 类进行编码,然后手工生成其关联工件(部署描述符文件、WSDL 文件、用户定义数据类型的数据绑定工件等)。该过程难度较大且非常繁琐。BEA 建议利用新的 JDK 5.0 metadata annotations 功能,使用编程模型创建批注 Java 文件,再使用 Ant 任务将该文件编译为 Java 源代码,然后生成所有关联工件。

Java Web Service (JWS) 批注的文件是 Web Service 的核心。它包含确定 Web Service 行为方式的 Java 代码。JWS 文件是一个普通 Java 类文件,它使用 JDK 5.0 元数据批注指定 Web Service 的形状和特征。可在 JWS 文件中使用的 JWS 批注包括Web Services Metadata for the Java Platform specification (JSR-181) 中定义的标准批注以及 WebLogic 特定的一组批注。

本主题是创建 Web Service 的迭代开发过程的一部分,如从 Java 开始迭代开发 WebLogic Web Service:主要步骤从 WSDL 文件开始迭代开发 WebLogic Web Service:主要步骤中所述。本主题假设您已经创建 JWS 文件,现在希望向其中添加 JWS 批注。


JWS 文件编程:Java 要求

在编写 JWS 文件时,必须遵守 Web Services Metadata for the Java Platform JSR-181 specification 指定的一组要求。具体来说,实现 Web Service 的 Java 类:

  • 必须是外部公共类,不得是最终类,也不得是抽象类。
  • 必须包含默认的公共构造方法。
  • 不得定义 finalize() 方法。
  • 必须至少包括一个类级别 @WebService JWS 批注,以指示 JWS 文件实现 Web Service。
  • 可以使用 @WebService.endpointInterface 批注引用服务端点接口。在这种情况下,假设服务端点接口存在,且不能在 JWS 文件中指定除 @WebService.endpointInterface@WebService.serviceName 以外的 JWS 批注。
  • 如果 JWS 文件未实现服务端点接口,则除从 java.lang.Object 继承的方法外,所有公共方法都会公开为 Web Service 操作。通过使用 @WebMethod 批注明确指定将公开的公共方法,可以替代此行为。如果存在 @WebMethod 批注,则仅公开对其适用的方法。

JWS 文件编程:典型步骤

下列部分描述如何在 JWS 文件中使用标准 (JSR-181) 批注和 WebLogic 特定的批注来编写基本 Web Service 功能。批注用于 JWS 文件中的不同级别或不同目标。部分批注用在类级别,表明该批注应用于整个 JWS 文件。其他批注用于方法级别,但还有一部分批注用于参数级别。此部分讨论下列基本 JWS 批注:

  • @WebService(标准)
  • @SOAPBinding(标准)
  • @WLHttpTransport(WebLogic 特定)
  • @WebMethod(标准)
  • @Oneway(标准)
  • @WebParam(标准)
  • @WebResult(标准)

有关使用其他 JWS 批注编写 Web Service 可靠消息传递、对话、SOAP 消息处理程序等多个高级功能的信息,请参阅高级 JWS 编程:实现异步功能

有关标准批注和 WebLogic 特定 JWS 批注的参考文档,请参阅 JWS 批注参考

以下步骤说明 JWS 文件编程 时实现 Web Service 的常规基本步骤。有关代码示例,请参阅 JWS 文件示例

  1. 导入将在 JWS 文件中使用的标准 JWS 批注。标准 JWS 批注位于 javax.jwsjavax.jws.soap 包中。例如: <pre>import javax.jws.WebMethod;
    import javax.jws.WebService;
    import javax.jws.soap.SOAPBinding;</pre>

  2. 导入 JWS 文件中使用的 WebLogic 特定批注。WebLogic 特定批注位于 weblogic.jws 包中。例如: <pre>import weblogic.jws.WLHttpTransport;</pre>

  3. 在类级别添加所需的标准 @WebService JWS,以指定 Java 类公开 Web Service。 请参阅指定 JWS 文件实现 Web Service

  4. (可选)在类级别添加标准 @SOAPBinding JWS 批注,以指定 Web Service 与 SOAP 消息协议之间的映射。具体来说,使用此批注指定 Web Service 是 document-literal 还是 RPC 编码等。 虽然此 JWS 批注并非必需项,但 BEA 建议您在 JWS 文件中明确指定它,以明确客户端应用程序用于调用 Web Service 的 SOAP 绑定类型。

<del><a name="wp223755"></a></del>请参阅[指定 Web Service 到 SOAP 消息协议的映射](http://www.beansoft.biz/weblogic/docs92/webserv/jws.html#wp212250)。
  1. (可选)在类级别添加 WebLogic 特定的 @WLHttpTransport JWS 批注,以指定调用 Web Service 的 URL 中使用的上下文路径和服务 URI。 虽然此 JWS 批注并非必需项,但 BEA 建议您在 JWS 文件中明确指定它,以明确客户端应用程序用于调用 Web Service的 URL。
<del><a name="wp212322"></a></del>请参阅[指定 Web Service 的上下文路径和服务 URI](http://www.beansoft.biz/weblogic/docs92/webserv/jws.html#wp212252)。
  1. 对于希望作为公共操作公开的 JWS 文件中的每种方法,可选择添加标准 @WebMethod 批注。(可选)使用标准 @Oneway 批注,以指定该操作仅使用输入参数,但不返回任何值。 请参阅指定 JWS 方法公开为公共操作

  2. (可选)通过添加标准 @WebParam 批注,自定义所公开操作的输入参数的名称。 请参阅自定义操作参数和 WSDL 部件之间的映射

  3. (可选)通过添加标准 @WebResult 批注,自定义所公开操作的返回值的名称和行为。 请参阅自定义操作返回值与 WSDL 部件之间的映射

  4. 向方法中添加业务 Java 代码,使 WebService 能够执行您需要的行为。

JWS 文件示例

以下 JWS 文件示例说明如何实现简单 Web Service。

package examples.webservices.simple;

// 导入标准 JWS 批注接口

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

// 导入 WebLogic 特定的 JWS 批注接口

import weblogic.jws.WLHttpTransport;

// 标准 JWS 批注,用于指定 Web Service 的
// porType 名称为“SimplePortType”,服务名为“SimpleService”,
// 在生成的 WSDL 中使用的 targetNamespace 为“http://example.org”

@WebService(name="SimplePortType", serviceName="SimpleService",
targetNamespace="http://example.org")

// 标准 JWS 批注,用于指定服务到
// SOAP 消息协议的映射。尤其,它用于指定 SOAP 消息
// 为 document-literal-wrapped。

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

// WebLogic 特定的 JWS 批注,用于指定生成 Web Service
// 的 URI 所使用的上下文路径和服务 URI 为
// “simple/SimpleService”

@WLHttpTransport(contextPath="simple", serviceUri="SimpleService",
portName="SimpleServicePort")

/**
* 此 JWS 文件形成了带有下列单个操作的简单 Java 类实现的 WebLogic
* Web Service 的基础:sayHello
*
*/

public class SimpleImpl {

// 标准 JWS 批注,用于指定方法应公开为
// 公共操作。因为批注不包括
// 成员值“operationName”,所以操作的公共名称将与
// 方法名相同:sayHello。

@WebMethod()
public String sayHello(String message) {
System.out.println("sayHello:" + message);
return "Here is the message: '" + message + "'";
}
}
指定 JWS 文件实现 Web Service

使用标准 @WebService 批注在类级别指定 JWS 文件实现 Web Service,如以下代码摘录所示:

@WebService(name="SimplePortType", serviceName="SimpleService",
targetNamespace="http://example.org")

在该示例中,Web Service 的名称是 SimplePortType,以后它将映射到 jwsc Ant 任务生成的 WSDL 文件中的 wsdl:portType 元素。服务名称是 SimpleService,它将映射到生成的 WSDL 文件中的 wsdl:service 元素。生成的 WSDL 中使用的目标名称空间是 http://example.org

另外,可以指定 @WebService 批注的下列其他特性:

  • endpointInterface – 现有服务端点接口文件的完全限定名称。如果指定此特性,jwsc Ant 任务不会生成接口,但会假设已创建该接口且它位于 CLASSPATH 中。

@WebService 批注的所有特性都不是必需项。有关每个特性的默认值,请参阅 Web Services Metadata for the Java Platform

指定 Web Service 到 SOAP 消息协议的映射

假设您希望通过 SOAP 消息协议提供 Web Service;因此,JWS 文件中应当在类级别包含标准 @SOAPBinding 批注,以指定 Web Service 的 SOAP 绑定(RPC 编码或 document-literal-wrapped),如以下代码摘录所示:

@SOAPBinding(style=SOAPBinding.Style.DOCUMENT,
use=SOAPBinding.Use.LITERAL,
parameterStyle=SOAPBinding.ParameterStyle.WRAPPED)

在该示例中,Web Service 使用 document-wrapped-style 编码和文字消息格式,如果未指定 @SOAPBinding 批注,则这类格式也是默认格式。

另外,可以使用 WebLogic 特定的 @weblogic.jws.soap.SOAPBinding 批注在方法级别指定 SOAP 绑定;其特性与标准 @javax.jws.soap.SOAPBinding 批注的特性相同。

使用 parameterStyle 批注(与 style=SOAPBinding.Style.DOCUMENT 特性结合使用)指定 Web Service 操作参数是代表全部 SOAP 消息正文,还是包装为与操作同名的顶级元素的元素。

下表列出 @SOAPBinding(标准或 WebLogic 特定)批注的三个特性的可能值和默认值。

表 5-1:@SOAPBinding 批注的特性

特性

可能值

默认值

style

SOAPBinding.Style.RPC<br /> <br />SOAPBinding.Style.DOCUMENT

SOAPBinding.Style.DOCUMENT

use

SOAPBinding.Use.LITERAL<br /> <br />SOAPBinding.Use.ENCODED

SOAPBinding.Use.LITERAL

parameterStyle

SOAPBinding.ParameterStyle.BARE<br /> <br />SOAPBinding.ParameterStyle.WRAPPED

SOAPBinding.ParameterStyle.WRAPPED

指定 Web Service 的上下文路径和服务 URI

使用 WebLogic 特定的 @WLHttpTransport 批注指定通过 HTTP 传输调用 Web Service 的 URL 的上下文路径和服务 URI 部分,以及生成的 WSDL 中的端口名称,如以下代码摘录所示:

@WLHttpTransport(contextPath="simple", serviceUri="SimpleService",
portName="SimpleServicePort")

在该示例中,jwsc Ant 任务生成的 WSDL 文件中的端口名称(具体来说,即 <port> 元素的 name 特性)是 SimpleServicePort。用于通过 HTTP 调用 Web Service 的 URL 包括上下文路径 simple 和服务 URI SimpleService,如下例中所示:

http://host:port/simple/SimpleService

有关此批注和其他 WebLogic 特定批注的参考文档,请参阅 JWS 批注参考

指定 JWS 方法公开为公共操作

使用标准 @WebMethod 批注指定 JWS 文件的一个方法应公开为 Web Service 的公共操作,如以下代码摘录所示:

public class SimpleImpl {

@WebMethod(operationName="sayHelloOperation")
public String sayHello(String message) {
System.out.println("sayHello:" + message);
return "Here is the message: '" + message + "'";
}
...

在该示例中,SimpleImpl JWS 文件的 sayHello() 方法公开为 Web Service 的公共操作。不过,operationName 特性指定 WSDL 文件中操作的公共名称是 sayHelloOperation。如果不指定 operationName 特性,则操作的公共名称就是方法本身的名称。

另外,可以使用 action 特性指定操作的行为。在使用 SOAP 作为绑定时,action 特性的值确定 SOAP 消息中 SOAPAction 头的值。

可以使用标准 @Oneway 批注指定操作不向调用应用程序返回值,如下例所示:

public class OneWayImpl {

@WebMethod()
@Oneway()

public void ping() {
System.out.println("ping operation");
}

...

如果将某个操作指定为单向,则需要实现方法以返回 void,不能使用 Holder 类作为参数,也不能引发任何 checked 异常。

@WebMethod 批注的所有特性都不是必需项。有关每个特性的默认值,以及有关 @WebMethod@Oneway 批注的其他信息,请参阅 Web Services Metadata for the Java Platform

如果 JWS 文件中的所有公共方法都尚未使用 @WebMethod 批注进行批注,则在默认情况下,__所有公共方法都会公开为 Web Service 操作。

自定义操作参数和 WSDL 部件之间的映射

使用标准 @WebParam 批注自定义 Web Service 的操作输入参数与生成的 WSDL 文件中的元素之间的映射,并指定参数的行为,如以下代码摘录所示:

public class SimpleImpl {

@WebMethod()
@WebResult(name="IntegerOutput",
targetNamespace="http://example.org/docLiteralBare")
public int echoInt(
@WebParam(name="IntegerInput",
targetNamespace="http://example.org/docLiteralBare")
int input)

{
System.out.println("echoInt '" + input + "' to you too!");
return input;
}
...

在该示例中,生成的 WSDL 中 echoInt 操作的参数名称是 IntegerInput;如果 JWS 文件中不存在 @WebParam 批注,则生成的 WSDL 文件中参数的名称将与方法参数的名称相同:inputtargetNamespace 特性指定参数的 XML 名称空间是http://example.org/docLiteralBare;仅在使用 document-style SOAP 绑定,即参数映射至 XML 元素时,该特性才起作用。

另外,可以指定 @WebParam 批注的下列其他特性:

  • mode– 参数流的方向(WebParam.Mode.INWebParam.Mode.OUTWebParam.Mode.INOUT)。只能为符合 Holder 类型的 JAX-RPC 定义的参数类型指定 OUT 和 INOUT 模式。仅 RPC 样式操作或映射至头的参数支持 OUT 和 INOUT 模式。
  • header – 布尔特性,设置为 true 时,则指定应当从 SOAP 头而不是从默认正文中检索出的参数的值。

@WebParam 批注的所有特性都不是必需项。有关每个特性的默认值,请参阅 Web Services Metadata for the Java Platform

自定义操作返回值与 WSDL 部件之间的映射

使用标准 @WebResult 批注自定义 Web Service 操作返回值与生成 WSDL 文件中的对应元素之间的映射,如以下代码摘录所示:

public class Simple {

@WebMethod()
@WebResult(name="IntegerOutput",
targetNamespace="http://example.org/docLiteralBare")
public int echoInt(
@WebParam(name="IntegerInput",
targetNamespace="http://example.org/docLiteralBare")
int input)

{
System.out.println("echoInt '" + input + "' to you too!");
return input;
}
...

在该示例中,生成的 WSDL 中的 echoInt 操作的返回值名称是 IntegerOutput;如果 JWS 文件中不存在 @WebResult 批注,则所生成 WSDL 文件中返回值的名称将是硬编码名称 returntargetNamespace 特性指定返回值的 XML 名称空间是http://example.org/docLiteralBare;仅在使用 document-style SOAP 绑定,即返回值映射至 XML 元素时,该特性才起作用。

@WebResult 批注的所有特性都不是必需项。有关每个特性的默认值,请参阅 Web Services Metadata for the Java Platform


使用 JwsContext 访问有关 Web Service 的运行时信息

当客户端应用程序调用使用 JWS 文件实现的 WebLogic Web Service 时,WebLogic Server 会自动创建一个上下文__,Web Service 可以使用该上下文来访问有关该服务的运行时信息,有时还可以更改这些信息。此信息主要与对话相关,例如当前对话是否已完成、对话属性的当前值以及在运行时更改对话属性等。(有关对话和如何实现对话的信息,请参阅创建对话 Web Service。)可以通过该上下文访问的某些信息更为通用,如用于调用该 Web Service 的协议(HTTP/S 或 JMS)、SOAP 消息请求中的 SOAP 头等。

可以在 JWS 文件中使用批注和 WebLogic Web Service API 访问运行时上下文信息,如下列部分所述。

访问 Web Service 上下文的准则

下例说明使用上下文确定用于调用 Web Service 的协议的简单 JWS 文件;该示例之后的编程准则中将讨论用粗体显示的代码。

package examples.webservices.jws_context;

import javax.jws.WebMethod;
import javax.jws.WebService;

import weblogic.jws.WLHttpTransport;
import weblogic.jws.Context;

import weblogic.wsee.jws.JwsContext;<br />import weblogic.wsee.jws.Protocol;

@WebService(name="JwsContextPortType", serviceName="JwsContextService",
targetNamespace="http://example.org")

@WLHttpTransport(contextPath="contexts", serviceUri="JwsContext",
portName="JwsContextPort")

/**
* 说明如何使用 @Context 批注的简单 Web Service。
*/

public class JwsContextImpl {

  @Context<br />  private JwsContext ctx;

@WebMethod()
public String getProtocol() {

    Protocol protocol = ctx.getProtocol();

System.out.println("protocol: " + protocol);
return "This is the protocol: " + protocol;
}
}

使用 JWS 文件中的下列准则访问 Web Service 的运行时上下文,如上例中用粗体显示的代码所示:

  • 导入 @weblogic.jws.Context JWS 批注:
    import weblogic.jws.Context;
  • 导入 weblogic.wsee.jws.JwsContext API 以及可能使用的所有其他相关 API(该示例还使用 weblogic.wsee.jws.Protocol API):
    import weblogic.wsee.jws.JwsContext;
    import weblogic.wsee.jws.Protocol;

    有关上下文相关 API 的参考文档,请参阅 weblogic.wsee.* Javadocs。

  • 使用字段级 @Context JWS 批注对 weblogic.wsee.jws.JwsContext 数据类型的私有变量进行批注:
    @Context
    private JwsContext ctx;

    第一次调用 Web Service 时,WebLogic Server 自动为已批注变量(在该例中为 ctx)分配 JwsContext 运行时实现,所以,以后无需在代码中明确初始化该变量即可以使用它。

  • 使用 JwsContext 类的方法获取和在某些情况下更改有关 Web Service 的运行时信息。下例说明如何获取用于调用 Web Service 的协议:
    Protocol protocol = ctx.getProtocol();

    有关可用方法的完整列表,请参阅 JwsContext 的方法

JwsContext 的方法

下表简单介绍 JwsContext 的方法,可以在 JWS 文件中使用这些方法,以访问有关 Web Service 的运行时信息。有关 JwsContext 以及 ProtocolServiceHandle 等其他上下文相关 API 的详细参考信息,请参阅 weblogic.wsee.* Javadocs。

表 5-2:JwsContext 的方法

方法

返回值

描述

isFinished()

boolean

返回一个布尔值,指定当前对话已结束还是仍在继续。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

finishConversation()

void

完成当前对话。

此方法相当于调用已使用 @Conversation (Conversation.Phase.FINISH) JWS 批注进行批注的方法的客户端应用程序。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

setMaxAge(java.util.Date)

void

将新的最大对话期限设置为绝对 Date。如果 date 参数为过去的日期,WebLogic Server 会立即结束该对话。

此方法相当于 @Conversational 批注的 maxAge 特性__,该特性指定默认的最大对话期限。使用此方法在运行时替代此默认值。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

setMaxAge(String)

void

通过指定 String 持续时间,例如 1 day,来设置新的最大对话期限。

String 参数的有效值为数字和下列期限之一:

  • seconds
  • minutes
  • hours
  • days
  • years

例如,要指定最大期限为 10 分钟,请使用以下语法:

ctx.setMaxAge("10 minutes")

此方法相当于 @Conversational 批注的 maxAge 特性__,该特性指定默认的最大对话期限。使用此方法在运行时替代此默认值。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

getMaxAge()

long

返回允许的最大对话期限,以秒为单位。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

getCurrentAge()

long

返回对话的当前期限,以秒为单位。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

resetIdleTime()

void

重置用于计量当前会话中上一次活动之后经过的秒数的计时器。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

setMaxIdleTime(long)

void

设置在 WebLogic Server 因客户端不活动而结束对话之前,对话可保持空闲的秒数。

此方法相当于 @Conversational 批注的 maxIdleTime 特性__,该特性指定默认的对话空闲时间。使用此方法在运行时替代此默认值。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

setMaxIdleTime(String)

void

设置在 WebLogic Server 因客户端不活动而结束对话之前,对话可保持空闲的秒数(指定为 String)。

String 参数的有效值为数字和下列期限之一:

  • seconds
  • minutes
  • hours
  • days
  • years

例如,要指定最大空闲时间为 10 分钟,请使用以下语法:

ctx.setMaxIdleTime("10 minutes")

此方法相当于 @Conversational 批注的 maxIdleTime 特性__,该特性指定默认的对话空闲时间。使用此方法在运行时替代此默认值。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

getMaxIdleTime()

long

返回在 WebLogic Server 因客户端不活动而结束对话之前,允许对话保持空闲的秒数。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

getCurrentIdleTime()

long

获取最后一个客户端请求后,或重置对话的最大空闲时间后的秒数。

仅在对话 Web Service 中,或者在已使用 @Conversation@Conversational 批注进行批注的 Web Service 中使用此方法。

getCallerPrincipal()

java.security.Principal

返回与刚刚调用的操作关联的安全委托人,假设已执行基本身份验证。

isCallerInRole(String)

boolean

如果经身份验证的委托人具有指定的安全角色,则返回 true

getService()

weblogic.wsee.jws.ServiceHandle

返回 ServiceHandle 的实例,即一个 WebLogic Web Service API,可查询该 API 以收集有关 Web Service 的其他信息,例如对话 ID(如果 Web Service 为对话)和 Web Service 的 URL 等。

getLogger(String)

weblogic.wsee.jws.util.Logger

获取 Logger 类的实例,可使用该实例将消息从 Web Service 发送到日志文件。

getInputHeaders()

org.w3c.dom.Element[]

返回与当前操作调用的 SOAP 请求消息关联的 SOAP 头数组。

setUnderstoodInputHeaders(boolean)

void

指明是否应了解输入头。

getUnderstoodInputHeaders()

boolean

返回最近通过调用 setUnderstoodInputHeader 设置的值。

setOutputHeaders(Element[])

void

指定应当与传出 SOAP 响应消息(发送回最初调用当前操作的客户端应用程序)关联的 SOAP 头数组。

getProtocol()

weblogic.wsee.jws.Protocol

返回用于调用当前操作的协议(如 HTTP/S 或 JMS)。


是否要实现无状态会话 EJB?

jwsc Ant 任务始终选择常规 Java 对象,作为处理 JWS 文件时的 Web Service 底层实现。

不过,有时可能要将 Web Service 的底层实现作为无状态会话 EJB,从而利用 EJB 提供的所有特性,例如实例缓冲池、事务、安全、容器管理的持久性、容器管理的关系和数据缓存等。如果决定需要 Web Service 的 EJB 实现,请遵循以下部分中的编程准则。

在 JWS 文件中实现 EJB 时的编程准则

一般准则是始终在 JWS 文件中使用 EJBGen 批注,以自动生成而不是手工创建实现 EJB 时需要的 EJB Remote 类、Home 接口类和部署描述符文件。EJBGen 批注的工作方式与 JWS 批注相同:它们遵循 JDK 5.0 元数据语法,可显著简化编程任务。

有关 EJBGen 的详细信息,请参阅 WebLogic Enterprise JavaBean 编程 中的 EJBGen 参考 部分。

在 JWS 文件中明确实现无状态会话 EJB 时,请遵循上述准则。有关示例,请参阅实现 EJB 的 JWS 文件示例,相关部分用粗体显示:

  • 导入标准 J2EE EJB 类:
    import javax.ejb.SessionBean;
    import javax.ejb.SessionContext;
  • 导入 EJBGen 批注,所有批注都包含在 weblogic.ejbgen 包中。至少需要导入 @Session 批注;如果希望在 JWS 文件中使用其他 EJBGen 批注指定 EJB 的形状和行为,请参阅 EJBGen 参考指南。
    import weblogic.ejbgen.Session;
  • 至少应在类级别使用 @Session 批注指定 EJB 的名称:
    @Session(ejbName="TransactionEJB")

    @Session 是唯一一个必须在 JWS 文件中使用的 EJBGen 批注。如果希望,可以使用其他 EJBGen 批注指定 EJB 的其他特性。

  • 确保 JWS 类实现 SessionBean
    public class TransactionImpl implements SessionBean {...
  • 另外,必须包含标准 EJB 方法 ejbCreate()ejbActivate() 等,即便除了希望更改 EJB 的默认行为的情况下以外,通常并不需要向这些方法中添加代码:
    public void ejbCreate() {}
    public void ejbActivate() {}
    public void ejbRemove() {}
    public void ejbPassivate() {}
    public void setSessionContext(SessionContext sc) {}

如果在 JWS 文件中遵循上述全部准则,jwsc Ant 任务稍后会将 Web Service 编译为 EJB,并将其打包到企业应用程序的 EJB JAR 文件中。

实现 EJB 的 JWS 文件示例

下例给出一个实现无状态会话 EJB 的简单 JWS 文件。相关代码用粗体显示。

package examples.webservices.transactional;

import javax.ejb.SessionBean;<br />import javax.ejb.SessionContext;

import javax.jws.WebMethod;
import javax.jws.WebService;

import weblogic.jws.WLHttpTransport;
import weblogic.jws.Transactional;

import weblogic.ejbgen.Session;

@Session(ejbName="TransactionEJB")

@WebService(name="TransactionPortType", serviceName="TransactionService",
targetNamespace="http://example.org")

@WLHttpTransport(contextPath="transactions", serviceUri="TransactionService",
portName="TransactionPort")

/**
* 此 JWS 文件形成了带有下列单个操作的简单 EJB 实现的 WebLogic
* Web Service 的基础:sayHello。此操作作为事务的一部分
* 执行。
*
*/

public class TransactionImpl implements SessionBean {

@WebMethod()
@Transactional(value=true)

public String sayHello(String message) {
System.out.println("sayHello:" + message);
return "Here is the message: '" + message + "'";
}

// 标准 EJB 方法。通常无需替换这些方法。

  public void ejbCreate() {}<br />  public void ejbActivate() {}<br />  public void ejbRemove() {}<br />  public void ejbPassivate() {}<br />  public void setSessionContext(SessionContext sc) {}<br />}

编写用户定义的 Java 数据类型

公开为 Web Service 操作的 JWS 文件的方法无需使用内置数据类型(如字符串和整数类型)作为参数,也无需返回值,而是应当使用您自己创建的 Java 数据类型。用户定义数据类型的示例是 TradeResult,它包含两个字段:String 股票代码和代表交易股数的整数。

如果 JWS 文件使用用户定义的数据类型作为它的一个或多个方法的参数或返回值,则必须创建您自己的数据类型的 Java 代码,然后将该类导入 JWS 文件并相应地使用它。jwsc Ant 任务稍后会创建所有必需的数据绑定工件,例如,Java 用户定义数据类型的对应 XML Schema 表示、JAX-RPC 类型映射文件等。

在为用户定义数据类型编写 Java 类时,请遵循下列基本要求:

  • 定义不使用参数的默认构造方法。
  • 对于要公开公布的每个成员变量,定义 getXXX()setXXX() 方法。
  • 将公开的每个成员变量的数据类型设置为内置数据类型之一,或设置为包含内置数据类型的其他用户定义数据类型。

这些要求由 JAX-RPC 1.1 指定;有关更详细的信息和完整的要求列表,请参阅 JAX-RPC specification

jwsc Ant 任务可为大多数常用 XML 和 Java 数据类型生成数据绑定工件。有关支持的用户定义数据类型的列表,请参阅支持的用户定义数据类型。有关支持的内置数据类型的完整列表,请参阅支持的内置数据类型

下例介绍称为 BasicStruct 的简单 Java 用户定义数据类型:

package examples.webservices.complex;

/**
* 定义一个具有 integer、String
* 和 String[] 属性的名为 BasicStruct 的简单 JavaBean
*/

public class BasicStruct {

// 属性

private int intValue;
private String stringValue;
private String[] stringArray;

// 获取器和设置器方法

public int getIntValue() {
return intValue;
}

public void setIntValue(int intValue) {
this.intValue = intValue;
}

public String getStringValue() {
return stringValue;
}

public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}

public String[] getStringArray() {
return stringArray;
}

public void setStringArray(String[] stringArray) {
this.stringArray = stringArray;
}

}

以下段落选自 JWS 文件,说明如何导入 BasicStruct 类和将该类其方法之一的参数和返回值;有关完整的 JWS 文件,请参阅示例 ComplexImpl.java JWS 文件

package examples.webservices.complex;

// 导入标准 JWS 批注接口

import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;

// 导入 WebLogic 特定的 JWS 批注接口

import weblogic.jws.WLHttpTransport;

// 导入 BasicStruct JavaBean

import examples.webservices.complex.BasicStruct;

@WebService(serviceName="ComplexService", name="ComplexPortType",
targetNamespace="http://example.org")

...

public class ComplexImpl {

@WebMethod(operationName="echoComplexType")
public BasicStruct echoStruct(BasicStruct struct)

{
return struct;<br /> }
}

引发异常

在 JWS 文件的方法中编写错误处理 Java 代码时,可以引发您自己的用户定义异常,也可以引发 javax.xml.rpc.soap.SOAPFaultException 异常。如果引发 SOAPFaultException 异常,WebLogic Server 会将其映射到 SOAP 错误,并将其发送至调用该操作的客户端应用程序。

如果 JWS 文件引发 SOAPFaultException 以外的任何 Java 异常类型,WebLogic Server 会尝试尽可能将其映射至 SOAP 错误。不过,如果希望控制由哪一个客户端应用程序检索并向其发送最相关的异常信息,应明确引发 SOAPFaultException 异常或引发扩展该异常的异常。有关创建和引发您自己的用户定义异常的详细信息,请参阅 JAX-RPC 1.1 specification

以下代码摘录介绍 SOAPFaultException 类:

public class SOAPFaultException extends java.lang.RuntimeException {
public SOAPFaultException (QName faultcode,
String faultstring,
String faultactor,
javax.xml.soap.Detail detail ) {...}
public Qname getFaultCode() {...}
public String getFaultString() {...}
public String getFaultActor() {...}
public javax.xml.soap.Detail getDetail() {...}
}

使用 SOAP with Attachments API for Java 1.1 (SAAJ) javax.xml.soap.SOAPFactory.createDetail() 方法创建 Detail 对象,该对象是提供有关错误的详细应用程序特定信息的 DetailEntry 对象的容器。

可以使用您自己或 BEA 的 SOAPFactory 实现,可以在 JWS 文件中访问后者,方法是通过调用返回 javax.xml.soap.SOAPFactory objectweblogic.wsee.util.WLSOAPFactory.createSOAPFactory() 静态方法。然后,在运行时使用 -Djavax.xml.soap.SOAPFactory 标志指定 BEA 的 SOAPFactory 实现,如下所示:

-Djavax.xml.soap.SOAPFactory=weblogic.xml.saaj.SOAPFactoryImpl

以下 JWS 文件显示通过实现 Web Service 操作的方法创建并引发 SOAPFaultException;各部分中用粗体突出显示异常代码:

package examples.webservices.soap_exceptions;

import javax.xml.namespace.QName;<br />import javax.xml.soap.Detail;<br />import javax.xml.soap.SOAPException;<br />import javax.xml.soap.SOAPFactory;<br />import javax.xml.rpc.soap.SOAPFaultException;

// 导入 @WebService 批注

import javax.jws.WebService;

// 导入 WLHttpTransport

import weblogic.jws.WLHttpTransport;

@WebService(serviceName="SoapExceptionsService",
name="SoapExceptionsPortType",
targetNamespace="http://example.org")

@WLHttpTransport(contextPath="exceptions",
serviceUri="SoapExceptionsService",
portName="SoapExceptionsServicePort")
/**
* 此 JWS 文件形成了带有下列单个操作的简单 Java 类实现的 WebLogic
* Web Service 的基础:sayHelloWorld
*
* @作者版权所有 (c) 2005,BEA Systems。保留所有权利。
*/

public class SoapExceptionsImpl {

public SoapExceptionsImpl() {

}

public void tirarSOAPException() {

    Detail detail = null;

    try {

      SOAPFactory soapFactory = SOAPFactory.newInstance();<br />      detail = soapFactory.createDetail();

    } catch (SOAPException e) {<br />        // 执行某些操作<br />    }

    QName faultCode = null;<br />    String faultString = "the fault string";<br />    String faultActor = "the fault actor";<br />    throw new SOAPFaultException(faultCode, faultString, faultActor, detail);<br />  }  
}

以上示例使用 SOAPFactory 的默认实现。

警告:

如果您创建和引发自己的异常(而不是使用 SOAPFaultException),而且您的异常类的两个或多个属性具有相同数据类型,那么还必须__为这些属性创建 setter 方法,即使 JAX-RPC 规范并不要求这样做也是如此。这是因为在 WebLogic Web Service 通过 SOAP 消息接收异常时,会将 XML 转换为 Java 异常类,如果不使用对应的 setter 方法,则无法确定 XML 元素与类属性之间的映射关系。


从 JWS 文件调用另一 Web Service

在 JWS 文件中可以调用另一 Web Service,它既可以部署在 WebLogic Server 上,也可以部署在 .NET 等其他应用服务器上。执行该操作的步骤与从独立 JAX-RPC Java 客户端调用 Web Service中介绍的对应步骤相似,只是不运行 clientgen Ant 任务生成客户端存根控件,而是包含构建调用 Web Service 以生成客户端存根控件的 jwsc Ant 任务的 <clientgen> 子元素。然后,与在独立客户端应用程序中一样,在 JWS 文件中使用标准 JAX-RPC API。

有关详细说明,请参阅从其他 Web Service 中调用 Web Service


使用 JWS 批注和 API 编写其他杂项功能

下列部分介绍通过在 JWS 文件中指定特定 JWS 批注或使用 WebLogic Web Service API 可以编写的其他杂项功能:

流 SOAP 附件

通过使用 @weblogic.jws.StreamAttachments JWS 批注,可以指定 Web Service 在读取包含附件的入站 SOAP 消息时使用流 API,而不是执行服务将整条消息读取到内存中的默认行为。此功能可以提高 SOAP 消息特别大的 Web Service 的性能。

有关指定应使用流的附件的示例,请参阅 weblogic.jws.StreamAttachments

使用 SOAP 1.2

默认情况下,WebLogic Web Service 使用简单对象访问协议 (SOAP) 版本 1.1,作为在 Web Service 与其客户端之间传输数据和调用呼叫时的消息格式。要指定 Web Service 使用 SOAP 版本 1.2,请在 JWS 文件中使用类级别 @weblogic.jws.Binding批注并将其单个特性设置为值 Binding.Type.SOAP12,如下例所示(相关代码用粗体显示):

package examples.webservices.soap12;

import javax.jws.WebMethod;
import javax.jws.WebService;

import weblogic.jws.WLHttpTransport;
import weblogic.jws.Binding;

@WebService(name="SOAP12PortType",
serviceName="SOAP12Service",
targetNamespace="http://example.org")

@WLHttpTransport(contextPath="soap12",
serviceUri="SOAP12Service",
portName="SOAP12ServicePort")

@Binding(Binding.Type.SOAP12)

/**
* 此 JWS 文件形成了带有下列单个操作的简单 Java 类实现的 WebLogic
* Web Service 的基础:sayHello。该类绑定了 SOAP 1.2。
*
*
*/

public class SOAP12Impl {

@WebMethod()
public String sayHello(String message) {
System.out.println("sayHello:" + message);
return "Here is the message: '" + message + "'";
}
}

除设置该批注外,无需执行任何其他操作即可指定 Web Service 使用SOAP 1.2,包括更改调用 Web Service 的客户端应用程序;WebLogic Web Service 运行时会完成其他操作。

指定操作在事务内运行

默认情况下,当客户端应用程序调用 WebLogic Web Service 操作时,该操作调用会在事务上下文以外发生。如果希望操作在事务内运行,请在 JWS 文件中指定 @weblogic.jws.Transactional 批注,然后将布尔特性 value 设置为 true,如下例所示(相关代码用粗体显示):

package examples.webservices.transactional;

import javax.jws.WebMethod;
import javax.jws.WebService;

import weblogic.jws.WLHttpTransport;
import weblogic.jws.Transactional;

@WebService(name="TransactionPojoPortType",
serviceName="TransactionPojoService",
targetNamespace="http://example.org")

@WLHttpTransport(contextPath="transactionsPojo",
serviceUri="TransactionPojoService",
portName="TransactionPojoPort")

/**
* 此 JWS 文件形成了带有下列单个操作的简单 WebLogic
* Web Service 的基础:sayHello。此操作作为事务的一部分
* 执行。
*
*/

public class TransactionPojoImpl {

@WebMethod()
@Transactional(value=true)<br /> public String sayHello(String message) {
System.out.println("sayHello:" + message);
return "Here is the message: '" + message + "'";
}
}

如果希望 Web Service 的所有__操作都在事务内运行,请在类级别指定 @Transactional 批注。如果仅希望在事务中运行操作的子集,请在方法级别指定批注。如果存在冲突,方法级别的值将替代类级别的值。

有关其他特性的信息,请参阅 weblogic.jws.Transactional

获取 HttpServletRequest/Response 对象

如果您的 Web Service 使用 HTTP 作为传输协议,则使用 <a href="http://e-docs.bea.com/wls/docs92/javadocs/weblogic/wsee/connection/transport/servlet/package-summary.html">weblogic.wsee.connection.transport.servlet.HttpTransportUtils</a> API 可以从 JAX-RPC ServletEndpointContext 对象获取 javax.servlet.http.HttpServletRequestjavax.servlet.http.HttpServletResponse 对象,如以下示例所示(相应的代码以粗体表示,在示例后有相应的说明):

package examples.webservices.http_transport_utils;

import javax.xml.rpc.server.ServiceLifecycle;<br />import javax.xml.rpc.server.ServletEndpointContext;<br />import javax.xml.rpc.ServiceException;

import javax.servlet.http.HttpServletRequest;<br />import javax.servlet.http.HttpServletResponse;

import javax.jws.WebMethod;
import javax.jws.WebService;

import weblogic.jws.WLHttpTransport;

import weblogic.wsee.connection.transport.servlet.HttpTransportUtils;

@WebService(name="HttpTransportUtilsPortType",
serviceName="HttpTransportUtilsService",
targetNamespace="http://example.org")

@WLHttpTransport(contextPath="servlet", serviceUri="HttpTransportUtils",
portName="HttpTransportUtilsPort")

public class HttpTransportUtilsImpl implements ServiceLifecycle {

  private ServletEndpointContext wsctx = null;

  public void init(Object context) throws ServiceException {<br />    System.out.println("ServletEndpointContext inited...");<br />    wsctx = (ServletEndpointContext)context;<br />  }

  public void destroy() {<br />    System.out.println("ServletEndpointContext destroyed...");<br />    wsctx = null;<br />  }

@WebMethod()
public String getServletRequestAndResponse() {

    HttpServletRequest request =<br />       HttpTransportUtils.getHttpServletRequest(wsctx.getMessageContext());<br />    HttpServletResponse response =<br />       HttpTransportUtils.getHttpServletResponse(wsctx.getMessageContext());

System.out.println("HttpTransportUtils API used successfully.");
return "HttpTransportUtils API used successfully";

}

}

上述示例的重要部分如下:

  • 导入所需的 JAX-RPC 和 Servlet 类:
    import javax.xml.rpc.server.ServiceLifecycle;
    import javax.xml.rpc.server.ServletEndpointContext;
    import javax.xml.rpc.ServiceException;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
  • 导入 WebLogic HttpTransportUtils 类:
    import weblogic.wsee.connection.transport.servlet.HttpTransportUtils;
  • 由于您将查询 JAX-RPC 消息上下文,因此您的 JWS 文件必须明确实现 ServiceLifecycle
    public class HttpTransportUtilsImpl implements ServiceLifecycle 
  • 创建 ServletEndpointContext 数据类型的变量:
    private ServletEndpointContext wsctx = null;
  • 由于 JWS 文件实现 ServiceLifecycle,因此您还必须实现 initdestroy 生命周期方法:
    public void init(Object context) throws ServiceException {
    System.out.println("ServletEndpointContext inited...");
    wsctx = (ServletEndpointContext)context;
    }
    public void destroy() {
    System.out.println("ServletEndpointContext destroyed...");
    wsctx = null;
    }
  • 最后,在实现 Web Service 操作的方法中,使用 ServletEndpointContext 对象获取 HttpServletRequestHttpServletResponse 对象:
    HttpServletRequest request =
    HttpTransportUtils.getHttpServletRequest(wsctx.getMessageContext());
    HttpServletResponse response =
    HttpTransportUtils.getHttpServletResponse(wsctx.getMessageContext());

JWS 编程最佳实践

以下列表提供了 JWS 文件编程时的部分最佳实践:

  • 在创建 document-literal-bare Web Service 时,使用 @WebParam JWS 批注确保给定 Web Service 的所有操作的所有输入参数都具有唯一名称。 document-literal-bare Web Service 的性质决定了如果不明确使用 @WebParam 批注指定输入参数的名称,WebLogic Server 会创建一个名称,所以可能造成 Web Service 内的参数名称重复。

  • 一般而言,document-literal-wrapped Web Service 是互操作性最强的 Web Service 类型。
  • 使用 @WebResult JWS 批注明确设置操作返回值的名称,而不是始终依赖于硬编码名称 return,如果没有在 JWS 文件中使用 @WebResult 批注,则该硬编码名称是返回值的默认名称。
  • 如果希望控制在调用 Web Service 时遇到错误的情况下传递回客户端应用程序的异常信息,请在 JWS 文件中使用 SOAPFaultExceptions。
  • 虽然并非必需操作,但 BEA 建议您始终在 JWS 文件中指定 WebLogic 特定 @WLHttpTransport 批注的 portName 特性。如果不指定此特性,jwsc Ant 任务将在生成 WSDL 文件时为您生成端口名称,但该名称可能不会非常便于用户记忆。因此,不会为在客户端应用程序中用于调用 Web Service 的 getXXX() 方法指定适当名称。为确保客户端应用程序在调用 Web Service 时使用最便于用户使用的方法,请使用 portName 特性指定 Web Service 端口的相对名称。

返回顶部 上一页 下一页

© 2008 BEA Systems

转载请注明:WebLogic Android 博客 » WebLogic Server 9 的 Web Service 编程之 JWS