基于 Java SOAP 的基于 HTTP2 的 WebService 端点

Posted

技术标签:

【中文标题】基于 Java SOAP 的基于 HTTP2 的 WebService 端点【英文标题】:Java SOAP based WebService endpoint over HTTP2 【发布时间】:2016-03-15 10:08:49 【问题描述】:

是否可以在 java 9 发布之前编写基于 SOAP 的 WebService 和客户端通过 HTTP2 进行通信?

如果是,我应该如何完成这项任务?

背景。最近我阅读并观看了一些关于 HTTP2 的很酷的东西。

文章: HTTP/2: A jump-start for Java developers

书籍章节: High Performance Browser Networking

还有视频:

unRESTful Web Services with HTTP2 by F*** Stäber

Simone Bordet - HTTP 2.0 & Java: Current Status

简而言之,HTTP/2 更高效,解决了 HTTP/1.1 的问题,并且对 Web 应用程序是透明的(简化了它只是通过网络传输消息的不同表示)。

看起来您可以在使用 RESTful Web 服务时轻松切换到 HTTP2。 您需要在服务器端做的就是通过 Jetty(或其他支持 HTTP2 的容器)部署应用程序。

在客户端使用特殊的 Jetty HttpClient:

// Standard HTTP/1.1 client
new HttpClient();

// HTTP/2 transport client
new HttpClient(new HttpClientTransportOverHTTP2());

您可以通过 HTTP2 进行通信。

另一方面,基于 SOAP 的 WebServices 则完全不同(它们基于 JAX-WS API)。 您可以像这样定义服务器端端点:

@WebService
public class HelloWorld 
    public String hello(String name) 
        return "Hello " + name;
    

使用 java wsgen 生成一些代码,然后像这样运行它:

public class RunService 
   public static void main(String[] args) 
       Endpoint.publish("http://localhost:8080/wsServerExample", new HelloWorld());
   

对于客户端,当您从 WSDL(使用 java wsimport)生成代码时,您可以像这样调用此服务:

public class WsClient 
    public static void main(String args[]) 
        HelloWorldService shs = new HelloWorldService();
        HelloWorld sh = shs.getHelloWorldPort();
        ((BindingProvider) sh).getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://localhost:8080/wsServerExample");
        System.out.println(sh.hello("bary"));
    

对于服务器,您可以通过更改属性 com.sun.net.httpserver.HttpServerProvider 来提供 HttpServer 的不同实现,例如:

System.setProperty("com.sun.net.httpserver.HttpServerProvider", "org.eclipse.jetty.http.spi.JettyHttpServerProvider");

但这不会为您提供 HTTP2 传输(对吗?)。

所以在我看来,这种基于 SOAP 的 WebServices 的 HTTP 传输被深埋在 java API 内部,在 java 9 之前无法切换到 HTTP2(或者至少我不知道如何做到这一点)?

我错过了什么吗?如果您有任何想法,请分享。

谢谢

【问题讨论】:

【参考方案1】:

要使服务器端能够提供 http/2 端点,您需要一个支持 http/2 的服务器(jetty 或 undertow 从 2017 年 4 月起支持它)。

此外,服务器必须配置为提供 https,即您必须添加 ssl/tls-certificate。因此,您创建了一个包含服务器证书的 java 密钥库。

虽然 http/2 的工作不需要 https,但大多数客户端都需要对连接进行加密。此外,在使用 jetty 或 undertow 等服务器时,您必须通过添加 alpn-jar 来添加对 alpn(应用层协议协商)的支持。

如果你使用 Spring Boot 和 Undertow 作为你的服务器,你可以这样配置它:

@Bean
UndertowEmbeddedServletContainerFactory embeddedServletContainerFactory() 
    UndertowEmbeddedServletContainerFactory factory = new UndertowEmbeddedServletContainerFactory();
    factory.addBuilderCustomizers(
            builder -> builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
    return factory;

这应该添加到您的 application.properties:

server.port=8443
server.ssl.key-store=classpath:sample.jks
server.ssl.key-store-password=secret
server.ssl.key-password=password

启动服务器时,必须将 ALPN-jar 添加到引导类路径:

-Xbootclasspath/p:/home/user_x/.m2/repository/org/mortbay/jetty/alpn/alpn-boot/8.1.8.v20160420/alpn-boot-8.1.8.v20160420.jar

您的 http/2-client 必须信任服务器的证书。如果您为服务器创建了自签名证书,则必须将其公钥添加到客户端的 jvm 信任库中:

$ keytool -import -trustcacerts -keystore /opt/java/jre/lib/security/cacerts \
-storepass changeit -noprompt -alias mycert -file /tmp/examplecert.crt

这个答案的灵感来自这篇博文:https://vanwilgenburg.wordpress.com/2016/04/01/spring-boot-http2/

【讨论】:

以上是关于基于 Java SOAP 的基于 HTTP2 的 WebService 端点的主要内容,如果未能解决你的问题,请参考以下文章

TCP 模式下基于 AWS ELB 的 HTTP2

grpc基于http2之上的协议

elang(基于 yaws_soap_lib)soap 客户端的问题

JAVA中使用JSON进行数据传递

RPC接口与REST对比

基于kylinTOP工具的HTTP2压力测试