基于 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 端点的主要内容,如果未能解决你的问题,请参考以下文章