这节把spring整合进Thrift,这次用maven来构建工程,maven的pom.xml加上依赖:
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>4.3.7.RELEASE</version> </dependency> <dependency> <groupId>org.apache.thrift</groupId> <artifactId>libthrift</artifactId> <version>0.9.3</version> </dependency>
1 客户端:我们可以把transport,protocol以及根据接口定义文件生成的ThriftTest.Client的实例化放到spring容器中,由spring容器维护它们的依赖关系,这样客户端的调用代码会简洁很多,并且ThriftTest.Client的transport和protocol将是可配置的。
spring-config-client.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- <context:component-scan base-package="thrift.test"/> --> <bean id="tSocket" class="org.apache.thrift.transport.TSocket" scope="prototype"> <constructor-arg name="host" value="localhost"/> <constructor-arg name="port" value="9090"/> <property name="timeout" value="1000"/> </bean> <bean id="tFastFramedTransport" class="org.apache.thrift.transport.TFastFramedTransport" init-method="open" destroy-method="close" scope="prototype"> <constructor-arg name="underlying" ref="tSocket"/> </bean> <bean id="tCompactProtocol" class="org.apache.thrift.protocol.TCompactProtocol" scope="prototype"> <constructor-arg name="transport" ref="tFastFramedTransport"/> </bean> <bean id="testClient" class="thrift.test.ThriftTest.Client" scope="prototype"> <constructor-arg name="prot" ref="tCompactProtocol"/> </bean> </beans>
TestClient.java:
package com.halloffame.thriftspring;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import thrift.test.ThriftTest;
import thrift.test.User;
public class TestClient {
public static final AbstractApplicationContext context = new ClassPathXmlApplicationContext("spring-config-client.xml");
public static void main(String [] args) throws Exception {
ThriftTest.Client testClient = (ThriftTest.Client)context.getBean("testClient");
//getUser就是ThriftTest.thrift所定义的接口
User user = testClient.getUser(2);
System.out.println("名字:"+ user.getName());
//context.registerShutdownHook();
//context.close();
testClient.getInputProtocol().getTransport().close();
}
}
2 服务端:本来也想把那些transport,protocol之类的放到spring当中,但是发现一些成员变量是没有set方法的,无法依赖注入。不过服务端最重要的还是业务逻辑的实现类TestHandler,把这个放到spring容器里。服务端采用注解配置类SpringConfigServer。
SpringConfigServer.java:
package com.halloffame.thriftspring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration //表明这是注解配置类,相当于spring-config-client.xml
@ComponentScan //相当于xml配置文件里的标签<context:component-scan .../>
public class SpringConfigServer {
}
TestHandler.java:
package com.halloffame.thriftspring;
import org.apache.thrift.TException;
import org.springframework.stereotype.Component;
import thrift.test.ThriftTest;
import thrift.test.User;
/**
* 具体的业务逻辑类
* 实现ThriftTest.thrift里的getUser接口
*/
@Component //由spring容器实例化管理等
public class TestHandler implements ThriftTest.Iface {
@Override
public User getUser(int id) throws TException {
System.out.println("id==>" + id);
if (id == 2 ) {
User user = new User();
user.setId(2);
user.setName("另外一个烟火");
return user;
}
return null;
}
}
TestServer.java:
package com.halloffame.thriftspring;
import org.apache.thrift.protocol.TCompactProtocol;
import org.apache.thrift.protocol.TProtocolFactory;
import org.apache.thrift.server.TServer;
import org.apache.thrift.server.TThreadedSelectorServer;
import org.apache.thrift.transport.TFastFramedTransport;
import org.apache.thrift.transport.TNonblockingServerSocket;
import org.apache.thrift.transport.TTransportFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import thrift.test.ThriftTest;
public class TestServer {
public static final ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfigServer.class);
public static void main(String [] args) throws Exception {
//从spring容器中取得业务处理bean TestHandler
ThriftTest.Iface iface = context.getBean(TestHandler.class);
//ThriftTest.Processor是生成的服务端代码
ThriftTest.Processor testProcessor = new ThriftTest.Processor(iface);
//指定的通信协议
TProtocolFactory tProtocolFactory = new TCompactProtocol.Factory();
//指定的通信方式
TTransportFactory tTransportFactory = new TFastFramedTransport.Factory();
int port = 9090;
TNonblockingServerSocket tNonblockingServerSocket =
new TNonblockingServerSocket(new TNonblockingServerSocket.NonblockingAbstractServerSocketArgs().port(port));
TThreadedSelectorServer.Args tThreadedSelectorServerArgs
= new TThreadedSelectorServer.Args(tNonblockingServerSocket);
tThreadedSelectorServerArgs.processor(testProcessor);
tThreadedSelectorServerArgs.protocolFactory(tProtocolFactory);
tThreadedSelectorServerArgs.transportFactory(tTransportFactory);
//指定的服务器模式
TServer serverEngine = new TThreadedSelectorServer(tThreadedSelectorServerArgs);
System.out.println("Starting the server on port " + port + "...");
serverEngine.serve();
}
}
3 工程结构图:
依次运行TestServer,TestClient,结果如预期。
附件是整个eclipse的maven工程。