现在在做个车务通系统(网站),系统需要与远程的mina服务器端进行交换,服务器端由其他公司开发,只为我们提供接口,在我们的车务通系统中需要通过网络编程调用这些远程接口,所以车务通系统相当于mina的客户端(相对于mina服务器端而言)。
流程是这样的 当车务通系统的客户端,也就是浏览器页面,发出请求,车务通系统中的servlet接收,调用mina客户端的Iosession.write()方法 向mina服务器端(也就是远程服务器)发送请求、调用接口后 , 远程服务器会返回响应的处理结果,
然后在mina客户端(车务通系统中接收),messageReceive()方法负责接收,在这里遇到了问题,接收后的数据该如何返回给客户端(浏览器端)。
这个问题其实很简单,没有大家想的那么复杂,只是大家没有想到点子上而己,解决办法就是要将接收后的数据和当前请求联系起来就可以返回给客户端了,以下是简单的解决办法:
在车务通系统客户端,也就是浏览器页面,发出请求,调用mina客户端的Iosession.write()方法,发送请求前产生一个系统全局唯一标识,并将这个标识保存到Iosession中,如:
1 /** 2 * @see HttpServlet#service(HttpServletRequest request, HttpServletResponse 3 * response) 4 */ 5 protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, 6 IOException { 7 8 response.setContentType("text/html;charset=utf-8"); 9 10 String param1 = request.getParameter("param1"); 11 12 // 创建客户端连接器 13 IoConnector connector = new NioSocketConnector(); 14 // 设置事件处理器 15 connector.setHandler(new ClientHandler()); 16 // 设置编码过滤器和按行读取数据模式 17 connector.getFilterChain().addLast("codec", 18 new ProtocolCodecFilter(new TextLineCodecFactory(Charset.forName("UTF-8")))); 19 // 创建连接 20 ConnectFuture future = connector.connect(new InetSocketAddress(TARGET_IP, PORT)); 21 // 等待连接创建完成 22 future.awaitUninterruptibly(); 23 // 获取连接会话 24 IoSession session = future.getSession(); 25 26 // 产生当次发送请求标识,标识由客户端地址+随机数 27 // 这里的标识只是一个例子,标识可以任何方法产生,只要保持在系统中的唯一性 28 String flag = request.getLocalAddr() + UUID.randomUUID().toString(); 29 //将标识保存到当前session中 30 session.setAttribute("SendRequestFlag", flag); 31 /// 发送信息 32 session.write(param1); 33 /// 等待连接断开 34 session.getCloseFuture().awaitUninterruptibly(); 35 connector.dispose(); 36 37 //通过标识获取保存的结果 38 Object result = ClientHandler.results.get(flag); 39 //清除标识内容 40 ClientHandler.results.remove(flag); 41 //将结果返回客户端 42 response.getWriter().write(result.toString()); 43 }
然后在mina客户端(车务通系统中接收),messageReceive()方责接收到消息时将系统全局唯一标识从Iosession中取出,将其和当前数据绑定保存,如:
public static final Map<String,Object> results = new ConcurrentHashMap<String,Object>(); public void messageReceived(IoSession session, Object message) throws Exception { //从session中取到标识 String flag = (String)session.getAttribute("SendRequestFlag"); //将从服务端接收到的message和标识绑定保存,可以保存到内存、队列、文件、数据库等等 //在这里简单的以标识为key,message为value保存到Map中 results.put(flag, message); //关闭session session.close(true); }
最后通过系统全局唯一标识获取结果并返回给客户端
//通过标识获取保存的结果 Object result = ClientHandler.results.get(flag); //清除标识内容 ClientHandler.results.remove(flag); //将结果返回客户端 response.getWriter().write(result.toString());
从上可知,我们可以通过IoSession将一个标识传到messageReceived方法中,熟悉web开发的知道,IoSession在这里跟HttpSession使用方式一样,因此我们可以将任何东东通过IoSession传到messageReceived方法中,比如HttpServletRequest、HttpServletResponse、Spring bean、Hibernate Dao、数据库连接等等。反之,在messageReceived方法中通过IoSession将接收后的数据或任何其它东东传到外面,这时就不能在messageReceived方法中关闭IoSession了。
用servlet简单写了一个例子,以供参考,见附件。采用同步、异步调用均可,任君选择,在这例子中我采用jquery的ajax异步调用