`

Spring HTTP invoker

 
阅读更多

具体使用请参考,这里主要看一下源码如何实现,以及和其他rpc框架的区别。

源码:

服务端配置:在spring-web包的org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter,该类继承了RemoteExporter,它内部两个属性service和serviceInterface,分别是远程服务接口和该服务的实现类,它主要提供HTTP协议封装和java对象序列化功能。

Spring的HttpInvokerServiceExporter(继承了HttpRequestHandler接口,可被适配器适配为HTTP请求处理器)是与Spring的MVC结合在一起的,它本质上是Spring MVC的一个Controller(所以要另外定义一个SimpleUrlHandlerMapping进行url映射),客户端发来的远程调用HTTP请求有Spring MVC的中央控制器DispatcherServlet转发到指定URL的HttpInvokerServiceExporter上。

<beans>
	<bean id="userService" class="com.service.impl.UserServiceImpl" />
	<!-- 基于Url映射方式,这个配置,就是把userService接口,提供给远程调用 -->
	<bean id="httpService"  class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
            <property name="service" ref="userService"/>
            <property name="serviceInterface" value="com.service.UserService"/>
        </bean>
    <bean
        class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
         <property name="mappings">
            <props>
                  <prop key="/test">httpService</prop>
            </props>
        </property>
    </bean>

客户端配置:在通过从工厂的getbean("httpTestService")方式,通过接口调用。

	<bean id="httpTestService"
	class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
		<property name="serviceUrl">
			<value>http://localhost:8080/SpringHttp_Server/test</value>
		</property>
		<!-- 在客户端定义,或者抽出来当做公用定义接口 -->
		<property name="serviceInterface">
			<value>com.service.UserService</value>
		</property>
	</bean>

  

 

 

1、在调用时,会通过HttpInvokerProxyFactoryBean作为一个ioc容器,对远程客户端封装。当通过getObject方法向Spring IoC容器索取远程调用对象时,触发afterPropertiesSet回调方法,创建远程调用的代理对象,最后将该远程调用代理对象返回。在创建远程调用代理对象时,使用其父类HttpInvokerClientInterceptor作为远程调用代理对象的拦截器,该拦截器将拦截对代理对象的方法调用。下面我们分析HttpInvokerClientInterceptor代理拦截器对代理对象的方法拦截处理。

2、当客户端通过HTTP请求调用远程调用代理的方法时,将会触发HttpInvokerClientInterceptor拦截器的invoke方法对当前的请求进行封装处理,将客户端的java对象序列化传输到服务器端,在远程服务器端执行完请求之后,又将处理结果java对象序列化返回给客户端。

3、拦截器将客户端对远程调用的HTTP请求封装成了MethodInvocation对象,拦截器的在调用远程调用的代理对象时,又将方法调用封装成了RemoteInvocation远程调用,RemoteInvocation数据对象中封装了调用的具体信息,如方法名、方法参数以及参数类型等。

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

4、SimpleHttpInvokerRequestExecutor封装了基于HTTP协议的远程调用过程,HTTP调用请求执行器的处理逻辑是:首先,打开指定URL的HTTP连接,设置连接属性。其次,将封装请求的RemoteInvocation对象序列化到请求体中,请HTTP请求发送到服务器端。最后,从服务器端的HTTP响应中读取输入流,并将响应结果转换成RemoteInvocationResult。

将远程调用的HTTP响应转换为RemoteInvocationResult是由AbstractHttpInvokerRequestExecutor的readRemoteInvocationResult方法实现,下面我们将分析其将HTTP响应结果转换成RemoteInvocationResult的实现。

public class SimpleHttpInvokerRequestExecutor extends AbstractHttpInvokerRequestExecutor {
//HTTP调用请求执行器真正进行远程调用的方法,该方法有其父类//AbstractHttpInvokerRequestExecutor的executeRequest方法调用
	protected RemoteInvocationResult doExecuteRequest(
			HttpInvokerClientConfiguration config, ByteArrayOutputStream baos)
			throws IOException, ClassNotFoundException {
		//打开一个标准的J2SE HttpURLConnection
		HttpURLConnection con = openConnection(config);
		//准备连接
		prepareConnection(con, baos.size());
//远程调用被封装成了RemoteInvocation对象,它通过序列化被写到对应的//HttpURLConnection中
		writeRequestBody(config, con, baos);
		//获取远程调用的结果,校验返回的结果
		validateResponse(config, con);
		InputStream responseBody = readResponseBody(config, con);
		//将远程调用结果转换成RemoteInvocationResult返回
		return readRemoteInvocationResult(responseBody, config.getCodebaseUrl());
	}
//打开一个HttpURLConnection
	protected HttpURLConnection openConnection(HttpInvokerClientConfiguration config) throws IOException {
		//getServiceUrl()方法获取配置的远程调用URL,打开一个URL连接
		URLConnection con = new URL(config.getServiceUrl()).openConnection();
		if (!(con instanceof HttpURLConnection)) {
			throw new IOException("Service URL [" + config.getServiceUrl() + "] is not an HTTP URL");
		}
		return (HttpURLConnection) con;
	}
	//准备HTTP请求连接
	protected void prepareConnection(HttpURLConnection con, int contentLength) throws IOException {
		con.setDoOutput(true);
		//HTTP调用器只支持POST请求方法
		con.setRequestMethod(HTTP_METHOD_POST);
	//设置HTTP请求头内容类型,设置为:application/x-java-serialized-object
		con.setRequestProperty(HTTP_HEADER_CONTENT_TYPE, getContentType());
		//设置HTTP请求头内容长度
		con.setRequestProperty(HTTP_HEADER_CONTENT_LENGTH, Integer.toString(contentLength));
		LocaleContext locale = LocaleContextHolder.getLocaleContext();
		//设置HTTP请求的Locale
		if (locale != null) {
			con.setRequestProperty(HTTP_HEADER_ACCEPT_LANGUAGE, StringUtils.toLanguageTag(locale.getLocale()));
		}
		//设置HTTP请求压缩方式
		if (isAcceptGzipEncoding()) {
			con.setRequestProperty(HTTP_HEADER_ACCEPT_ENCODING, ENCODING_GZIP);
		}
	}
//把序列化对象输出到HTTP请求体中
	protected void writeRequestBody(
			HttpInvokerClientConfiguration config, HttpURLConnection con, ByteArrayOutputStream baos)
			throws IOException {
		baos.writeTo(con.getOutputStream());
	}
//校验远程调用的HTTP响应
	protected void validateResponse(HttpInvokerClientConfiguration config, HttpURLConnection con)
			throws IOException {
		//如果HTTP响应状态码大于等于300,则证明调用发生错误
		if (con.getResponseCode() >= 300) {
			throw new IOException(
					"Did not receive successful HTTP response: status code = " + con.getResponseCode() +
					", status message = [" + con.getResponseMessage() + "]");
		}
	}
	//提取远程调用结果的HTTP响应信息
	protected InputStream readResponseBody(HttpInvokerClientConfiguration config, HttpURLConnection con)
			throws IOException {
		//如果响应信息是Gzip压缩的,则需要先解压
		if (isGzipResponse(con)) {
			return new GZIPInputStream(con.getInputStream());
		}
		//正常的HTTP响应
		else {
			return con.getInputStream();
		}
	}
	//是否是Gzip格式压缩
	protected boolean isGzipResponse(HttpURLConnection con) {
		//获取HTTP响应头信息中的压缩方式
		String encodingHeader = con.getHeaderField(HTTP_HEADER_CONTENT_ENCODING);
		return (encodingHeader != null && encodingHeader.toLowerCase().indexOf(ENCODING_GZIP) != -1);
	}
}

 5、AbstractHttpInvokerRequestExecutor中处理远程调用结果,并HTTP响应转换成RemoteInvocationResult的主要方法如下:

//从HTTP响应中读取远程调用结果入口方法
protected RemoteInvocationResult readRemoteInvocationResult(InputStream is, String codebaseUrl)
			throws IOException, ClassNotFoundException {
		//根据给定的输入流和类创建对象输入流
		ObjectInputStream ois = createObjectInputStream(decorateInputStream(is), codebaseUrl);
		try {
			//从对象输入流中读取远程调用结果
			return doReadRemoteInvocationResult(ois);
		}
		finally {
			ois.close();
		}
	}
//从对象输入流中读取远程调用结果
protected RemoteInvocationResult doReadRemoteInvocationResult(ObjectInputStream ois)
			throws IOException, ClassNotFoundException {
		//获取对象输入流中的对象
		Object obj = ois.readObject();
		if (!(obj instanceof RemoteInvocationResult)) {
			throw new RemoteException("Deserialized object needs to be assignable to type [" +
					RemoteInvocationResult.class.getName() + "]: " + obj);
		}
		//将获取到的对象封装为RemoteInvocationResult
		return (RemoteInvocationResult) obj;
	}

 

 

分享到:
评论

相关推荐

    Spring HttpInvoker的封装

    **Spring HttpInvoker的封装** 在Java企业级应用开发中,Spring框架因其强大的功能和灵活性而被广泛应用。HttpInvoker是Spring框架的一部分,它提供了一种基于HTTP协议的远程调用机制,使得不同网络环境中的Java...

    Spring HttpInvoker

    Spring HttpInvoker,是一套基于Maven+Spring+SpringMVC+MyBatis框架,还包含了Invoker的客户端及服务器端的demo实例

    Spring HttpInvoker介绍

    公司内部讲义,比较了SOA,RMI和Spring HttpInvoker。并介绍了Spring HttpInvoker的基本使用方法。

    Spring HttpInvoker 初学实例

    org.springframework.remoting.httpinvoker最基本的实现例子,这是3个eclipse的JavaEE工程,全部导入即可,能运行。 初学可以轻松了解Spring HttpInvoker 的结构和使用。

    spring httpInvoker示例

    &lt;bean id="serviceExporter" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"&gt; ``` 这里,`ServiceImpl`是你实现`ServiceInterface`的具体类,`HttpInvokerServiceExporter`将...

    使用httpInvoker提供远程服务

    在分布式系统中,远程服务调用是常见的需求,Spring框架提供了多种远程服务支持,其中包括HttpInvoker。HttpInvoker是Spring框架的一部分,它允许开发者使用HTTP协议进行远程方法调用,而不需要额外的类库。与...

    Spring 实现远程访问详解——httpinvoker

    Spring httpInvoker使用标准java序列化机制,通过Http暴露业务服务。如果你的参数和返回值是比较复杂的,通过httpInvoker有巨大的优势。 1. 远程访问流程 1) 服务端定义服务接口 2) 服务端实现服务接口 3) 暴露服务...

    springboot-httpinvoker-demo.zip

    同时,使用`@HttpInvokerService`注解暴露该服务,指定远程访问的URL。 3. 配置服务消费方:在服务消费方,使用`@HttpInvokerProxyFactoryBean`来创建服务代理,指定服务的URL和接口类型。这样,消费方就可以像调用...

    Spring的HttpInvoker使用示例 (可下载源码)

    NULL 博文链接:https://lggege.iteye.com/blog/369151

    spring-httpinvoker-demo

    Spring HTTP Invoker是spring框架中的一个远程调用模型,执行基于HTTP的远程调用,也就是说,可以通过防火墙,并使用java的序列化机制在网络间传递对象。客户端可以很轻松的像调用本地对象一样调用远程服务器上的...

    Java Spring2.5 Remote Invoke HTTP Invoker

    Java Spring 2.5 Remote Invoke HTTP Invoker 是一个基于HTTP协议的远程调用框架,它允许Spring应用通过HTTP协议来调用远程服务。这个技术在分布式系统中非常有用,因为它可以轻松地跨越网络边界,实现服务间的通信...

    http invoker 做post测试

    3. **配置HTTP Invoker**:在服务端配置Spring,启用HTTP Invoker的支持,将接口绑定到特定的URL路径上,以便客户端可以访问。 4. **客户端构建请求**:在客户端,我们需要创建一个HTTP Invoker的代理对象,该对象...

    Thrift转SpringHttpInvoker

    在IT行业中,Thrift和Spring Http Invoker是两种常见的服务通信框架。Thrift是由Facebook开源的一种高性能、跨语言的服务框架,而Spring Http Invoker是Spring框架的一部分,用于实现基于HTTP的远程方法调用。这篇...

    spring远程调用

    在分布式系统中,远程调用是一个常见需求,Spring为此提供了一种轻量级的解决方案——HttpInvoker。本文将详细讲解如何利用Spring的HttpInvoker进行远程方法调用。 首先,我们需要理解什么是Spring HttpInvoker。...

    Http Invoker

    **Http Invoker:接口测试工具详解** Http Invoker是一款用于接口测试的工具,它允许开发者对Web服务进行调用和测试,验证API的功能和性能。虽然在某些用户看来,Http Invoker可能并不是最易用或者功能最全面的工具...

    http接口相关介绍

    Spring HTTP Invoker是Spring框架提供的一个远程调用模型,它允许通过HTTP进行远程调用,这意味着可以在防火墙环境下实现服务间的通信。与传统的远程过程调用(RPC)不同,Spring HTTP Invoker简化了客户端和服务端...

    Java Spring1.2 Remote Invoke HTTP Invoker

    Java Spring 1.2 远程调用HTTP Invoker是一个基于HTTP协议的远程服务调用框架,它是Spring框架的一部分,允许应用通过HTTP协议进行服务间的通信。这种通信方式相对于RMI(Remote Method Invocation)等其他远程调用...

    基于Spring的HttpInvoker实现改写egova_invoker.zip

    基于Spring的HttpInvoker实现改写服务器端调用: HttpInvoker.invoker 方法,设置InvokerProcess处理客户端调用: ProxyFactory.proxy 方法,生成接口的代理对象,直接调用方法客户端和服务器端的接口和实体类要...

    用Http Invoker实现RCP客户端与后台的交互

    `Http Invoker`是Spring框架提供的一种基于HTTP协议的RPC实现,主要用于Java应用程序之间进行服务调用。本文将深入探讨如何使用Http Invoker实现RCP客户端与后台的交互,以及相关知识点。 1. **Http Invoker的基本...

    Hessian 、 HttpInvoker 、 XFire 、 Axis

    HttpInvoker主要面向Spring应用程序,易于集成,但相比Hessian,其数据传输效率较低,因为HTTP协议本身较重,且Java序列化也相对消耗资源。 XFire(后来被Apache CXF吸收)是一款基于XML的Web服务框架,它支持多种...

Global site tag (gtag.js) - Google Analytics