經過採用spring配置以及反射的方式來實現.對於一個服務提供者來講,須要提供端口,接口以及接口實現類,所以在接口中spring配置文件中配置以下web
<!-- 服務代理列表 --> <util:list id="serverProxyList"> <ref bean="resourceMgtProxy" /> </util:list>
<!-- 資源管理 --> <bean id="resourceMgtServer" class="com.nari.rpc.server.ResourceMgtServer" /> <bean id="resourceMgtProxy" class="com.nari.proxy.RpcServerProxy"> <property name="port" value="1002"/> <property name="serviceInterface" value="com.nari.api.resource.rpc.ResourceMgtRpc"/> <property name="serviceImplObject" ref="resourceMgtServer"/> </bean>
接下來定義ThriftServerProxy類,定義bean中須要用到的3個屬性,接下來經過反射來實現服務的啓動。spring
public class RpcServerProxy { // 端口 private int port; // 服務接口 private String serviceInterface; //服務實現類 private Object serviceImplObject; /** * 啓動RPC服務 */ public void start() { ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); cachedThreadPool.execute(() -> { try { TNonblockingServerTransport serverTransport = new TNonblockingServerSocket(getPort()); Class processor = Class.forName(getServiceInterface() + "$Processor"); Class face = Class.forName(getServiceInterface() + "$Iface"); Constructor con = processor.getConstructor(face); TProcessor tProcessor = (TProcessor) con.newInstance(serviceImplObject); TBinaryProtocol.Factory factory = new TBinaryProtocol.Factory(true, true); TThreadedSelectorServer.Args args = new TThreadedSelectorServer.Args(serverTransport); args.protocolFactory(factory); args.processor(tProcessor); TServer server = new TThreadedSelectorServer(args); // 啓動服務 server.serve(); } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException | TTransportException e) { e.printStackTrace(); } }); } public Object getServiceImplObject() { return serviceImplObject; } public void setServiceImplObject(Object serviceImplObject) { this.serviceImplObject = serviceImplObject; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public String getServiceInterface() { return serviceInterface; } public void setServiceInterface(String serviceInterface) { this.serviceInterface = serviceInterface; } }
配置監聽啓動服務api
** * 服務啓動監聽器 */ public class RpcServerStartListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent event) { try { ApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext()); // 獲取服務代理列表 List<RpcServerProxy> proxyList = ((List<RpcServerProxy>) context.getBean("serverProxyList")); if (!CollectionUtils.isEmpty(proxyList)) { // 啓動代理服務 proxyList.forEach(proxy -> proxy.start()); } } catch (Exception e) { e.printStackTrace(); } } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { } }
最後在web.xml中添加listener便可ide
對於客戶端,從鏈接池裏面獲取一個可用的服務端鏈接,經過反射的方式獲取客戶端,在spring-client.xml中配置以下:this
<!-- thrift鏈接池配置 --> <bean id="connectionProvider" class="com.nari.common.thrift.pool.impl.ConnectionProviderImpl"> <property name="serviceIP" value="localhost" /> <property name="servicePort" value="1002" /> <property name="maxActive" value="10" /> <property name="maxIdle" value="10" /> <property name="testOnBorrow" value="true" /> <property name="testOnReturn" value="true" /> <property name="testWhileIdle" value="true" /> <property name="conTimeOut" value="30000" /> </bean> <bean id="connectionManager" class="com.nari.common.thrift.pool.ConnectionManager"> <property name="connectionProvider" ref="connectionProvider"/> </bean> <bean id="thriftClientProxy" class="com.nari.common.thrift.proxy.ThriftClientProxy"> <property name="connectionManager" ref="connectionManager"/> </bean>
客戶端的代理對象獲取client代碼:spa
public class ThriftClientProxy { private ConnectionManager connectionManager; public ConnectionManager getConnectionManager() { return connectionManager; } public void setConnectionManager(ConnectionManager connectionManager) { this.connectionManager = connectionManager; } public Object getClient(Class clazz) { Object result = null; try { TTransport transport = connectionManager.getSocket(); TProtocol protocol = new TBinaryProtocol(transport); Class client = Class.forName(clazz.getName() + "$Client"); Constructor con = client.getConstructor(TProtocol.class); result = con.newInstance(protocol); //transport.open(); } catch (Exception e) { e.printStackTrace(); } return result; } }
使用:代理
ResourceMgtRpc.Iface client = (ResourceMgtRpc.Iface) thriftClientProxy.getClient(ResourceMgtRpc.class); // 封裝請求參數 QuerySyncStatusRequest requestPo = new QuerySyncStatusRequest(); requestPo.setMasterSourceId(master.getResourceId()); QuerySyncStatusResponse responsePo = client.querySynStatus(requestPo);
當前的不足:
沒有使用訂閱服務列表, 使得在配置中, 須要指定ip:port列表,若是有多個指定的ip:port須要配置多個鏈接池。server