4

我想在 Java 中创建一个连接到需要摘要式身份验证的 Web 服务的客户端。由于对java和java stack不熟悉,所以研究了一下,遇到了jax-ws、axis2、xcf、metro。我了解到 JAX-WS 是一个 API,JDK 中有一个参考实现,但它缺乏摘要授权支持。

我的第一次尝试是使用axis2,因为Eclipse IDE 中内置了对它的支持。以下代码似乎遵循摘要身份验证工作流程,但不知何故它最终仍然未能通过授权。

Service1Stub stub = new Service1Stub();

HttpTransportProperties.Authenticator authenticator = new Authenticator();
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(Authenticator.DIGEST);
authenticator.setAuthSchemes(authSchemes);
authenticator.setUsername("doman user");
authenticator.setPassword("domain password");
authenticator.setPreemptiveAuthentication(true);
Options options = stub._getServiceClient().getOptions();
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, authenticator);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, org.apache.axis2.Constants.VALUE_FALSE);

GetData getData = new GetData();
getData.setValue(25);
GetDataResponse data = stub.getData(getData);
System.out.println(data.getGetDataResult());

我的第二次尝试是使用 Metro 框架,但我得到了一些与 JAXB 版本相关的错误。

java.lang.LinkageError: JAXB 2.1 API is being loaded from the bootstrap classloader, but this RI needs 2.2 API.

我必须使用 JDK 1.6.0_03,所以我猜这是因为 JDK 版本不匹配而发生的,但我也不想使用建议的“认可目录机制”,因为它可能会在部署过程中造成很多麻烦。

我完全迷失了,我正在寻找最简单、最快和最新的方式来使用需要 Java 中的摘要式身份验证的 Web 服务?最好尽可能少的依赖。

4

2 回答 2

3

Java 类加载是一团糟,抱歉。根本原因是没有像 .NET 世界中那样的强名称,因此运行时链接器会采用类路径中首先出现的任何匹配项,无论这是否是编译代码所针对的库版本。OSGi 系统解决了这个问题,但它从未获得主流采用。

您引用的错误消息:

java.lang.LinkageError:正在从引导类加载器加载 JAXB 2.1 API,但此 RI 需要 2.2 API。

是非常有用和具体的,大多数时候发生的事情是你盯着一个NoSuchMethodError或类似的东西。随着时间的推移,您将学会将这些识别为库版本不匹配。在这种情况下,库作者编写了代码来识别常见错误情况并打印更好的错误消息(祝福他们)。

咆哮,这里有一些信息,我希望能让你走上正轨:

  • Java 类加载器是分层的,分辨率是自下而上的
  • 但是在层次结构的根部有一个有福的类加载器,负责加载核心运行时库
  • 供应商的恶作剧导致很多东西被包含在核心运行时库中,这些东西真的不应该在那里,因为这是在达尔文主义选择过程中占据主导地位的捷径。正如您刚刚发现的那样,JAXB 就是其中之一。JAXB2 实际上相当不错,但它的发展独立于核心运行时,好吧,我们在这里。
  • JDK 和 JRE 安装有一个名为的文件夹lib\endorsed,您可以在其中添加需要由根加载程序加载的 JAR 文件,甚至绕过rt.jar.

总之,如果您手动将 2.2 版本的 JAXB 库添加到%JAVA_HOME%\lib\endorsed,那么它应该覆盖包含的 2.1 版本并且您的 Web 服务客户端将部署。这必须在每个运行 Web 服务客户端的系统上发生,直到 JDK 更新到包含 JAXB 2.2 的 7.x 版本。如果同一个 JVM 正在运行其他基于 JAXB 的应用程序,则这些应用程序可能会或可能不会因此而中断。

是的,这很痛苦。您可以调查的一个切线是故意使用为 JAXB 2.1 构建的旧版 Metro。只要您一定要在 上进行部署1.6.0_03,这可能是更好的选择,尽管失去了 Metro 中最近的一些改进。

更新:这里有一篇关于这个主题的博客文章。它包含一些指向更多信息的链接。

于 2013-02-17T22:09:30.803 回答
1

Metro 框架配置起来太复杂了,而且我发现的文档不完整。所以我已经使用Apache Axis2完成了它。

要遵循的步骤:

  • 下载并解压 Apache Axis2 二进制文件。
  • 引用所有jar文件
  • 转到 /bin 文件夹并使用 wsdl2java 生成客户端代码。

wsdl2java -S src -uri "wsdl_file_location"

将文件夹下的所有内容复制src到您的 java 应用程序并连接到服务,如下所示:

//Fictious is the name of the web service
FictiousStub stub = new FictiousStub("servicelocation/fictiousService.php");

HttpTransportProperties.Authenticator authenticator = new Authenticator();
List<String> authSchemes = new ArrayList<String>();
authSchemes.add(Authenticator.DIGEST);
authenticator.setAuthSchemes(authSchemes);
authenticator.setUsername("admin");
authenticator.setPassword("12345");
authenticator.setPreemptiveAuthentication(true);
Options options = stub._getServiceClient().getOptions();
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.AUTHENTICATE, authenticator);
options.setProperty(org.apache.axis2.transport.http.HTTPConstants.CHUNKED, org.apache.axis2.Constants.VALUE_FALSE);
于 2013-04-02T13:47:54.420 回答