html5_websocket_tomcat8
目录
前言
后端
浏览器前端
java的client
注意
前言
HTML5 WebSocket实现了服务器与浏览器的双向通讯,开销小,实时性高,常用于即时通讯和对信息实时性要求比较高的应用。
下面讲解如利用Tomcat8+WebSocket开发聊天室。
目前Spring已经推出了WebSocket的API,能够兼容各个服务器的实现
后端
说明
@ServerEndpoint("/echo") 的 annotation 注释端点表示将 WebSocket 服务端运行在 ws://[Server 端 IP 或域名]:[Server 端口]/websockets/echo 的访问端点,客户端浏览器已经可以对 WebSocket 客户端 API 发起 HTTP 长连接了。使用 ServerEndpoint 注释的类必须有一个公共的无参数构造函数,
@onMessage 注解的 Java 方法用于接收传入的 WebSocket 信息,这个信息可以是文本格式,可以是json数据,也可以是二进制格式。
@OnOpen 在这个端点一个新的连接建立时被调用。参数提供了连接的另一端的更多细节。Session 表明两个 WebSocket 端点对话连接的另一端,可以理解为类似 HTTPSession 的概念。
@OnClose 在连接被终止时调用。参数 closeReason 可封装更多细节,如为什么一个 WebSocket 连接关闭。
@Message 注释,MaxMessageSize 属性可以被用来定义消息字节最大限制,在示例程序中,如果超过 6 个字节的信息被接收,就报告错误和连接关闭。
ChatServer.java
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
//该注解用来指定一个URI,客户端可以通过这个URI来连接到WebSocket。类似Servlet的注解mapping。无需在web.xml中配置。
@ServerEndpoint("/ws/chat/{nickName}")
public class ChatServer {
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
private static CopyOnWriteArraySet<ChatServer> webSocketSet = new CopyOnWriteArraySet<ChatServer>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
private String nickName;
/**
* 连接建立成功调用的方法
* @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
*/
@OnOpen
public void onOpen(Session session, @PathParam(value = "nickName") String nickName){
this.session = session;
this.nickName = nickName;
webSocketSet.add(this); //加入set中
String message = String.format("System> %s %s", this.nickName, " 加入.");
broadCast(message);
addOnlineCount(); //在线数加1
System.out.println(nickName+"新加入!当前在线人数为" + getOnlineCount());
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose(){
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
String message = String.format("System> %s, %s", this.nickName, " 离开.");
broadCast(message);
System.out.println(this.nickName+"离开!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
* @param message 客户端发送过来的消息
* @param session 可选的参数
*/
@OnMessage
public void onMessage(String message, Session session, @PathParam(value = "nickName") String nickName) {
System.out.println(nickName+":" + message);
broadCast(nickName + ">" + message);
}
/**
* 发生错误时调用
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable throwable) {
System.out.println("发生错误");
System.out.println(throwable.getMessage());
}
/**
* 发送或广播信息
* @param message
*/
private void broadCast(String message) {
//群发消息
for (ChatServer chat : webSocketSet) {
try {
synchronized (chat) {
chat.session.getBasicRemote().sendText(message);
}
} catch (IOException e) {
webSocketSet.remove(chat);
try {
chat.session.close();
} catch (IOException e1) {
}
broadCast(String.format(" %s %s", chat.nickName, " has bean disconnection."));
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
ChatServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
ChatServer.onlineCount--;
}
}
前端
chat.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <% String path =request.getContextPath(); String basePath =
request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + path + "/"; String nickName=request.getParameter("nickName"); %> <!DOCTYPE HTML> <html> <head> <base href="<%=basePath%>"> <title>My WebSocket</title> </head> <body> Welcome <br /> <div id="message"></div> <input id="text" type="text" /> <button onclick="send()">Send</button> <button onclick="closeWebSocket()">Close</button> </body> <script type="text/javascript"> var websocket = null; //判断当前浏览器是否支持WebSocket if ('WebSocket'in window) { websocket = new
WebSocket("ws://localhost:8080/webSocket/ws/chat/<%=nickName%>"); } else { alert('Not support websocket') } //连接发生错误的回调方法 websocket.onerror = function() { setMessageInnerHTML("error"); }; //连接成功建立的回调方法 websocket.onopen = function(event) { setMessageInnerHTML("open"); } //接收到消息的回调方法 websocket.onmessage = function() { setMessageInnerHTML(event.data); } //连接关闭的回调方法 websocket.onclose = function() { setMessageInnerHTML("close"); } //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。 window.onbeforeunload = function() { websocket.close(); } //将消息显示在网页上 function setMessageInnerHTML(innerHTML) { document.getElementById('message').innerHTML += innerHTML + '<br/>'; } //关闭连接 function closeWebSocket() { websocket.close(); } //发送消息 function send() { var message =
document.getElementById('text').value; websocket.send(message); } </script> </html>
访问
http://127.0.0.1:8080/webSocket/chat.jsp?nickName=dengzy
http://127.0.0.1:8080/webSocket/chat.jsp?nickName=dengbw
java的client
java_websocket.
import java.net.URI;
import
java.net.URISyntaxException;
import java.util.Scanner;
import
org.java_websocket.client.WebSocketClient;
import
org.java_websocket.drafts.Draft_17;
import
org.java_websocket.handshake.ServerHandshake;
publicclass TestTocatWebSocket
{
publicstaticvoid main(String[] args) throws URISyntaxException
{
String url = "ws://localhost:8080/webSocket/ws/chat/"+ args[0] ;//
WebSocketClient
wc = new WebSocketClient(new URI(url), new Draft_17()) {
@Override
publicvoid
onOpen(ServerHandshake handshakedata) {
System.out.println(handshakedata.getHttpStatusMessage());
}
@Override
publicvoid onMessage(String message) {
System.out.println(message);
}
@Override
publicvoid onError(Exception ex) {
}
@Override
publicvoid onClose(intcode, String reason, booleanremote) {
}
};
wc.connect();
while (true) {
Scanner scanner = new Scanner(System.in);
String message = scanner.nextLine();
if (message.equals("q")) {
wc.close();
break;
}
scanner.close();
wc.send(message);
}
}
}
注意
1.在部署完成之后需要将在tomcat应用目录中的lib目录下的catalina.jar和tomcat-coyote.jar删掉,比如项目的lib目录在D:\workspace\WebSocket\WebRoot\WEB-INF\lib,而部署的应用lib目录是在D:\tools\apache-tomcat-7.0.32\webapps\WebSocket\WEB-INF\lib,删掉部署目录的lib目录中连两个jar就可以了,否则会包Could not initialize class com.ibcio.WebSocketMessageServlet错误。
2.Tomcat8安装包里有WebSocket的demo
3.html5 才支持WebSocket
html5_websocket_tomcat8的更多相关文章
随机推荐
- 去掉Chrome手机版首屏的“推荐的文章”
百度可得很多类似的文章,然而都是失效的,,比如此文,本文演示所使用的Chrome版本为59. 百度所得的解决办法都是同一个,排版,截图都是一样的,害我浪费了不少力气. 第一,转载文章未标明文章出处: ...
- Web目录全能扫描工具DirBuster
Web目录全能扫描工具DirBuster Kali Linux提供的目录扫描工具DirBuster支持全部的Web目录扫描方式.它既支持网页爬虫方式扫描,也支持基于字典暴力扫描,还支持纯暴力扫描. ...
- 微信小程序开发教程(二)创建第一个微信小程序
在安装完“微信Web开发者工具”之后,通过开发者的微信扫码进入后,如图. 点击“添加项目”,填入之前获得的AppID(无AppID可忽略),输入项目名称“Hello WXapplet”,选定本地文件夹 ...
- [Codeforces 19E] Fiary
Brief Intro: 给定一个无向图,询问删去哪条边能使得剩下的图为一个二分图,输出所有结果 Algorithm: 关于二分图的重要性质:一个图为二分图的充要条件为其中没有奇环 1.如果没有奇环, ...
- 【莫队算法】【权值分块】bzoj2223 [Coci 2009]PATULJCI
不带修改主席树裸题<=>莫队+权值分块裸题. 复杂度O(m*sqrt(n)). P.S.题目描述坑爹,第二个数是权值的范围. #include<cstdio> #include ...
- java源码阅读Object
1 类注释 Class {@code Object} is the root of the class hierarchy. Every class has {@code Object} as a s ...
- Spring中@Value用法收集
一.配置方式 @Value需要参数,这里参数可以是两种形式: @Value("#{configProperties['t1.msgname']}") 或者 @Value(" ...
- hdu 1054 Strategic Game(tree dp)
Strategic Game Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...
- 获取XIB子视图的两个方法
创建了一个XIB文件 CommentCell.xib,并设置好UIImageView的tag为100,昵称UILabel的tag为101,时间的UILabel的tag为102,并制定cell为Comm ...
- Virtualbox环境中安装Oracle 11gr2 RAC(ASM)
系统Oracle Linux 6.5,Oracle 11.2.0.1 终于开始安装ASM和RAC的行程了.开始前需要想清楚的几个事情: 如何规划网络配置(配置多网卡,实现连通性,规划内外网,eth0, ...