LD is tigger forever,CG are not brothers forever, throw the pot and shine forever.
Modesty is not false, solid is not naive, treacherous but not deceitful, stay with good people, and stay away from poor people.
talk is cheap, show others the code and KPI, Keep progress,make a better result.
Survive during the day and develop at night。
Jetty的HTTP模块提供简单易用的APIs和工具来处理HTTP(HTTPS)请求。Jetty的HTTP客户端是不封闭和异步的。它提供一个从不会堵塞I/O的异步的API,提高线程利用率,适合高性能场景如负载测试或并行计算。然而,如果你所有的请求都是使用GET方式来获得一个响应,Jetty的HTTP客户端还提供了一个同步API,这是一个编程接口,线程从发出请求直到请求/响应对话完成才释放。Jetty的HTTP客户端支持不同的协议,如HTTP/1.1, FastCGI 和 HTTP/2。这样HTTP请求可以以不同的方式获得资源,最常用的事HTTP/1.1。
FastCGI传输过程中大量使用Jetty FastCGI的支持,允许Jetty作为反向代理PHP(Apache或Nginx做完全一样),因此能够服务—例如WordPress网站。
解析一个http请求的最简单方法如下:
ContentResponse response = httpClient.GET(“http://domain.com/path?query”);
方法 HttpClient.GET(…)用来通过给定的URI来获得一个HTTP的GET请求,并且当成功响应后返回一个ContentResponse 。
ContentResponse 包含一个HTTP的相应信息:状态码、响应头、响应内容。内容大小被限制在2M内,为了获得更大的内容详见相应内容处理器。
如果你想订做请求信息,例如,使用请求头,请求方式或者浏览器版本,做法如下:
ContentResponse response = httpClient.newRequest(“http://domain.com/path?query”)
.method(HttpMethod.HEAD)
.agent(“Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:17.0) Gecko/20100101 Firefox/17.0”)
.send();
你第一次通过httpClient.newRequest(…)方式创建一个Request对象,然后使用APIs来定制它(可以使用链式调用)。当Request请求被定制完成,你可以调用Request.send()方法来获得成功访问后的ContentResponse 对象。
POST方式的参数通过 param() 方法,并自动进行URL编码。
Jetty的客户端会自动重定向,可以自动处理典型的WEB模式如, POST/Redirect/GET,随后的重定向可以被单独禁用或者全局禁用。
到目前,我们已经展示了如何使用阻塞方式的Jetty HTTP客户端,线程需要等到请求/响应完成后才能结束。
这一章节,我们将着眼于非阻塞式、异步的Jetty HTTP客户端使用方法,这种方法非常适合大文件下载、并行处理,在这些情况下,性能和高效的线程性和资源利用率是一个关键因素。
异步APIs的实现依靠请求和响应各阶段的监听。这些监听器所实现的应用可以有各种类型的逻辑,监听器的实现在同一个线程中来完成请求或响应。所以如果在监听器内的应用程序代码需要较长的执行时间,那么请求或者响应将会等待直到监听器返回结果。
如果你要在监听器内执行一个需要很长时间的代码,你必须创建自己的线程,并且深度拷贝你需要的监听器的任何数据,因为当监听器返回数据后,监听器内的数据有可能会被回收、清除、销毁。
请求和响应将会被两个不同的线程处理也有可能同步进行,一个并发处理典型的例子是一个大文件上传可能与大大文件下载并发进行。符代替性下,响应的处理有可能会在请求没有结束前就已经完成了,典型的例子是一个大文件上传会立即触发一个响应回复如服务器返回的错误信息,响应完成了,但是上传文件依然在继续。
应用程序的线程调用Request.send(Response.CompleteListener)方法来对请求进行处理,直到请求被处理完或者阻塞I/O,那么它将返回(没有阻塞),如果它将阻塞I/O,那么这个线程会要求I/O系统提供一个I/O可以开始的事件,并返回,当这个事件被触发的时候,在HttpClient线程池中的线程将返回来继续处理请求。
响应会在可以有字节进行读的这一条件触发下执行,响应会一直执行知道响应完全执行完成或者将要堵塞I/O。如果它将堵塞I/O,那么线程会要求I/O系统提供一个I/O可以使用的触发事件,然后线程返回。当这个事件被触发的时候,在HttpClient线程池中的线程将返回来继续处理响应。
22.3 cookies支持
Jetty HTTP客户端很容易支持cookies。HttpClient 实例将从HTTP响应中接收cookies并把它们存在java.net.CookieStore中,这个class是JDK的一个类。当有新的请求时,如果有匹配的cookies(简单来说,cookies不能过期并要匹配请求的路径),那么cookies将会被添加到请求中。
应用程序可以以编程的方式访问cookies并进行设置:
应用程序也可以使用编程的方式来设置cookies是否它们将从一个响应中返回:
cookies可以被添加到指定的请求中:
22.4 证书支持
Jetty的客户端程序支持由 RFC 7235定义的 “Basic” 和"Digest"两种身份验证机制。
你可以在http客户端实例中配置身份验证如下:
URI uri = new URI(“http://domain.com/secure”);
String realm = “MyRealm”;
String user = “username”;
String pass = “password”
AuthenticationStore auth = httpClient.getAuthenticationStore();
auth.addAuthentication(new BasicAuthentication(uri, realm, user, pass));
ContentResponse response = httpClient
.newRequest(uri)
.send()
.get(5, TimeUnit.SECONDS);
Jetty的http客户端会自动发送匹配的验证信息到服务器进行身份验证,如果验证成功后,那么将会把结果进行缓存,以后相同的域名或匹配的URI将不会再校验。
一个成功校验的HTTP会话如下:
一个成功校验的HTTP会话如下:
当应用程序接收到401状态码时,不会响应这个事件,它将会在HttpClient 内部进行处理,会产生一个简单的携带校验信息头的请求到原地址,然后传递带有200状态码的响应到应用程序。
httpClient.getAuthenticationStore().clearAuthenticationResults();
认证有可能会被提前,避免往返服务时间的资源的消耗:
AuthenticationStore auth = httpClient.getAuthenticationStore();
URI uri = URI.create(“http://domain.com/secure”);
auth.addAuthenticationResult(new BasicAuthentication.BasicResult(uri, “username”, “password”));
在这种方式中,原始请求会有HttpClient 携带一个验证的头信息,并且服务端应该返回200,这种方式比返回401要更有挑战性(因为要保证验证信息的准确性)。
Jetty的http客户端支持以代理的方式来访问目标地址。
有两种简单的方式来使用代理:一种是HTTP代理(由org.eclipse.jetty.client.HttpProxy类提供),另一种是SOCKS 4代理(由org.eclipse.jetty.client.Socks4Proxy类提供),还可以自己写一个roxyConfiguration.Proxy.的子类来实现代理。
ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
HttpProxy proxy = new HttpProxy(“proxyHost”, proxyPort);
// 不使用代理访问 localhost:8080
proxy.getExcludedAddresses().add(“localhost:8080”);
// 添加新的代理
proxyConfig.getProxies().add(proxy);
ContentResponse response = httpClient.GET(uri);
你可以指定代理的地址和端口,也可以有选择的指定某些地址不是用代理,并将代理配置添加到ProxyConfiguration 实例中。
如果以这种方式,httpclient建立请求到http代理(纯文本请求)或者建立一个隧道连接通过http连接(为了加密HTTPS的请求)。
代理认证支持:
Jetty的http客户端支持代理身份认证,同样的它也支持服务端身份认证。
URI proxyURI = new URI(“http://proxy.net:8080”);
URI serverURI = new URI(“http://domain.com/secure”);
AuthenticationStore auth = httpClient.getAuthenticationStore();
// 代理认证.
auth.addAuthentication(new BasicAuthentication(proxyURI, “ProxyRealm”, “proxyUser”, “proxyPass”));
// 服务端认证
auth.addAuthentication(new DigestAuthentication(serverURI, “ServerRealm”, “serverUser”, “serverPass”));
// 代理配置
ProxyConfiguration proxyConfig = httpClient.getProxyConfiguration();
HttpProxy proxy = new HttpProxy(“proxy.net”, 8080);
proxyConfig.getProxies().add(proxy);
ContentResponse response = httpClient.newRequest(serverURI)
.send()
.get(5, TimeUnit.SECONDS);
HTTP回话认账且代理也成功认证的回话过程如下:
Application HttpClient Proxy Server
| | | |
|— GET -->|------------- GET ------------->| |
| | | |
| |<----- 407 + Proxy-Authn -------| |
| | | |
| |------ GET + Proxy-Authz ------>| |
| | | |
| | |---------- GET --------->|
| | | |
| | |<— 401 + WWW-Authn ----|
| | | |
| |<------ 401 + WWW-Authn --------| |
| | | |
| |-- GET + Proxy-Authz + Authz -->| |
| | | |
| | |------ GET + Authz ----->|
| | | |
应用程序不会接收到407或401状态码因为处理全部在httpclient内部完成。
同样的验证,代理和服务端的验证可能被避免,特别当407和401循环返回时。
22.6 可选择式传输
22.6.1 HTTP/1.1 传输协议
HttpClient client = new HttpClient();
client.start();
如果你想定制HTTP/1.1协议,你可以配置用如下的方式配置HttpClient :
int selectors = 1;
HttpClientTransportOverHTTP transport = new HttpClientTransportOverHTTP(selectors);
HttpClient client = new HttpClient(transport, null);
client.start();
22.6.2 HTTP/2 传输协议
HTTP/2可以用如下的方式进行配置:
HTTP2Client是低级别的客户端,它提供了一个API基于HTTP / 2,像session,strean和frames特定于HTTP / 2。HttpClientTransportOverHTTP2 使用HTTP2Client 来格式高级语义的HTTP请求(“GET resource /index.html”)。
22.6.3 FastCGI 传输协议
1.链接: 参考资料.