Thrift网上有N多教程,不再赘述,这里搭建的是WEB项目,使用了spring,所以尽量使用了基于配置的方式。
一。server端
本着少些代码,配置优先的原则,在server端引入代理类,如下:
ThriftServerProxy:使用了反射
public class ThriftServerProxy { private static Logger logger = Logger.getLogger(ThriftServerStartListener.class); private int port;// 端口 private String serviceInterface;// 实现类接口 private Object serviceImplObject;//实现类 set and get …………………… @SuppressWarnings({ "rawtypes", "unchecked" }) public void start() { new Thread() { public void run() { try { TServerSocket serverTransport = new TServerSocket(getPort()); Class Processor = Class.forName(getServiceInterface()+"$Processor"); Class Iface = Class.forName(getServiceInterface()+"$Iface"); Constructor con = Processor.getConstructor(Iface); TProcessor processor = (TProcessor)con.newInstance(serviceImplObject); Factory protFactory = new TBinaryProtocol.Factory(true,true); TThreadPoolServer.Args args = new TThreadPoolServer.Args(serverTransport); args.protocolFactory(protFactory); args.processor(processor); TServer server = new TThreadPoolServer(args); logger.info("Starting server on port "+getPort()+" ..."); server.serve(); } catch (TTransportException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } }.start(); } }
applicationContext-thrift.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" …………………………………………………… <description>thrift服务</description> <!-- 声明多个server,并将其关联到该list中,以便监听器自动启动 --> <util:list id="thriftServerList"> <ref bean="userProxy01" /> <ref bean="userProxy02" /> </util:list> <bean id="userProxy01" class="thrift.proxy.ThriftServerProxy"> <property name="port" value="7911"/> <property name="serviceInterface" value="thrift.service.UserService"/> <property name="serviceImplObject" ref="userServiceImpl"/> </bean> <bean id="userProxy02" class="thrift.proxy.ThriftServerProxy"> <property name="port" value="7910"/> <property name="serviceInterface" value="thrift.service.UserService"/> <property name="serviceImplObject" ref="userServiceImpl"/> </bean> </beans>
使用监听器启动全部服务:
ThriftServerStartListener:
public class ThriftServerStartListener implements ServletContextListener{ private static Logger logger = Logger.getLogger(UserServiceImpl.class); @Override public void contextDestroyed(ServletContextEvent event) { } @SuppressWarnings("unchecked") @Override public void contextInitialized(ServletContextEvent event) { //启动SETUP SEERVER try { ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext()); List<ThriftServerProxy> list = ((List<ThriftServerProxy>) context.getBean("thriftServerList")); if(list!=null&&list.size()>0){ for(ThriftServerProxy userProxy:list){ userProxy.start(); } } logger.info("Thrift Server监听接口启动。。。。。。。。。。。"); } catch (Exception e) { logger.error("Thrift Server监听接口启动错误", e); e.printStackTrace(); } } }
二。client端
client使用链接池管理链接,同时对客户端使用代理,spring配置如下:
applicationContext-thrift.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" …………………………………………………… <description>thrift客户端</description> <context:property-placeholder location="classpath:config/properties/thrift.properties" /> <!-- 连接池,管理器,客户端代理,3个一组 --> <!-- thrift连接池配置7911 --> <bean id="connectionProvider01" class="thrift.common.ConnectionProviderImpl"> <property name="serviceIP" value="${thrift.ens.ip01}" /> <property name="servicePort" value="${thrift.ens.port01}" /> <property name="maxActive" value="${thrift.ens.maxActive}" /> <property name="maxIdle" value="${thrift.ens.maxIdle}" /> <property name="testOnBorrow" value="${thrift.ens.testOnBorrow}" /> <property name="testOnReturn" value="${thrift.ens.testOnReturn}" /> <property name="testWhileIdle" value="${thrift.ens.testWhileIdle}" /> <property name="conTimeOut" value="${thrift.ens.conTimeOut}" /> </bean> <!-- thrift连接管理配置7911 --> <bean id="connectionManager01" class="thrift.common.ConnectionManager"> <property name="connectionProvider" ref="connectionProvider01" /> </bean> <bean id="userClient01" class="thrift.proxy.ThriftClientProxy"> <property name="serviceInterface" value="thrift.service.UserService" /> <property name="connectionManager" ref="connectionManager01" /> </bean> <!-- thrift连接池配置7910 --> <bean id="connectionProvider02" class="thrift.common.ConnectionProviderImpl"> <property name="serviceIP" value="${thrift.ens.ip02}" /> <property name="servicePort" value="${thrift.ens.port02}" /> <property name="maxActive" value="${thrift.ens.maxActive}" /> <property name="maxIdle" value="${thrift.ens.maxIdle}" /> <property name="testOnBorrow" value="${thrift.ens.testOnBorrow}" /> <property name="testOnReturn" value="${thrift.ens.testOnReturn}" /> <property name="testWhileIdle" value="${thrift.ens.testWhileIdle}" /> <property name="conTimeOut" value="${thrift.ens.conTimeOut}" /> </bean> <!-- thrift连接管理配置 7910--> <bean id="connectionManager02" class="thrift.common.ConnectionManager"> <property name="connectionProvider" ref="connectionProvider02" /> </bean> <bean id="userClient02" class="thrift.proxy.ThriftClientProxy"> <property name="serviceInterface" value="thrift.service.UserService" /> <property name="connectionManager" ref="connectionManager02" /> </bean> </beans>
ThriftClientProxy:
public class ThriftClientProxy { private String serviceInterface; private ConnectionManager connectionManager; set and get…………………… @SuppressWarnings({ "rawtypes", "unchecked" }) public Object getClient() { Object object = null; try { TTransport transport = connectionManager.getSocket(); TProtocol protocol = new TBinaryProtocol(transport); Class client = Class.forName(getServiceInterface() + "$Client"); Constructor con = client.getConstructor(TProtocol.class); object = con.newInstance(protocol); } catch (ClassNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SecurityException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchMethodException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InstantiationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (InvocationTargetException e) { // TODO Auto-generated catch block e.printStackTrace(); } return object; } }
客户端调用,这里使用一个controller:
@Controller public class IndexController { @Resource(name="userClient01") private ThriftClientProxy client01; @Resource(name="userClient02") private ThriftClientProxy client02; @RequestMapping("/index.do") public String handleIndex(Model model) { UserService.Client client_01 = (UserService.Client)(client01.getClient()); UserService.Client client_02 = (UserService.Client)(client02.getClient()); String name; try { client_01.getUser("zhangsan"); name = client_02.getUserName("zhaosi", 100); model.addAttribute("userName", name); } catch (TException e) { // TODO Auto-generated catch block e.printStackTrace(); } return "index"; } }
连接池部分参考了如下内容:http://wenku.baidu.com/view/d0e91021aaea998fcc220e3d.html
代码详见附件。