3、正式开始编码
我已经在CSDN的资源区上传了这个示例工程的所有代码(http://download.csdn.net/detail/yinwenjie/9289999)。读者可以直接到资源下载站进行下载(不收积分哦~~^_^)。这篇文章将紧接上文,主要介绍这个工程几个主要的类代码。
3-1、编写服务端主程序
服务端主程序的类名:processor.MainProcessor,它负责在服务端启动Apache Thrift并且在服务监听启动成功后,连接到zookeeper,注册这个服务的基本信息。
这里要注意一下,Apache Thrift的服务监听是阻塞式的,所以processor.MainProcessor的Apache Thrift操作应该另起线程进行(processor.MainProcessor.StartServerThread),并且通过线程间的锁定操作,保证zookeeper的连接一定是在Apache Thrift成功启动后才进行。
package processor;import java.io.IOException;import java.util.Set;import java.util.concurrent.Executors;import net.sf.json.JSONObject;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.log4j.BasicConfigurator;import org.apache.thrift.TProcessor;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.protocol.TProtocol;import org.apache.thrift.server.ServerContext;import org.apache.thrift.server.TServerEventHandler;import org.apache.thrift.server.TThreadPoolServer;import org.apache.thrift.server.TThreadPoolServer.Args;import org.apache.thrift.transport.TServerSocket;import org.apache.thrift.transport.TTransport;import org.apache.thrift.transport.TTransportException;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.KeeperException;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.ZooKeeper;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.data.Stat;import business.BusinessServicesMapping;import thrift.iface.DIYFrameworkService;import thrift.iface.DIYFrameworkService.Iface;public class MainProcessor { static { BasicConfigurator.configure(); } /** * 日志 */ private static final Log LOGGER = LogFactory.getLog(MainProcessor.class); private static final Integer SERVER_PORT = 8090; /** * 专门用于锁定以保证这个主线程不退出的一个object对象 */ private static final Object WAIT_OBJECT = new Object(); /** * 标记apache thrift是否启动成功了 * 只有apache thrift启动成功了,才需要连接到zk */ private boolean isthriftStart = false; public static void main(String[] args) { MainProcessor mainProcessor = new MainProcessor(); mainProcessor.startServer(); synchronized (mainProcessor) { try { while(!mainProcessor.isthriftStart) { mainProcessor.wait(); } } catch (InterruptedException e) { MainProcessor.LOGGER.error(e); System.exit(-1); } } try { mainProcessor.connectZk(); } catch (IOException | KeeperException | InterruptedException e) { MainProcessor.LOGGER.error(e); System.exit(-1); } synchronized (MainProcessor.WAIT_OBJECT) { try { MainProcessor.WAIT_OBJECT.wait(); } catch (InterruptedException e) { MainProcessor.LOGGER.error(e); System.exit(-1); } } } /** * 这个私有方法用于连接到zk上,并且注册相关服务 * @throws IOException * @throws InterruptedException * @throws KeeperException */ private void connectZk() throws IOException, KeeperException, InterruptedException { Set<String> serviceNames = BusinessServicesMapping.SERVICES_MAPPING.keySet(); if(serviceNames == null || serviceNames.isEmpty()) { return; } MyDefaultWatcher defaultWatcher = new MyDefaultWatcher(); ZooKeeper zk = new ZooKeeper("192.168.61.128:2181", 120000, defaultWatcher); Stat pathStat = null; try { pathStat = zk.exists("/Service", defaultWatcher); if(pathStat == null) { zk.create("/Service", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch(Exception e) { System.exit(-1); } for (String serviceName : serviceNames) { JSONObject nodeData = new JSONObject(); nodeData.put("ip", "127.0.0.1"); nodeData.put("port", MainProcessor.SERVER_PORT); zk.create("/Service/" + serviceName, nodeData.toString().getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL); } MainProcessor.LOGGER.info("===================所有service都启动完成了,主线程开始启动==================="); } /** * 这个私有方法用于开启Apache thrift服务端,并进行持续监听 * @throws TTransportException */ private void startServer() { Thread startServerThread = new Thread(new StartServerThread()); startServerThread.start(); } private class StartServerThread implements Runnable { @Override public void run() { MainProcessor.LOGGER.info("看到这句就说明thrift服务端准备工作 ...."); TProcessor tprocessor = new DIYFrameworkService.Processor<Iface>(new DIYFrameworkServiceImpl()); TServerSocket serverTransport = null; try { serverTransport = new TServerSocket(MainProcessor.SERVER_PORT); } catch (TTransportException e) { MainProcessor.LOGGER.error(e); System.exit(-1); } Args tArgs = new Args(serverTransport); tArgs.processor(tprocessor); tArgs.protocolFactory(new TBinaryProtocol.Factory()); tArgs.executorService(Executors.newFixedThreadPool(100)); TThreadPoolServer server = new TThreadPoolServer(tArgs); server.setServerEventHandler(new StartServerEventHandler()); server.serve(); } } /** * 为这个TThreadPoolServer对象,设置是一个事件处理器。 * 以便在TThreadPoolServer正式开始监听服务请求前,通知mainProcessor: * “Apache Thrift已经成功启动了” * @author yinwenjie * */ private class StartServerEventHandler implements TServerEventHandler { @Override public void preServe() { MainProcessor.this.isthriftStart = true; synchronized (MainProcessor.this) { MainProcessor.this.notify(); } } @Override public ServerContext createContext(TProtocol input, TProtocol output) { return null; } @Override public void deleteContext(ServerContext serverContext, TProtocol input, TProtocol output) { } @Override public void processContext(ServerContext serverContext, TTransport inputTransport, TTransport outputTransport) { } } /** * 这是默认的watcher,什么也没有,也不需要有什么<br> * 因为按照功能需求,服务器端并不需要监控zk上的任何目录变化事件 * @author yinwenjie */ private class MyDefaultWatcher implements Watcher { public void process(WatchedEvent event) { } }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
3-2、编写服务具体实现
服务端具体实现的代码很简单,就是在IDL脚本生成了Java代码后,对DIYFrameworkService接口进行的实现。
package processor;import java.nio.ByteBuffer;import net.sf.json.JSONObject;import org.apache.commons.lang.StringUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.thrift.TException;import business.BusinessService;import business.BusinessServicesMapping;import business.exception.BizException;import business.exception.ResponseCode;import business.pojo.AbstractPojo;import business.pojo.BusinessResponsePojo;import business.pojo.DescPojo;import thrift.iface.DIYFrameworkService.Iface;import thrift.iface.EXCCODE;import thrift.iface.RESCODE;import thrift.iface.Reponse;import thrift.iface.Request;import thrift.iface.ServiceException;import utils.JSONUtils;/** * IDL文件中,我们定义的唯一服务接口DIYFrameworkService.Iface的唯一实现 * @author yinwenjie * */public class DIYFrameworkServiceImpl implements Iface { /** * 日志 */ public static final Log LOGGER = LogFactory.getLog(DIYFrameworkServiceImpl.class); @SuppressWarnings("unchecked") @Override public Reponse send(Request request) throws ServiceException, TException { String serviceName = request.getServiceName(); String className = BusinessServicesMapping.SERVICES_MAPPING.get(serviceName); if(StringUtils.isEmpty(className)) { return this.buildErrorReponse("无效的服务" , null); } JSONObject paramJSON = null; try { byte [] paramJSON_bytes = request.getParamJSON(); if(paramJSON_bytes != null && paramJSON_bytes.length > 0) { String paramJSON_string = new String(paramJSON_bytes); paramJSON = JSONObject.fromObject(paramJSON_string); } } catch(Exception e) { DIYFrameworkServiceImpl.LOGGER.error(e); throw new ServiceException(EXCCODE.PARAMNOTFOUND, e.getMessage()); } BusinessService<AbstractPojo> businessServiceInstance = null; try { businessServiceInstance = (BusinessService<AbstractPojo>)Class.forName(className).newInstance(); } catch (Exception e) { DIYFrameworkServiceImpl.LOGGER.error(e); throw new ServiceException(EXCCODE.SERVICENOTFOUND, e.getMessage()); } AbstractPojo returnPojo = null; try { returnPojo = businessServiceInstance.handle(paramJSON); } catch (BizException e) { DIYFrameworkServiceImpl.LOGGER.error(e); return this.buildErrorReponse(e.getMessage() , e.getResponseCode()); } BusinessResponsePojo responsePojo = new BusinessResponsePojo(); responsePojo.setData(returnPojo); DescPojo descPojo = new DescPojo("", ResponseCode._200); responsePojo.setDesc(descPojo); String returnString = JSONUtils.toString(responsePojo); byte[] returnBytes = returnString.getBytes(); ByteBuffer returnByteBuffer = ByteBuffer.allocate(returnBytes.length); returnByteBuffer.put(returnBytes); returnByteBuffer.flip(); Reponse reponse = new Reponse(RESCODE._200, returnByteBuffer); return reponse; } /** * 这个私有方法,用于构造“Thrift中错误的返回信息” * @param erroe_mess * @return */ private Reponse buildErrorReponse(String erroe_mess , ResponseCode responseCode) { BusinessResponsePojo responsePojo = new BusinessResponsePojo(); responsePojo.setData(null); DescPojo descPojo = new DescPojo(erroe_mess, responseCode == null?ResponseCode._504:responseCode); responsePojo.setDesc(descPojo); String responseJSON = JSONUtils.toString(responsePojo); byte[] responseJSON_bytes = responseJSON.getBytes(); ByteBuffer byteBuffer = ByteBuffer.allocate(responseJSON_bytes.length); byteBuffer.put(byteBuffer); byteBuffer.flip(); Reponse reponse = new Reponse(RESCODE._500, byteBuffer); return reponse; }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
3-3、编写客户端实现
在上文中已经介绍过了,客户端有两件事情需要做:连接到zookeeper查询注册的服务该如何访问;然后向真实的服务提供者发起请求。代码如下:
package client;import java.nio.ByteBuffer;import java.util.List;import net.sf.json.JSONObject;import org.apache.commons.lang.StringUtils;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.apache.log4j.BasicConfigurator;import org.apache.thrift.protocol.TBinaryProtocol;import org.apache.thrift.protocol.TProtocol;import org.apache.thrift.transport.TSocket;import org.apache.zookeeper.CreateMode;import org.apache.zookeeper.WatchedEvent;import org.apache.zookeeper.Watcher;import org.apache.zookeeper.ZooKeeper;import org.apache.zookeeper.ZooDefs.Ids;import org.apache.zookeeper.data.Stat;import thrift.iface.DIYFrameworkService.Client;import thrift.iface.Reponse;import thrift.iface.Request;import utils.JSONUtils;public class ThriftClient { /** * 日志 */ private static final Log LOGGER = LogFactory.getLog(ThriftClient.class); private static final String SERVCENAME = "queryUserDetailService"; static { BasicConfigurator.configure(); } public static final void main(String[] main) throws Exception { ClientDefaultWatcher defaultWatcher = new ClientDefaultWatcher(); ZooKeeper zk = new ZooKeeper("192.168.61.128:2181", 120000, defaultWatcher); Stat pathStat = null; try { pathStat = zk.exists("/Service", defaultWatcher); if(pathStat == null) { zk.create("/Service", "".getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); } } catch(Exception e) { System.exit(-1); } List<String> serviceList = zk.getChildren("/Service", false); if(serviceList == null || serviceList.isEmpty()) { ThriftClient.LOGGER.info("未发现相关服务,客户端退出"); return; } boolean isFound = false; byte[] data; for (String serviceName : serviceList) { if(StringUtils.equals(serviceName, ThriftClient.SERVCENAME)) { isFound = true; break; } } if(!isFound) { ThriftClient.LOGGER.info("未发现相关服务,客户端退出"); return; } else { data = zk.getData("/Service/" + ThriftClient.SERVCENAME, false, null); } zk.close(); if(data == null || data.length == 0) { ThriftClient.LOGGER.info("未发现有效的服务端地址,客户端退出"); return; } JSONObject serverTargetJSON = null; String serverIp; String serverPort; try { serverTargetJSON = JSONObject.fromObject(new String(data)); serverIp = serverTargetJSON.getString("ip"); serverPort = serverTargetJSON.getString("port"); } catch(Exception e) { ThriftClient.LOGGER.error(e); return; } TSocket transport = new TSocket(serverIp, Integer.parseInt(serverPort)); TProtocol protocol = new TBinaryProtocol(transport); JSONObject jsonParam = new JSONObject(); jsonParam.put("username", "yinwenjie"); byte[] params = jsonParam.toString().getBytes(); ByteBuffer buffer = ByteBuffer.allocate(params.length); buffer.put(params); buffer.flip(); Request request = new Request(buffer, ThriftClient.SERVCENAME); Client client = new Client(protocol); transport.open(); Reponse reponse = client.send(request); byte[] responseBytes = reponse.getResponseJSON(); transport.close(); ThriftClient.LOGGER.info("respinse value = " + new String(responseBytes)); }}/** * 这是默认的watcher,什么也没有,也不需要有什么<br> * 因为按照功能需求,客户端并不需要监控zk上的任何目录变化事件 * @author yinwenjie */class ClientDefaultWatcher implements Watcher { public void process(WatchedEvent event) { }}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
3-4、工程结构说明
以上代码是服务器端、客户端的主要代码。整个工程还有其他的辅助代码,为了让各位读者能够看得清楚直接,我们将整个工程结构进行一下说明,下载后导入的工程结构如下图所示:
这是一个典型的JAVA工程。请使用 JDK 1.6+ 版本。我们将讲解整个工程结构。首先来看看这个工程中主要的package和它们的作用。
business:具体的业务层逻辑都在这个包里面,其中exception包含了一个业务层异常的定义BizException,还有错误代码ResponseCode;impl包中放置具体的业务层实现,它们都必须实现BusinessService接口;Pojo是业务层对象模型。client:为了简单起见,我将服务端的实现和客户端的实现放置在一个工程中,client这个包就是客户端的实现代码了;utils包放置了两个工具类,用来进行日期格式化的DataUtils和用来进行json转换的JSONUtils。
定义的apache thrift IDL文件放置在thrift文件夹下面,名字叫做:demoHello.thrift;您可以使用它生成各种语言的代码;
工程需要maven的支持。
2016年08月08日,由网友OneZhous发现了一个程序的bug,这是由于Apache Thrift内部并不会在进行org.apache.thrift.TBaseHelper.copyBinary执行时,将java.nio.ByteBuffer自动进行flip()。所以在完成request和response对象设置后,需要开发人员自行进行flip()。感谢OneZhous对文章中的问题进行纠正,但是CSDN由于无法修改已上传的资源,所以还请各位读者在下载运行时注意这个问题:
......ByteBuffer buffer = ByteBuffer.allocate(params.length);buffer.put(params);buffer.flip();// 以及位置ByteBuffer byteBuffer = ByteBuffer.allocate(responseJSON_bytes.length);byteBuffer.put(byteBuffer);byteBuffer.flip();......