spring boot rpc框架支不支持rpc调用

22275人阅读
微服务及云计算学习总结(19)
Spring Cloud介绍
Spring Cloud是一个基于Spring Boot实现的云应用开发工具,它为基于JVM的云应用开发中的配置管理、服务发现、断路器、智能路由、微代理、控制总线、全局锁、决策竞选、分布式会话和集群状态管理等操作提供了一种简单的开发方式。
Spring Cloud与Dubbo对比
提到Dubbo,我想顺便提下ESB,目前央视新华社也在用ESB来做任务编排,这里先比较下Dubbo和ESB:
ESB(企业数据总线),一般采用集中式转发请求,适合大量异构系统集成,侧重任务的编排,性能问题可通过异构的方式来进行规避,无法支持特别大的并发。Dubbo(服务注册管理),采用的是分布式调用,注册中心只记录地址信息,然后直连调用,适合并发及压力比较大的情况;其侧重服务的治理,将各个服务颗粒化,各个子业务系统在程序逻辑上完成业务的编排。
回归主题,Spring Cloud和Dubbo又有什么不同那,首先,我们看下有什么相同之处,它们两都具备分布式服务治理相关的功能,都能够提供服务注册、发现、路由、负载均衡等。说到这,Dubbo的功能好像也就这么多了,但是Spring Cloud是提供了一整套企业级分布式云应用的完美解决方案,能够结合Spring Boot,Docker实现快速开发的目的,所以说Dubbo只有Spring Cloud的一部分RPC功能,而且也谈不上谁好谁坏。不过,Dubbo项目现已停止了更新,淘宝内部由hsf替代dubbo,我想这会有更多人倾向Spring
从开发角度上说,Dubbo常与Spring、zookeeper结合,而且实现只是通过xml来配置服务地址、名称、端口,代码的侵入性是很小的,相对Spring Cloud,它的实现需要类注解等,多少具有一定侵入性。
Spring Cloud子项目
Spring Cloud包含了多个子项目(针对分布式系统中涉及的多个不同开源产品),之前在第一章节也介绍这些,比如:Spring Cloud Config、Spring Cloud Netflix、Spring Cloud CloudFoundry、Spring Cloud AWS、Spring Cloud Security、Spring Cloud Commons、Spring Cloud Zookeeper、Spring Cloud CLI等项目,可以跳至(一)看下。
Spring Cloud提供了Config Server,它有在分布式系统开发中做外部配置的功能,通过Config Server我们可以集中存储所有应用的配置文件。Config Server支持Git或者在文件系统中放置配置文件(GitLab),通常我们使用不同格式来区分不同应用的不同配置文件。云计算环境下,习惯上使用YAML配置,而且一般配置文件的位置都放在类路径下的config目录下,配置文件规则:应用名+profile.yml:
/{application}/{profile}[/{label}]
/{application}-{profile}.yml
/{label}/{application}-{profile}.yml
/{application}-{profile}.properties
/{label}/{application}-{profile}.propertiesSpring Cloud提供了注解@EnableConfigServer来启动配置服务。
Spring Cloud通过Netflix OSS的Eureka来实现服务发现,服务发现的主要目的是为了让每个服务之间可以互相通信。Eureka Server为微服务的注册中心。谈到Spring Cloud Netflix,它是Spring Cloud的子项目之一,主要提供的模块包括:服务发现(Eureka),断路器(Hystrix),智能路有(Zuul),客户端负载均衡(Ribbon)等。
Spring Cloud使用注解的方式提供了Eureka服务端(@EnableEurekaServer)和客户端(@EnableEurekaClient)。
路由网关的主要目的是为了让所有的微服务对外只有一个接口,我们只需访问一个网关地址,即可由网关将所有的请求代理到不同的服务中。Spring Cloud是通过Zuul来实现的,支持自动路由映射到在Eureka Server上注册的服务。Spring Cloud提供了注解@EnableZuulProxy来启用路由代理。
Spring Cloud提供了Ribbon和Feign作为客户端的负载均衡。在Spring Cloud下,使用Ribbon直接注入一个RestTemplate对象即可,此RestTemplate已做好负载均衡的配置;而使用Feign只需定义个注解,有@FeignClient注解的接口,然后使用@RequestMapping注解在方法上映射远程的REST服务,此方法也是做好了负载均衡配置。
断路器(Circuit Breaker)主要是为了解决当某个方法调用失败的时候,调用后备方法来替代失败的方法,已达到容错/阻止级联错误的功能。Spring Cloud使用@EnableCircuitBreaker来启用断路器支持,使用@HystrixCommand的fallbackMethod来指定后备方法。(@HystrixCommand(fallbackMethod=&fallbackOper&))
Spring Cloud还提供了一个控制台来监控断路器的运行情况,通过@EnableHystrixDashboard注解开启。
Spring Cloud依赖库
这里我会罗列下常用的一些依赖包,为了更好理解每个依赖所负责的区域,我还是用一张和之前类似的图来展示各块的功能:
常用依赖包如下:
spring-cloud-starter-parent 具备spring-boot-starter-parent同样功能并附加Spring Cloud的依赖
spring-cloud-starter-config 默认的配置服务依赖,快速自动引入服务的方式,端口8888
spring-cloud-config-server/client 用户自定义配置服务的服务端/客户端依赖
spring-cloud-starter-eureka-server 服务发现的Eureka Server依赖
spring-cloud-starter-eureka 服务发现的Eureka客户端依赖
spring-cloud-starter-hystrix/zuul/feign/ribbon 断路器(Hystrix),智能路有(Zuul),客户端负载均衡(Ribbon)的依赖
angular-ui-router 页面分发路由依赖
这里所有的总结只是停留在对Spring Cloud的理解上,我推荐去http://projects.spring.io/spring-cloud/官网导读多实践下项目,了解下各个模块的服务消息通信方式等,大概就是这样。
如果你对Spring Cloud感兴趣,想了解Spring Boot快速开发,以及使用JHipster生成构建Spring Boot + AngularJS的应用代码,欢迎加QQ群:,里面有很多大牛指导,我也在学习中。另外,群里我们在组织翻译GitHub上JHipster的官方文档,如果感兴趣,可以进来一块为开源做贡献。
关于JHipster扩展
JHipster -&&关于SpringBoot,AngularJS及Spring生态融合的技术栈, 是SpringBoot的最佳实践,是SpringCloud对Netflix技术栈的最佳实践,是J2EE-Cloud微服务的最佳实践,是Docker,Kubernetes和AngularJS1/2的最佳实践,是全栈式开发,敏捷开发最理想的工具。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:254070次
积分:4114
积分:4114
排名:第6472名
原创:174篇
转载:27篇
评论:31条
文章:14篇
阅读:84640
(2)(4)(1)(4)(4)(13)(7)(4)(6)(1)(1)(2)(1)(1)(5)(3)(2)(3)(5)(20)(3)(27)(23)(23)(11)(15)(1)(9)(3)(1)(1)Using Spring Boot together with gRPC and Protobuf - Stack Overflow
Join the Stack Overflow Community
Stack Overflow is a community of 7.0 million programmers, just like you, helping each other.
J it only takes a minute:
Anyone having any examples or thoughts using gRPC together with Spring Boot?
If it's still relevant for you, I've created gRPC spring-boot-starter .
grpc-spring-boot-starter auto-configures and run the embedded gRPC server with @GRpcService-enabled beans.
The simplest example :
@GRpcService(grpcServiceOuterClass = GreeterGrpc.class)
public static class
GreeterService implements GreeterGrpc.Greeter{
@Override public void
sayHello(GreeterOuterClass.HelloRequest request, StreamObserver&GreeterOuterClass.HelloReply& responseObserver) {
// omitted
There is also example of how to integrate the starter with Eureka in project's Readme file.
Starting from , then
take a look at
and related
That is some support for proto3 is coming in Spring 5. As it is under development one is encouraged to vote and raise what is important for their project.
17k25102193
@GrpcService(GreeterGrpc.class)
public class GrpcServerService extends GreeterGrpc.GreeterImplBase {
public void sayHello(HelloRequest req, StreamObserver&HelloReply& responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello =============& " + req.getName()).build();
responseObserver.onNext(reply);
responseObserver.onCompleted();
@GrpcClient("gRPC server name")
private Channel serverC
GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(serverChannel);
HelloReply response = stub.sayHello(HelloRequest.newBuilder().setName(name).build());
In here I use gRpc and eureka to communication. This project based on Spring-boot
additionally you canuse register as consul also. full example in this repo
this maven dependency help to gRpc
&dependency&
&groupId&io.grpc&/groupId&
&artifactId&grpc-stub&/artifactId&
&version&1.0.1&/version&
&/dependency&
&dependency&
&groupId&io.grpc&/groupId&
&artifactId&grpc-protobuf&/artifactId&
&version&1.0.1&/version&
&/dependency&
&dependency&
&groupId&io.grpc&/groupId&
&artifactId&grpc-netty&/artifactId&
&version&1.0.1&/version&
&/dependency&
and need plugin show in below
&groupId&org.xolstice.maven.plugins&/groupId&
&artifactId&protobuf-maven-plugin&/artifactId&
&version&0.5.0&/version&
&configuration&
&!-- The version of protoc must match protobuf-java. If you don't depend
on protobuf-java directly, you will be transitively depending on the protobuf-java
version that grpc depends on. --&
&protocArtifact&com.google.protobuf:protoc:3.0.2:exe:${os.detected.classifier}&/protocArtifact&
&pluginId&grpc-java&/pluginId&
&pluginArtifact&io.grpc:protoc-gen-grpc-java:1.0.1:exe:${os.detected.classifier}&/pluginArtifact&
&/configuration&
&executions&
&execution&
&goal&compile&/goal&
&goal&compile-custom&/goal&
&/execution&
&/executions&
Your Answer
Sign up or
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Post as a guest
By posting your answer, you agree to the
Not the answer you're looking for?
Browse other questions tagged
rev .25701
Stack Overflow works best with JavaScript enabled使用JSONRPC 2.0规范解决多语言RPC交互的方案
最近做的一个项目比较大,分了许多模块,但是由于不同的开源技术使用的语言不同,不同模块使用的语言可能不同,但基本上是使用和实现的。当各模块需要进行交互的时候,问题就出现了,模块不能像Jar包或者Python模块那样引入,Java有它的JVM,Python有它的解释器,单机调用只能是用native方案。但native明显与os有关,换个环境又不知道会有什么兼容问题出现。
具体问题还是要具体分析,考虑的因素有很多。在该实际项目中,关于效率需要考虑的因素有:
1. 单输入文本的处理时间
2. 网络传输时间
3. 机器的配置
经过测试,单输入文本处理时间&&网络传输时间,而且没有很高配置的机器,如果用native方法,需要跑几个模块,机器可能负荷不了,所以考虑构建成分布式,以提高效率。
设计分布式需要考虑机器间如何交互。最简单的又通用的就是使用互联网协议,如http协议,由于它是个应用层协议,所以效率肯定不会高,但为了简单起见,而且在网络传输效率基本可以忽略不计的情况下,我们还是选用了这个应用层协议。
http协议只是作为通信协议,但是数据传输的格式还是要规范的,传统的有xml和一些序列化方案,近年流行更加轻量级和通用的json格式,它被广泛用于web数据传输。本文选用的就是json格式。
于是朝着这个方向去调研,找到了json-rpc 2.0规范。
JSON-RPC 2.0简介
JSON-RPC is a stateless, light-weight remote procedure call (RPC) protocol. Primarily this specification defines several data structures and the rules around their processing. It is transport agnostic in that the concepts can be used within the same process, over sockets, over http, or in many various message passing environments. It uses JSON (RFC 4627) as data format.
JSON-RPC是一个无状态的、轻量级的远程过程调用(RPC)协议。本规范主要围绕它的处理方式定义了几个数据结构和规则。这个概念可用于在同一进程中、套接字或HTTP之间、或其他很多消息传递的环境中传输数据。它使用JSON (RFC 4627)作为数据格式。
好了,此处关键词:JSON、HTTP。
既然是规范,应当被很多人应用,而且有详尽文档,就不需要自己傻乎乎地去写详细的交互文档。
下面介绍一下规范中定义的对象必须有的成员:
A String specifying the version of the JSON-RPC protocol. MUST be exactly &2.0&.
A String containing the name of the method to be invoked. Method names that begin with the word rpc followed by a period character (U+002E or ASCII 46) are reserved for rpc-internal methods and extensions and MUST NOT be used for anything else.
A Structured value that holds the parameter values to be used during the invocation of the method. This member MAY be omitted.
An identifier established by the Client that MUST contain a String, Number, or NULL value if included. If it is not included it is assumed to be a notification. The value SHOULD normally not be Null [1] and Numbers SHOULD NOT contain fractional parts [2]
The Server MUST reply with the same value in the Response object if included. This member is used to correlate the context between the two objects.
当发起rpc调用时,服务器必须回复一个响应,通知除外。响应被表示成一个单一的对象,包含下列的成员:
指定JSON-RPC版本的字符串,它必须是&2.0&。
当调用成功时,该成员是必须的。
如果调用方法出现错误时,必须不包含该成员。
该成员的值由服务器上调用的方法决定。
当调用发生错误时,该成员是必须的。
在调用期间如果没有错误产生,必须不包含该成员。
该成员的值必须是一个5.1节定义的对象。
该成员是必须的。
它的值必须与请求对象中的id成员的值相同。
如果检查请求对象中的id时发生错误(如:转换错误或无效的请求),它必须为Null。
必须包含result或error成员,但是两个成员都必须不能同时包含。
Java Server
既然是使用http协议,那就需要一个web容器是装载。(不装载也可以,自己去实现一个http容器咯,或者去找开源的,其实也挺大的)
Java有一段时间没用了,以前用Java是做web开发,用经典的Spring框架做对象管理,SpringMVC管理整个web框架,数据层框架用Hibernate或者JPA等。听说最近有个框架很火,叫Spring Boot,它能够快速地构建web应用,而且配置纯Java化,通过一个函数即可启动,像Python的Flask那样的方便,实质它默认使用的底层容器还是Tomcat,简化了我们的操作而已。
用传统的web应用构建方式的成本跟学习Spring Boot框架的成本之间衡量了一下,选择了后者,因为前者再用也是没有什么收益,后者却能体验到新框架,而且现在的框架网站上的Quick Start都很容易实现。但是提高效率的方法不应是单个单个地学习,而是联系起来学习,所以我直接去github上找java jsonrpc的项目。于是定位到了一个叫的开源项目,Star299,肯定没找错了。
直接看它的Wiki,还真有Spring Boot的Quick Start。
这里省点力,直接贴:
Configuration
To get the entire system working, you need to define the AutoJsonRpcServiceImplExporter bean in your @Configuration class:
package example.jsonrpc4j.
import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceImplE
import org.springframework.context.annotation.B
import org.springframework.context.annotation.C
@Configuration
public class ApplicationConfig {
public static AutoJsonRpcServiceImplExporter autoJsonRpcServiceImplExporter() {
AutoJsonRpcServiceImplExporter exp = new AutoJsonRpcServiceImplExporter();
//in here you can provide custom HTTP status code providers etc. eg:
//exp.setHttpStatusCodeProvider();
//exp.setErrorResolver();
Then create your service interface. My example is a simple calculator endpoint:
package example.jsonrpc4j.springboot.
import com.googlecode.jsonrpc4j.JsonRpcP
import com.googlecode.jsonrpc4j.JsonRpcS
@JsonRpcService(&/calculator&)
public interface ExampleServerAPI {
int multiplier(@JsonRpcParam(value = &a&) int a, @JsonRpcParam(value = &b&) int b);
And implement your interface like this:
package example.jsonrpc4j.springboot.
import com.googlecode.jsonrpc4j.spring.AutoJsonRpcServiceI
import org.springframework.stereotype.S
@AutoJsonRpcServiceImpl
public class ExampleServerAPIImpl implements ExampleServerAPI {
public int multiplier(int a, int b) {
return a *
curl -H &Content-Type:application/json& -d '{&id&:&1&,&jsonrpc&:&2.0&,&method&:&multiplier&,&params&:{&a&:5,&b&:6}}' http://localhost:8080/calculator
Spring Boot整合jsonrpc4j的注意事项:
1. jsonrpc的API类应该在启动Spring Boot的java类的下一级名为api的包中。
2. 更改端口需要在src/main/resource文件夹中添加application.properties文件,内容如下:
management.port: 9001
management.address: 0.0.0.0
spring.data.mongodb.host=192.168.0.2
Python Server
这里我使用模块,直接pip安装。
有点尿急,也直接贴吧:
Create your application and initialize the Flask-JSONRPC.
from flask import Flask
from flask_jsonrpc import JSONRPC
app = Flask(__name__)
jsonrpc = JSONRPC(app, '/api')
Write JSON-RPC methods.
@jsonrpc.method('App.index')
def index():
return u'Welcome to Flask JSON-RPC'
All code of example run.py.
$ python run.py
* Running on http://0.0.0.0:5000/
$ curl -i -X POST \
-H &Content-Type: application/ indent=4& \
&jsonrpc&: &2.0&,
&method&: &App.index&,
&params&: {},
}' http://localhost:5000/api
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 77
Server: Werkzeug/0.8.3 Python/2.7.3
Date: Fri, 14 Dec :56 GMT
&jsonrpc&: &2.0&,
&id&: &1&,
&result&: &Welcome to Flask JSON-RPC&
如果是Python调用它,可以
&&& from flask_jsonrpc.proxy import ServiceProxy
&&& server = ServiceProxy('http://localhost:5000/api')
&&& server.App.index()
{'jsonrpc': '2.0', 'id': '91bce374-462f-11e2-af55-f0bf97588c3b', 'result': 'Welcome to Flask JSON-RPC'}
Flask-jsonrpc有一个优点就是它有一个api管理页面:
以上我们可以看到我们已经可以通过http协议,加上一些json字符串就可以实现调用了。
在实际项目中,我们只需要实现客户端使用语言的jsonrpc 2.0规范的http调用方法即可,如上一节中的Python使用ServiceProxy对象调用。
还有一定值得注意的是,交互的对象必须要能转为json格式,否则需要自己写转json字符串的方法。
总感觉这是个笨笨的方法,是因为http协议笨重吗?
反正我觉得比native好,少侵入代码,又能形成分布式,而且有个好处就是,前端应用可以直接用js调用。
其实RPC调用就是一个将模块服务化的过程,一个模块能够向多个模块提供服务,例如可以想一些公共功能服务化,就不需要重复代码。
由于分布式知识有限,不能进行更多方法的对比,日后如果有所学习,一定会更新。
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467142',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'Spring - 几种RPC模型的使用与比较_Linux编程_Linux公社-Linux系统门户网站
你好,游客
Spring - 几种RPC模型的使用与比较
来源:Linux社区&
作者:Kavlez
Spring中,用JMS搞RPC时会用到:
org.springframework.jms.remoting.JmsInvokerServiceExporter
org.springframework.jms.remoting.JmsInvokerProxyFactoryBean
spring在实现RPC的几种方式上都提供了风格一致的支持。在这里我打算把几种RPC模型记录下来并作比较。
Hessian/Burlap
HTTP Invoker
先从最基本的RMI开始。RMI相关的API早在JDK1.1时就有了,我在这里简单描述一下RMI的原生实现(代码可以从别的地方参考)。
声明一个远程接口,接口必须继承java.rmi.Remote,方法需要抛java.rmi.RemoteException。
为远程接口提供实现,实现类需要继承UnicastRemoteObject。
或者可以使用rmi相关命令创建skelton和stub。
启动一个RMI注册表并注册。
如果是spring实现RMI,方法会简单很多。我们只需要用到两个类:
org.springframework.remoting.rmi.RmiServiceExporter
org.springframework.remoting.rmi.RmiProxyFactoryBean
我简单定义一下接口和实现类:
package pac.testcase.
public interface MyService {
public boolean inviteMeIn();
public String welcome();
package pac.testcase.ws.
import pac.testcase.ws.MyS
public class MyServiceImpl implements MyService{
public boolean inviteMeIn() {
return true;
public String welcome() {
return "Everybody is welcome!!";
简简单单,不需要继承其他任何东西,非常pojo。
下面是spring相关配置:
id="myService" class="pac.testcase.ws.impl.MyServiceImpl" /&
class="org.springframework.remoting.rmi.RmiServiceExporter"
p:service-ref="myService"
p:serviceName="welcomeService"
p:serviceInterface="pac.testcase.ws.MyService"
将我们的pojo导出为RMI服务,在这里我采用默认配置。地址在默认情况时如下:
* Set the host of the registry for the exported RMI service,
* i.e. {@code rmi://HOST:port/name}
* &p&Default is localhost.
public void setRegistryHost(String registryHost) {
this.registryHost = registryH
* Set the port of the registry for the exported RMI service,
* i.e. {@code rmi://host:PORT/name}
* &p&Default is {@code Registry.REGISTRY_PORT} (1099).
* java.rmi.registry.Registry#REGISTRY_PORT
public void setRegistryPort(int registryPort) {
this.registryPort = registryP
客户端方面使用RmiProxyFactoryBean,被代理的服务就像一个简单的bean一样:
&bean id="clientSideService" class="org.springframework.remoting.rmi.RmiProxyFactoryBean"
p:serviceUrl="rmi://localhost:1099/welcomeService"
p:serviceInterface="pac.test.RemoteService"
配置中的pac.test.RemoteService就是那个简单的bean,根据客户端的需要,在这里重新定义一下。
package pac.
public interface RemoteService {
public String welcome();
这样就可以在服务端调用了,不用做什么Naming.lookup(serviceUrl)之类的操作,远程调用变得透明。
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
RemoteService service = (RemoteService)context.getBean("clientSideService");
System.out.println(service.welcome());
RMI虽然简单高效,但使用RMI会存在一些问题,比如java序列化的版本问题或者防火墙问题(RMI不是基于HTTP的)。
Hessian / Burlap&
Hessian和Burlap,现在进Caucho的网站都几乎见不到这方面的内容了。我也不知道有没有人还会用这两个东东,虽然去年出了一个版本,但上一个版本是在2010年。刚才在群里问了一下有没有人用,结果还真有人用Hessian,他们是C#和Java做通信。Burlap性能更令人头疼,不知道还有没有人提及。虽然不知道使用情况如何,但也在这里简单记录一下,拓展一下思维。
Hessian和Burlap都是由Caucho提供的,Hessian是Resin的一部分。这两个东西就像同一件事物的两个部件,比如像这样的枪+链锯?
Hessian是binary transport protocol,但与RMI不同的是他不是java序列化对象,所以他可以和其他语言的程序通信,比如C++、C#、Python、Ruby什么的。Burlap是基于XML的,自然也可以支持很多不同的语言。当然,同样地传输内容下,XML的传输量会大一些。如果要说有什么好处的话也只有可读性了。
实在懒得添加依赖再提供原生实现,但他并不复杂。 Creating a Hessian service using Java has four steps:
Create an Java interface as the public API
Create a client using HessianProxyFactory
Create the Service implementation class
Configure the service in your servlet engine.
在这里我主要记录一下如何在spring中导出与调用Hessian service。正如上面所说,我需要把服务配置到servlet engine中;服务端和客户端都需要添加一个dependency:
&com.caucho&
正好我这边有个使用springMVC的应用,我就在这个基础上导出Hessian service。
&springServlet&
&org.springframework.web.servlet.DispatcherServlet&
&contextConfigLocation&
&/WEB-INF/spring-mvc.xml&
&springServlet&
简单写一个接口与实现:
package mon.
public interface MyHessianService {
public String justHadEnoughParties();
package mon.rpc.
import mon.rpc.MyHessianS
public class MyHessianServiceImpl implements MyHessianService {
public String justHadEnoughParties() {
return "Please save me..";
我在spring-mvc.xml中曾经做了如下配置,并在*Controller中使用了RequestMapping注解去给URL做映射。但这并不妨碍我导出Hessian service再为其映射一个URL:
base-package="pac.king.controller"
use-default-filters="false"&
type="annotation"
expression="org.springframework.stereotype.Controller" /&
id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&
name="mappings"&
/service=myHessianService
导出Hessian service:
id="myHessianServiceImpl" class="mon.rpc.impl.MyHessianServiceImpl" /&
id="myHessianService" class="org.springframework.remoting.caucho.HessianServiceExporter"
p:service-ref="myHessianServiceImpl"
p:serviceInterface="mon.rpc.MyHessianService"
现在可以调用了,我需要在客户端声明一个接口(pac.test.HessianService),再用代理去调用:
&bean id="myHessianClient" class="org.springframework.remoting.caucho.HessianProxyFactoryBean"
p:serviceUrl="http://localhost:8080/runtrain/service"
p:serviceInterface="pac.test.HessianService"
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
HessianService service = (HessianService)context.getBean("myHessianClient");
System.out.println(service.justHadEnoughParties());
console输出:
对于Burlap,几乎与Hessian的配置没什么区别;只需要把HessianServiceExporter改为BurlapServiceExporter,并将HessianProxyFactoryBean改为BurlapProxyFactoryBean即可。
RMI使用Java的序列化,而Hessian/Burlap则为了不同语言之间通信而使用私有的序列化。如果我需要基于HTTP,但我并不需要多语言支持,我只想用Java...
HttpInvoker
我应该说这是基于Http的RMI吗?虽然看起来两全其美,但也存在让人"遗憾"的地方,(事实上不怎么遗憾的说,我曾经做过没有Spring的项目,连持久层框架都是自己实现,做得越久越痛苦...)他没有所谓"原生"的实现,他是Spring的一部分,只能在Spring应用中使用。
Spring为这些RPC通信模型提供的相关类在命名上都有一致,都是:
服务端:*ServiceExporter
客户端:*ProxyFactoryBean
自然地,HttpInvoker将用到
org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter
org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean
基于HttpInvoker的服务也像Hessian那样由DispatcherServlet进行分发。鉴于很多相同的地方,我打算继续使用在上一篇中用Hessian通信的接口和实现类。
我几乎不用做任何工作,URL映射也不需要修改,我只需要将服务端的配置修改一下:
id="myHessianServiceImpl" class="mon.rpc.impl.MyHessianServiceImpl" /&
id="myHessianService" class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter"
p:service-ref="myHessianServiceImpl"
p:serviceInterface="mon.rpc.MyHessianService"
相应地,客户端也只需要修改一下class:
id="myHessianClient" class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean"
p:serviceUrl="http://localhost:8080/runtrain/service"
p:serviceInterface="pac.test.HessianService"
这样就保证了效率又解决了防火墙的问题,后来我听有人说,他们用Hessian做跨语言通信时,基于Http这个特征并不能解决防火墙的问题。不知道他们具体情况如何,似乎没说到一块儿...
看了Hessian之后突然感觉Web service这种东西好笨重啊(虽然也有一些方法可以克服部分问题)。既然有Hessian,那为什么还要用Web service这种东西呢?我突然开始怀疑起他存在的意义。搜了一下,结果都是比较RPC通信模型的效率,没有人说他们为什么还要用(都应该有存在的意义吧)...如果仅仅是效率的话都用Hessian不就得了?带着这个问题我逛了逛stackoverflow,然后我得到了下面几种答案。
多数人手中拿着锤子的时候,他们倾向于将所有问题都当作钉子,他们通常不会试着去寻找别的工具。导致Web service泛滥的原因也是这个。
我觉得你应该重新看看Web service的优势(结果有人说了跨语言和SOA...果然关键还是相对什么做比较...)
Web service比那些non-xml的通信方式慢?这种相对的速度问题更多的取决于业务需求和你自己的代码实现(这个说法也同样适用于反射)。
最后我还是没有得到让我满意的答案,倒是复习了Web service...很多类似场景下人们都将Web service视为"standard"option。 既然如此...那就看看Web service吧。
看来使用web service是不可避免的。我曾对这个有些抵触,因为他给我印象总是麻烦+慢(后来虽然方便了许多,但还是很慢)。然后再去搜索"advantages of web service"什么的试着再让自己接受他。简单记录一下如何用Spring导出Endpoint。
假设我想在有一个Spring应用,我需要把一个Pojo或者一部分方法导出为Web Service。但这会有一个问题&&Endpoint的生命周期是由JAX-WS runtime来管理(The lifecycle of such an endpoint instance will be managed by the JAX-WS runtime),Spring context中的Bean无法autowire到Endpoint中,而我要导出的那些东东都用到了Spring管理的Bean。
对此,我们有两个解决方法:
org.springframework.web.context.support.SpringBeanAutowiringSupport
JaxWsServiceExporter
我上面括号中的那段话是引用的SpringBeanAutowiringSupport的javaDoc。使用该类的典型案例就是bean注入到JAX-WS endpoint类中(人家注释上写的),任何一个生命周期不是由Spring来管理的场景都可以用到他。而我们只需要继承这个类,也就是说创建一个实例时会调用父类的无参构造方法,我们来看看他的构造方法:
* This constructor performs injection on this instance,
* based on the current web application context.
* &p&Intended for use as a base class.
* #processInjectionBasedOnCurrentContext
public SpringBeanAutowiringSupport() {
processInjectionBasedOnCurrentContext(this);
* Process {@code} injection for the given target object,
* based on the current web application context.
* &p&Intended for use as a delegate.
* target the target object to process
* org.springframework.web.context.ContextLoader#getCurrentWebApplicationContext()
public static void processInjectionBasedOnCurrentContext(Object target) {
Assert.notNull(target, "Target object must not be null");
WebApplicationContext cc = ContextLoader.getCurrentWebApplicationContext();
if (cc != null) {
AutowiredAnnotationBeanPostProcessor bpp = new AutowiredAnnotationBeanPostProcessor();
bpp.setBeanFactory(cc.getAutowireCapableBeanFactory());
bpp.processInjection(target);
if (logger.isDebugEnabled()) {
logger.debug("Current WebApplicationContext is not available for processing of " +
ClassUtils.getShortName(target.getClass()) + ": " +
"Make sure this class gets constructed in a Spring web application. Proceeding without injection.");
那就试试看:
@WebService(serviceName="testMyService")
public class MyServiceEndpoint extends SpringBeanAutowiringSupport{
@Autowired
MyService myS
@WebMethod
public String sayHiFarAway(String name){
return myService.sayHiTo(name);
接着发布一下:
ApplicationContext context = new ClassPathXmlApplicationContext("classpath*:applicationContext*.xml");
Endpoint.publish("http://localhost:8080/myservices", (MyServiceEndpoint)context.getBean(MyServiceEndpoint.class));
javax.xml.ws.Service service = javax.xml.ws.Service.create(url, new QName("http://endpoint.king.pac/","testMyService"));
QName q = new QName("http://endpoint.king.pac/","MyServiceEndpointPort");
MyClientService client = service.getPort(q,MyClientService.class);
System.out.println(client.sayHiFarAway("King"));
写一个EndPoint还要继承和业务无关的类,让人不爽...而且发布和调用都麻烦。那试试SimpleJaxWsServiceExporter,只需要简单的配置就可以导出一个EndPoint。但是他也有需要注意的地方,引用一下该类的javaDoc:
Note that this exporter will only work if the JAX-WS runtime actually supports publishing with an address argument, i.e. if the JAX-WS runtime ships an internal HTTP server. This is the case with the JAX-WS runtime that's inclued in Sun's JDK 1.6 but not with the standalone JAX-WS 2.1 RI.
SimpleJaxWsServiceExporter会自动detect所有被WebService注解的类,因此只需要在配置中声明即可;此时Endpoint地址直接使用默认的localhost:8080:
&bean class="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter" /&
接着改善一下客户端的调用,使用JaxWsPortProxyFactoryBean:
&bean id="clientSide" class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean"
p:wsdlDocumentUrl="http://localhost:8080/testMyService?wsdl"
p:serviceName="testMyService"
p:portName="MyServiceEndpointPort"
p:serviceInterface="pac.king.endpoint.MyClientService"
p:namespaceUri="http://endpoint.king.pac/"
这样就可以像使用普通bean一样使用service了:
MyClientService client = (MyClientService)context.getBean("clientSide");
System.out.println(client.sayHiFarAway("King"));
用起来方便了不少,但仍然无法改变一个事实:
Web service requests are larger than requests encoded with a binary protocol.
还有就是http/https的问题。如果使用不当,我可能需要多做些工作去处理HTTP做不来的事情,而这时候RMI又非常适合。
Spring中如何配置Hibernate事务
Struts2整合Spring方法及原理
基于 Spring 设计并实现 RESTful Web Services
Spring-3.2.4 + Quartz-2.2.0集成实例
使用 Spring 进行单元测试
运用Spring注解实现Netty服务器端UDP应用程序
Spring 3.x 企业应用开发实战 PDF完整高清扫描版+源代码
Spring 的详细介绍:Spring 的下载地址:&
本文永久更新链接地址:
相关资讯 & & &
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款

我要回帖

更多关于 spring boot rpc 的文章

 

随机推荐