Spring框架学习[Spring HTTP调用器实现远程调用](五)

2014-11-24 03:00:37 · 作者: · 浏览: 16
ld not access HTTP invoker remote service at [" + getServiceUrl() + "]", ex); } } }

通过上面对HttpInvokerClientInterceptor拦截器的源码分析,我们可以看出,拦截器将客户端对远程调用的HTTP请求封装成了MethodInvocation对象,拦截器的在调用远程调用的代理对象时,又将方法调用封装成了RemoteInvocation远程调用,RemoteInvocation数据对象中封装了调用的具体信息,如方法名、方法参数以及参数类型等。

真正执行远程调用的是HTTP调用请求执行器SimpleHttpInvokerRequestExecutor,下面我们继续分析SimpleHttpInvokerRequestExecutor远程调用的具体过程。

5.SimpleHttpInvokerRequestExecutor远程调用:

SimpleHttpInvokerRequestExecutor封装了基于HTTP协议的远程调用过程,具体源码如下:

[java] view plaincopyprint
  1. public class SimpleHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor { //HTTP调用请求执行器真正进行远程调用的方法,该方法有其父类//AbstractHttpInvokerRequestExecutor的executeRequest方法调用
  2. protected RemoteInvocationResult doExecuteRequest( HttpInvokerClientConfiguration config, ByteArrayOutputStream baos)
  3. throws IOException, ClassNotFoundException { //打开一个标准的J2SE HttpURLConnection
  4. HttpURLConnection con = openConnection(config); //准备连接
  5. prepareConnection(con, baos.size()); //远程调用被封装成了RemoteInvocation对象,它通过序列化被写到对应的//HttpURLConnection中
  6. writeRequestBody(config, con, baos); //获取远程调用的结果,校验返回的结果
  7. validateResponse(config, con); InputStream responseBody = readResponseBody(config, con);
  8. //将远程调用结果转换成RemoteInvocationResult返回 return readRemoteInvocationResult(responseBody, config.getCodebaseUrl());
  9. } //打开一个HttpURLConnection
  10. protected HttpURLConnection openConnection(HttpInvokerClientConfiguration config) throws IOException { //getServiceUrl()方法获取配置的远程调用URL,打开一个URL连接
  11. URLConnection con = new URL(config.getServiceUrl()).openConnection(); if (!(con instanceof HttpURLConnection)) {
  12. throw new IOException("Service URL [" + config.getServiceUrl() + "] is not an HTTP URL"); }
  13. return (HttpURLConnection) con; }
  14. //准备HTTP请求连接 protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException {
  15. con.setDoOutput(true); //HTTP调用器只支持POST请求方法
  16. con.setRequestMethod(HTTP_METHOD_POST); //设置HTTP请求头内容类型,设置为:application/x-java-serialized-object
  17. con.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, getContentType()); //设置HTTP请求头内容长度
  18. con.setRequestProperty(HTTP_HEADER_CONTENT_LENGTH, Integer.toString(contentLength)); LocaleContext locale = LocaleContextHolder.getLocaleContext();
  19. //设置HTTP请求的Locale if (locale != null) {
  20. con.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale.getLocale())); }
  21. //设置HTTP请求压缩方式 if (isAcceptGzipEncoding()) {
  22. con.setRequestProperty(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP); }
  23. } //把序列化对象输出到HTTP请求体中
  24. protected void writeRequestBody( HttpInvokerClientConfiguration config, HttpURLConnection con, ByteArrayOutputStream baos)
  25. throws IOException { baos.writeTo(con.getOutputStream());
  26. } //校验远程调用的HTTP响应
  27. protected void validateResponse(HttpInvokerClientConfiguration config, HttpURLConnection con) throws IOException {
  28. //如果HTTP响应状态码大于等于300,则证明调用发生错误 if (con.getResponseCode() >= 300) {
  29. throw new IOException( "Did not receive successful HTTP response: status code = " + con.getResponseCode() +
  30. ", status message = [" + con.getResponseMessage() + "]"); }
  31. } //提取远程调用结果的HTTP响应信息
  32. protected InputStream readResponseBody(HttpInvokerClientConfiguration config, HttpURLConnection con) throws IOException {
  33. //如果响应信息是