文档章节

学习WebSocket(三) — 发送和接收Java对象

XuePeng77
 XuePeng77
发布于 2016/11/09 19:01
字数 1027
阅读 70
收藏 1

被@OnMessage修饰的函数是用来接收和返回客户端发送过来的消息的,接收的参数和返回值可以为Java对象。

    要使@OnMessage修饰的函数可以处理Java对象,需要对端点类设置decoders和encoders,其中decoders类需要实现接口javax.websocket.Decoder.Text<User>,而encoders类需要实现接口javax.websocket.Encoder.Text<User>,下面是具体例子:

    1.点击连接按钮与服务端连接;

    2.点击发送按钮发送一个json对象到服务端;

    3.服务端返回一个java对象的json字符串到客户端;

    4.关闭与服务端的连接;

pom文件

<dependencies>
		<!-- servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.0.1</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax/javaee-api -->
		<dependency>
			<groupId>javax</groupId>
			<artifactId>javaee-api</artifactId>
			<version>7.0</version>
		</dependency>

		<!-- https://mvnrepository.com/artifact/javax.websocket/javax.websocket-api -->
		<dependency>
			<groupId>javax.websocket</groupId>
			<artifactId>javax.websocket-api</artifactId>
			<version>1.0</version>
			<scope>provided</scope>
		</dependency>

		<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>fastjson</artifactId>
			<version>1.2.20</version>
		</dependency>


	</dependencies>

实体类

    实体类是一个POJO对象,叫User,具有两个属性Id和Name,下面是实体类的代码:

package cn.net.bysoft.websocketapp.lesson3;

public class User implements java.io.Serializable {
	
	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

}

转换类

    转换类有两个,分别是UserDecoder和UserEncoder。

    注意:UserDecoder类中,有一个willDecode方法,该方法优先于decode被调用。这是为了使你有一个跳过解码消息的机会。

    下面是具体代码:

package cn.net.bysoft.websocketapp.lesson3;

import javax.websocket.DecodeException;
import javax.websocket.EndpointConfig;

import com.alibaba.fastjson.JSON;

public class UserDecoder implements javax.websocket.Decoder.Text<User> {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void init(EndpointConfig arg0) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public User decode(String user) throws DecodeException {
		return JSON.parseObject(user, User.class);
	}

	@Override
	public boolean willDecode(String arg0) {
		return true;
	}

}
package cn.net.bysoft.websocketapp.lesson3;

import javax.websocket.EncodeException;
import javax.websocket.EndpointConfig;

import com.alibaba.fastjson.JSON;

public class UserEncoder implements javax.websocket.Encoder.Text<User> {

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void init(EndpointConfig arg0) {
		// TODO Auto-generated method stub

	}

	@Override
	public String encode(User user) throws EncodeException {
		return JSON.toJSONString(user);
	}

}

 

服务端端点代码

    在@ServerEndpoint中指定了decoders和encoders,具体代码如下:

package cn.net.bysoft.websocketapp.lesson3;

import java.io.IOException;

import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

@ServerEndpoint(value = "/objecthandle", decoders = { UserDecoder.class }, encoders = { UserEncoder.class })
public class ObjectHandle {

	private Session ws_session;

	@OnOpen
	public void onOpen(Session ws_session) {
		// 设置session,并记录建立连接时间
		this.ws_session = ws_session;
		// 通知客户端连接成功
		this.sendMessage("success:opened.");
	}

	@OnMessage
	public User onMessage(User user) {
                // 做点处理返回给客户端
		user.setName("yes, jack");
		return user;
	}

	@OnError
	public void onError(Throwable t) {
		// 发生异常时,如果连接还是打开状态,则通知客户端错误信息
		if (ws_session.isOpen()) {
			this.sendMessage("warning:Error:" + t.getMessage());
		}
	}

	@OnClose
	public void onClose() {
		// 关闭连接时,需要做的事情在该函数内完成,例如关闭数据库连接等
	}

	private void sendMessage(String message) {
		try {
			// 以同步的方式向客户端发送消息
			ws_session.getBasicRemote().sendText(message);
		} catch (IOException e) {
			System.out.println("Method: sendMessage, Error closeing session " + e.getMessage());
		}
	}
}

客户端代码

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<!-- 新 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet"
	href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap.min.css">
<!-- 可选的Bootstrap主题文件(一般不用引入) -->
<link rel="stylesheet"
	href="http://cdn.bootcss.com/bootstrap/3.3.0/css/bootstrap-theme.min.css">
<!-- jQuery文件。务必在bootstrap.min.js 之前引入 -->
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<!-- 最新的 Bootstrap 核心 JavaScript 文件 -->
<script src="http://cdn.bootcss.com/bootstrap/3.3.0/js/bootstrap.min.js"></script>
</head>
<body>
	<div class="container">
		<h1>WebSocket发送JAVA对象</h1>
		<div class="row">

			<div class="col-md-12">
				<p>
					<button type="button" class="btn btn-primary"
						onclick="open_connection()">打开连接</button>
					<button type="button" class="btn btn-danger"
						onclick="closeClient()">关闭连接</button>
				</p>
			</div>
		</div>
		<div class="row">
			<form class="form-inline" role="form">
				<div class="col-md-12">
					<div class="form-group">
						<div class="input-group">
							<div class="input-group">
								<span class="input-group-addon"><span
									class="glyphicon glyphicon-send"></span></span> 
								<input id="txtMessage" value="{id:1, name: jack}" readonly="readonly"
									type="text" class="form-control" placeholder="Send Message">
							</div>
							<button type="button" class="btn btn-info"
								onclick="messageClick()">发送消息</button>
						</div>
					</div>
				</div>
			</form>
		</div>
		<div class="row">
			<div class="col-md-12">
				<p id="output">
					<br>
				</p>
			</div>
		</div>
	</div>
</body>
<script>
	var lifecycle_websocket = null;

	function init() {
		output = document.getElementById("output");
	}
	
	function dispose() {
		lifecycle_websocket.close();
		lifecycle_websocket = null;
	}

	function open_connection() {
		if (lifecycle_websocket == null) {
			lifecycle_websocket = new WebSocket(
					"ws://localhost:8080/websocketapp/objecthandle");

			lifecycle_websocket.onmessage = function(evt) {
				displayMessage(evt.data);
			}
			lifecycle_websocket.onclose = function(evt) {
				displayMessage(evt.data);
			}
			lifecycle_websocket.onerror = function(evt) {
				displayMessage(evt.data);
			}
		}
	}

	function messageClick() {
		var user = {
			id: 1,
			name: "jack"
		}
		send_message(JSON.stringify(user));
	}

	function closeClient() {
		lifecycle_websocket.close();
		displayMessage("danger:client closed.")
	}

	function send_message(message) {
		lifecycle_websocket.send(message);
	}

	function displayMessage(message) {
		var pre = document.createElement("p");
		if(message.indexOf('{') == 0) {
			// 调用bootstrap样式
			pre.className = "text-info";
			pre.innerHTML = message;
			output.appendChild(pre);
		}
		else {
			var flag = message.substring(0, message.indexOf(':'));
			var data = message.substring(message.indexOf(':') + 1);

			// 调用bootstrap样式
			pre.className = "text-" + flag;
			pre.innerHTML = data;
			output.appendChild(pre);
		}
	}

	window.addEventListener("load", init, false);
	window.addEventListener("unload", dispose, false);
</script>
</html>

 

© 著作权归作者所有

XuePeng77
粉丝 45
博文 145
码字总数 193294
作品 0
丰台
私信 提问
加载中

评论(1)

w
wahahachuang4
web实时推送技术使用越来越广泛,但是自己开发又太麻烦了,我觉得没有那个必要,GoEasy就挺不错的,服务器稳定,代码简洁易懂;官网: http://goeasy.io/
spring boot websocket stomp 实现广播通信和一对一通信聊天

一、前言 玩.net的时候,在asp.net下有一个叫 SignalR 的框架,可以在ASP .NET的Web项目中实现实时通信。刚接触java寻找先关替代品,发现 java 体系中有一套基于stomp协议的websocket通信的框...

ejiyuan
2018/07/11
0
0
实时通信技术之websocket

本文章即从4个方面带大家了解websocket: websocket是什么? 为什么需要 WebSocket ? websocket的优点与缺点? websocket的相关使用(客户端与服务器端)? websocket的相关协议与规范? 一...

一看就喷亏的小猿
2018/11/03
0
0
Spray.io搭建Rest — 支持WebSocket

Spray.io尝试 使用Spray.io搭建Rest服务 Spray.io搭建Rest — 支持Twirl模板并部署 Spray.io搭建Rest — 支持WebSocket Spray.io搭建Rest — 支持WebSocket 工程地址:http://git.oschina.ne...

ForEleven
2014/04/30
0
3
Java EE HTML5 WebSocket 示例

在这个教程中,我们将借助于Java EE websocket的实现(服务器端)来实现HTML5 的 websocket。 1.介绍 HTML5规范带来了使用websocket标准服务让浏览器建立全双工TCP链接的能力。 换言之,浏览...

oschina
2013/08/14
112.8K
64
(websocket)协议中Ping Pong,长连接

- websocket协议,长连接;Http短连接 WebSocket如何建立连接、交换数据的细节,以及数据帧的格式。 WebSocket复用了HTTP的握手通道。具体指的是,客户端通过HTTP请求与WebSocket服务端协商升...

desaco
2018/12/25
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Cloud中Hystrix 线程隔离导致ThreadLocal数据丢失

在Spring Cloud中我们用Hystrix来实现断路器,Zuul中默认是用信号量(Hystrix默认是线程)来进行隔离的,我们可以通过配置使用线程方式隔离。 在使用线程隔离的时候,有个问题是必须要解决的...

xiaomin0322
38分钟前
2
0
使用 Jenkins + Ansible 实现 Spring Boot 自动化部署101

本文首发于:Jenkins 中文社区 本文要点: 设计一条 Spring Boot 最基本的流水线:包括构建、制品上传、部署。 使用 Docker 容器运行构建逻辑。 自动化整个实验环境:包括 Jenkins 的配置,J...

Jenkins中文社区
43分钟前
2
0
springcloud配置中心和消息总线,学习,记录其中的问题

改造配置中心的客户端,接入消息总线 1.增加pom文件的引用 <?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20......

夜中孤影
55分钟前
3
0
gzip压缩

tar -zcvf gz包路径 被压缩的路径 tar -zcvf /home/xxx/test.tar.gz hello gz包的路径可以是 完整的也可以相对 , 被压缩的路径 不要全路径 不然压缩包里也会有全路径...

shzwork
今天
3
0
rancher-1

部署rancher 官方快速部署 https://www.cnrancher.com/quick-start/ 部署命令 mkdir /data/rancher -p# 建立存放rancher数据的目录sudo docker run -d --restart=unless-stopped -v /dat......

以谁为师
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部