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

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

一、WebSocket

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

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

什么是WebSocket?

一个WebSocket是通过一个独立的TCP连接实现的、异步的、双向的、全双工的消息传递实现机制。WebSockets不是一个HTTP连接,却使用HTTP来引导一个WebSocket连接。一个全双工的系统允许同时进行双向的通讯。陆地线路电话是一个全双工设施的例子,因为它们允许两个通话者同时讲话并被对方听到。最初WebSocket被提议作为HTML5规范的一部分,HTML5承诺给现代的交互式的web应用带来开发上的便利和网络效率,但是随后WebSocket被移到一个仅用来存放WebSockets规范的独立的标准文档里。它包含两件事情 -- WebSocket协议规范,即2011年12月发布的RFC 6455,和WebSocket JavaScript API。

WebSocket协议利用HTTP 升级头信息来把一个HTTP连接升级为一个WebSocket连接。HTML5 WebSockets 解决了许多导致HTTP不适合于实时应用的问题,并且它通过避免复杂的工作方式使得应用结构很简单。

最新的浏览器都支持WebSockets,

WebSocket是如何工作的?

每一个WebSocket连接的生命都是从一个HTTP请求开始的。HTTP请求跟其他请求很类似,除了它拥有一个Upgrade头信息。Upgrade头信息表示一个客户端希望把连接升级为不同的协议。对WebSockets来说,它希望升级为WebSocket协议。当客户端和服务器通过底层连接第一次握手时,WebSocket连接通过把HTTP协议转换升级为WebSockets协议而得以建立。一旦WebSocket连接成功建立,消息就可以在客户端和服务器之间进行双向发送

  • WebSockets比其它工作方式比如轮询更有效也更高效。因为它需要更少的带宽并且降低了延时。
  • WebSockets简化了实时应用的结构体系。
  • WebSockets在点到点发送消息时不需要头信息。这显著的降低了带宽。

一些可能的WebSockets使用案例有:

  • 聊天应用
  • 多人游戏
  • 股票交易和金融应用
  • 文档合作编辑
  • 社交应用

JSR 356,WebSocket的Java API,规定了开发者把WebSockets 整合进他们的应用时可以使用的Java API — 包括服务器端和Java客户端。JSR 356是Java EE 7标准中的一部分。这意味着所有Java EE 7兼容的应用服务器都将有一个遵守JSR 356标准的WebSocket协议的实现。开发者也可以在Java EE 7应用服务器之外使用JSR 356。目前Apache Tomcat 8提供了JSR 356 API的WebSocket支持。 Jboss Wildfly 8 (原JBoss Application Server)也支持JSR 356.

一个Java客户端可以使用兼容JSR 356的客户端实现,来连接到WebSocket服务器。对web客户端来说,开发者可以使用WebSocket JavaScript API来和WebSocket服务器进行通讯。WebSocket客户端和WebSocket服务器之间的区别,仅在于两者之间是通过什么方式连接起来的。一个WebSocket客户端是一个WebSocket终端,它初始化了一个到对方的连接。一个WebSocket服务器也是一个WebSocket终端,它被发布出去并且等待来自对方的连接。在客户端和服务器端都有回调监听方法 -- onOpen , onMessage , onError, onClose。

怎么创建你的第一个WebSocket应用呢?基本上我们还是会使用Javascript API编写WebSocket客户端, 在服务器端, 本文使用JSR 356规范定义的通用模式和技术处理WebSocket的通讯。

下面看一个简单的例子, 演示了如果使用JavaScript WebSocket客户端与运行在Wildfly 8服务器通信.

客户端代码


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


<html>

<head>

<meta http-equiv="content-type"content="text/html; charset=ISO-8859-1">

</head>

<body>

<meta charset="utf-8">

<title>HelloWorld Web sockets</title>

<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(‘<span style="color: red;">ERROR:</span> ‘ + evt.data);

}

function doSend(message) {

writeToScreen("Message Sent: " + message);

websocket.send(message);

}

function writeToScreen(message) {

var pre = document.createElement("p");

pre.style.wordWrap = "break-word";

pre.innerHTML = message;

output.appendChild(pre);

}

window.addEventListener("load", init, false);

</script>

<h1 style="text-align: center;">Hello World WebSocket Client</h2>

<br>

<div style="text-align: center;">

<form action="">

<input onclick="send_message()" value="Send"type="button">

<input id="textID" name="message"value="Hello WebSocket!" type="text"><br>

</form>

</div>

<div id="output"></div>

</body>

</html>

如你所见,要想使用WebSocket协议与服务器通信, 需要一个WebSocket对象。它会自动连接服务器.


1

websocket = new WebSocket(wsUri);

连接上会触发open事件:


1

2

3


websocket.onopen = function(evt) {

onOpen(evt)

};

一旦连接成功,则向服务器发送一个简单的hello消息。


1

websocket.send(message);

服务器端代码

有两种创建服务器端代码的方法:

  • 注解方式Annotation-driven: 通过在POJO加上注解, 开发者就可以处理WebSocket 生命周期事件.
  • 实现接口方式Interface-driven: 开发者可以实现Endpoint接口和声明周期的各个方法.

建议开发时采用注解方式, 这样可以使用POJO就可以实现WebSocket Endpoint. 而且不限定处理事件的方法名。 代码也更简单。

本例就采用注解的方式, 接收WebSocket请求的类是一个POJO, 通过@ServerEndpoint标注. 这个注解告诉容器此类应该被当作一个WebSocket的Endpoint。value值就是WebSocket endpoint的path.


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


package com.sample.websocket;

import javax.websocket.*;

import javax.websocket.server.ServerEndpoint;

@ServerEndpoint("/hello")

public class HelloWorldEndpoint {

@OnMessage

public String hello(String message) {

System.out.println("Received : "+ message);

return message;

}

@OnOpen

public void myOnOpen(Session session) {

System.out.println("WebSocket opened: " + session.getId());

}

@OnClose

public void myOnClose(CloseReason reason) {

System.out.println("Closing a WebSocket due to " + reason.getReasonPhrase());

}

}

注意:这个例子还包括了其它两个回调函数: @OnOpen标注的方法在WebSocket连接开始时被调用, Web Session作为参数。 另外一个@OnClose标注的方法在连接关闭时被调用。

就是这么简单。但是为了编译这个例子你还需要Websockets API的实现,它在WildFly 8发布中(或者你用JSR 356的参考实现,或其它的容器提供的jar, 如tomcat):


1

modules\system\layers\base\javax\websocket\api\main\jboss-websocket-api_1.0_spec-1.0.0.Final.jar

对于Maven用户, 你需要增加undertow-websockets-jsr依赖:


1

2

3

4

5


<dependency>

<groupId>org.jboss.spec.javax.websocket</groupId>

<artifactId>jboss-websocket-api_1.0_spec</artifactId>

<version>1.0.0.Final</version>

</dependency>

这个例子比较早,应该是2013年写的,jsr 256还未发布。 现在,你应该直接使用Java EE提供的API


1

2

3

4

5


<dependency>

<groupId>javax.websocket</groupId>

<artifactId>javax.websocket-api</artifactId>

<version>1.1</version>

</dependency>

编解码器

前面的例子中WebSocket通信的消息类型默认为String。接下来的例子演示如何使用Encoder和Decoder传输更复杂的数据。
Websocket使用Decoder将文本消息转换成Java对象,然后传给@OnMessage方法处理; 而当对象写入到session中时,Websocket将使用Encoder将Java对象转换成文本,再发送给客户端。
更常用的, 我们使用XML 或者 JSON 来传送数据,所以将会会将Java对象与XML/JSON数据相互转换.

下图描绘了客户端和服务器使用encoder/decoder标准通信过程。

声明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 sockets</title>

<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(‘<span style="color: red;">ERROR:</span> ‘ + 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 Client</h2>

<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>john</name>

<surname>smith</surname>

</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();
    }
  }
}

时间: 2024-10-20 13:25:59

如何实现后台向前台传数据的相关文章

后台给前台传JSON字符串,前台解析并拼接显示

后台传JSON 1 public class CourseType : IHttpHandler 2 { 3 Epoint.PeiXun.Bizlogic.BLL.CourseLibrary.PX_CourseType.B_PX_CourseType b_coursetype = new Epoint.PeiXun.Bizlogic.BLL.CourseLibrary.PX_CourseType.B_PX_CourseType(); 4 5 List<CourseTypeData> list_

jquery ajax后台向前台传list 前台用jquery $.each遍历list

下边是两种前台接收并遍历list $.ajax({ type: 'post', url: xxx.action', dataType: 'text', success: function(data){ var dataObj=eval("("+data+")"); for(var i=0;i<dataObj.length;i++){ alert(dataObj[i].id+" "+dataObj[i].name); } var jsonOb

Struts从后台向前台传递数据

写在前面,在action中对实例化的对象,要有get.set方法,在前台就可以通过struts标签来取得数据. -----------------------------------------------------------------------转------------------------------------------------------------- 不是action传值到jsp页面,而是jsp页面获取action中的属性值,或者范围(如request,session,

说说ajax上传数据和接收数据

我是一个脑袋不太灵光的人,所以遇到问题,厚着脸皮去请教大神的时候,害怕被大神鄙视,但是还是被鄙视了.我说自己不要点脸面,那是不可能的,但是,为了能让自己的技术生涯能走的更长远一些,受点白眼,受点嘲笑也不算什么.重在被各种鄙视之后,我学到了什么,这才是关键的.好吧,我在自我安慰.哈哈,废话不多说啦,说正题. 我一直觉得ajax是个神奇的存在,但是之前我做的都是通过ajax去接收数据,栗如: $.ajax({ type: "get", url: "https://www.baid

springMVC接收前台传的日期

当前台传数据给spring的control时,如果后台方法的参数或参数对象的对应属性是基本类型或者string类型时,前台值自动的注入到后台方法参数或对象属性中.如果方法参数或对象属性不是基本类型或string,比如是date类型,则不能直接赋值. 解决方法有一下三种: 一.使用注解 1.在springmvc配置文件中开启注解<mvc:annotation-driven /> 2.在参数或对象属性上添加注解 如:如果是date类型可以添加@DateTimeFormat(pattern = &q

mybatis前台传给带年月日时分秒的数据给后台,后台接收不到时分秒

框架spring+springMVC+mybatis, 前台给后台传数据传不了时分秒,所以用springMVC的注解解决了,记录一下 controller中如下: /**     *      * 方法描述 : 使用@InitBinder 标签对表单数据绑定     * @param binder     */    @InitBinder//spring mvc使用@InitBinder 标签对表单数据绑定    public void initBinder(WebDataBinder bin

springmvc和easyui使用ajax前台后台互传数据,假删除提示警告问题。

前台 //删除 多/单条数据 function del(cid){ var id=''; if(cid=='-1'){ if(getSelections().length > 0){ id=getSelections(); }else{ $.messager.alert("提示", "请选择要删除的行", "error"); return; } }else{ id=cid; } var arr =id.split(":"

HighCharts绘制JS折线图(后台传数据给前台基于JFinal框架)

/*****************************Controller(基于JFinal框架)**************/ package com.zzu.controller;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.List;import org.jfree.chart.ChartFactory;import org.jfree.chart.ChartUtilitie

Jquery AJAX 简单实现前台后台互传数据

AJAX是一个很强大的东西,之前写过一篇 AJAX Servlet异步交互 ,是放在请求的url上进行实现的,放在Url上长度有限,如果想保存很长的东西,例如博客这样的就不行了! 导包: 主要是json.jar这个包,其他的是ueditor的包! 前台代码:(这是部分主要的代码,省略了ueditor的代码) //引入easyui的一些插件 <link rel="stylesheet" type="text/css" href="jquery-easy