如何实现后台向前台传数据


技术交流群:233513714

这两天正在研究如何让后天主动向前台展现数据,只要后台有数据上传的时候就向前台上传(因为公司有个项目,硬件设备会不断的上传数据,服务端将接收到的数据向前台展示)。在网上查了一下,下面将介绍一下其中的两种解决办法

一、WebSocket

WebSocket 是web客户端和服务器之间新的通讯方式, 依然架构在HTTP协议之上。使用WebSocket连接, web应用程序可以执行实时的交互, 而不是以前的poll方式。

WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议,可以用来创建快速的更大规模的健壮的高性能实时的web应用程序。WebSocket通信协议于2011年被IETF定为标准RFC 6455,WebSocketAPI被W3C定为标准。
在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。

声明Encoder/Decoder也是相当的简单: 你只需在@ServerEndpoint注解中增加encoder/decoder设置:

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 package com.sample.websocket;   import java.util.logging.Level; import java.util.logging.Logger; import javax.websocket.*; import javax.websocket.server.ServerEndpoint;   @ServerEndpoint(value = "/hello", decoders = { MessageDecoder.class,}, encoders = { MessageEncoder.class }) public class HelloWorldEndpoint {   @OnMessage public Person hello(Person person, Session session) { if (person.getName().equals("john")) { person.setName("Mr. John"); } try { session.getBasicRemote().sendObject(person); System.out.println("sent ");catch (Exception ex) { Logger.getLogger(HelloWorldEndpoint.class.getName()).log(Level.SEVERE, null, ex); } return person;   }   @OnOpen public void myOnOpen(Session session) { }   }

正像你看到的, OnMessage方法使用Java Object person作为参数, 我们为名字增加个尊称再返回给客户端。通过session.getBasicRemote().sendObject(Object obj)返回数据.
容器负责使用你指定的Decoder将接收到的XML消息转为Java对象:

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 package com.sample.websocket;   import java.io.StringReader;   import javax.websocket.Decoder; import javax.websocket.EndpointConfig; import javax.xml.bind.*;     public class MessageDecoder implementsDecoder.Text<Person> {   @Override public Person decode(String s) { System.out.println("Incoming XML " + s); Person person = null; JAXBContext jaxbContext; try { jaxbContext = JAXBContext.newInstance(Person.class);   Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();   StringReader reader = new StringReader(s); person = (Person) unmarshaller.unmarshal(reader); } catch (Exception ex) { ex.printStackTrace(); } return person; }   @Override public boolean willDecode(String s) {   return (s != null); }   @Override public void init(EndpointConfig endpointConfig) { // do nothing. }   @Override public void destroy() { // do nothing. } }

这里我们使用JAXB做转换。我们只要实现一个泛型接口Decoder.Text 或者 Decoder.Binary, 根据你传输的数据是文本还是二进制选择一个.

所以数据由Decoder解码, 传给Endpoint (这里的 HelloWorldEndpoint), 在返回给client之前, 它还会被下面的Encoder转换成XML:

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 package com.sample.websocket;   import java.io.StringWriter;   import javax.websocket.EncodeException; import javax.websocket.Encoder; import javax.websocket.EndpointConfig; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller;   public class MessageEncoder implementsEncoder.Text<Person> {   @Override public String encode(Person object) throws EncodeException {   JAXBContext jaxbContext = null; StringWriter st = null; try { jaxbContext = JAXBContext.newInstance(Person.class);   Marshaller marshaller = jaxbContext.createMarshaller(); st = new StringWriter(); marshaller.marshal(object, st); System.out.println("OutGoing XML " + st.toString());   } catch (Exception ex) { ex.printStackTrace(); } return st.toString(); }   @Override public void init(EndpointConfig endpointConfig) { // do nothing. }   @Override public void destroy() { // do nothing. } }

为了测试这个例子,将客户端的网页稍微修改一下以便能在textarea中粘帖XML:

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 <html> <head> <meta http-equiv="content-type"content="text/html; charset=ISO-8859-1"> head>   <body> <meta charset="utf-8"> <title>HelloWorld Web socketstitle> <script language="javascript"type="text/javascript"> var wsUri = getRootUri() + "/websocket-hello/hello";   function getRootUri() { return "ws://" + (document.location.hostname == "" ? "localhost" :document.location.hostname) + ":" + (document.location.port == "" ? "8080" :document.location.port); }   function init() { output = document.getElementById("output"); }   function send_message() {   websocket = new WebSocket(wsUri); websocket.onopen = function(evt) { onOpen(evt) }; websocket.onmessage = function(evt) { onMessage(evt) }; websocket.onerror = function(evt) { onError(evt) };   }   function onOpen(evt) { writeToScreen("Connected to Endpoint!"); doSend(textID.value);   }   function onMessage(evt) { writeToScreen("Message Received: " + evt.data); }   function onError(evt) { writeToScreen('ERROR: ' + evt.data); }   function doSend(message) { writeToScreen("Message Sent: " + message); websocket.send(message); }   function writeToScreen(message) { alert(message);   }   window.addEventListener("load", init, false);   script>   <h1 style="text-align: center;">Hello World WebSocket Clienth2>   <br>   <div style="text-align: center;"> <form action=""> <input onclick="send_message()" value="Send"type="button"> <textarea id="textID" rows="4" cols="50"name="message" > textarea> form> div> <div id="output">div> body> html>

在文本框中输入下面的XML进行测试。

1 2 3 4 <person> <name>johnname> <surname>smithsurname> person>
 这篇文章是我摘自http://colobu.com/2015/02/27/WebSockets-tutorial-on-Wildfly-8/(翻译自 mastertheboss的 WebSockets tutorial on Wildfly 8)     二、轮询 前台代码:

$(document).ready(function() {
  setInterval(checkIsExist, 1000);
});

function checkIsExist() {
  var urls = "/LogForPage/getShiftCarOrderCarId.do?ajax=1";
  var htmlobj = $.ajax({
    url : urls,
    async : false
  });
  var list = eval(htmlobj.responseText);
  $("#textarea-input").html(list);
}

后台代码:

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;

import org.codehaus.jackson.map.ObjectMapper;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.aotoso.control.ConnectionManage.PortCommunication;
import com.aotoso.control.base.BaseController;
import com.aotoso.server.FirstDataManage.EverydayPlanService;


@Controller
@RequestMapping("/LogForPage")
public class LogForPage extends BaseController {
@Resource(name = "everydayPlanService")
EverydayPlanService everydayPlanService;

/**
* 时时打印上传的信息!
* @param session
* @param request
* @param response
*/
@RequestMapping(value = "/TMRInfromation")
public void getShiftCarOrderCarId(HttpServletResponse response) {
  pd = this.getPageData();
  logger.info("时时打印上传的信息!");
  ObjectMapper objectMapper = new ObjectMapper();
  try {
    objectMapper.writeValue(response.getOutputStream(),new PortCommunication().getInfo());
    System.out.println(new PortCommunication().getInfo());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}