Java后端WebSocket的Tomcat实现

一.WebSocket简单介绍

随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了。近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据。

我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据;这种客户端是主动方,服务端是被动方的传统Web模式 对于信息变化不频繁的Web应用来说造成的麻烦较小,而对于涉及实时信息的Web应用却带来了很大的不便,如带有即时通信、实时数据、订阅推送等功能的应 用。在WebSocket规范提出之前,开发人员若要实现这些实时性较强的功能,经常会使用折衷的解决方法: 轮询(polling) 和 Comet 技术。其实后者本质上也是一种轮询,只不过有所改进。

轮询是最原始的实现实时Web应用的解决方案。轮询技术要求客户端以设定的时间间隔周期性地向服务端发送请求,频繁地查询是否有新的数据改动。明显地,这种方法会导致过多不必要的请求,浪费流量和服务器资源。

Comet技术  又可以分为 长轮询 和 流技术 。 长轮询 改进了上述的轮询技术,减小了无用的请求。它会为某些数据设定过期时间,当数据过期后才会向服务端发送请求;这种机制适合数据的改动不是特别频繁的情况。 流技术 通常是指客户端使用一个隐藏的窗口与服务端建立一个HTTP长连接,服务端会不断更新连接状态以保持HTTP长连接存活;这样的话,服务端就可以通过这条长连接主动将数据发送给客户端;流技术在大并发环境下,可能会考验到服务端的性能。

这两种技术都是基于请求-应答模式,都不算是真正意义上的实时技术;它们的每一次请求、应答,都浪费了一定流量在相同的头部信息上,并且开发复杂度也较大。

伴随着HTML5推出的WebSocket,真正实现了Web的实时通信,使B/S模式具备了C/S模式的实时通信能力。WebSocket的工作流程是这 样的:浏览器通过JavaScript向服务端发出建立WebSocket连接的请求,在WebSocket连接建立成功后,客户端和服务端就可以通过 TCP连接传输数据。因为WebSocket连接本质上是TCP连接,不需要每次传输都带上重复的头部数据,所以它的数据传输量比轮询和Comet技术小 了很多。本文不详细地介绍WebSocket规范,主要介绍下WebSocket在Java Web中的实现。

JavaEE 7中出了JSR-356:Java API for WebSocket规范。不少Web容器,如Tomcat,Nginx,Jetty等都支持WebSocket。Tomcat从7.0.27开始支持 WebSocket,从7.0.47开始支持JSR-356,下面的Demo代码也是需要部署在 Tomcat7.0.47  以上的版本才能运行。

客户端(Web主页)代码:

<%@ page language="java" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
  <title>Java后端WebSocket的Tomcat实现</title>
</head>
<body>
  Welcome<br/><input id="text" type="text"/>
  <button onclick="send()">发送消息</button>
  <hr/>
  <button onclick="closeWebSocket()">关闭WebSocket连接</button>
  <hr/>
  <div id="message"></div>
</body>

<script type="text/javascript">
  var websocket = null;
  //判断当前浏览器是否支持WebSocket
  if ('WebSocket' in window) {
    websocket = new WebSocket("ws://172.16.98.31:8080/websocket/websocket");
  }
  else {
    alert('当前浏览器 Not support websocket');
  }

  //连接发生错误的回调方法
  websocket.onerror = function () {
    setMessageInnerHTML("WebSocket连接发生错误");
  };

  //连接成功建立的回调方法
  websocket.onopen = function () {
    setMessageInnerHTML("WebSocket连接成功");
  }

  //接收到消息的回调方法
  websocket.onmessage = function (event) {
    setMessageInnerHTML(event.data);
  }

  //连接关闭的回调方法
  websocket.onclose = function () {
    setMessageInnerHTML("WebSocket连接关闭");
  }

  //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
  window.onbeforeunload = function () {
    closeWebSocket();
  }

  //将消息显示在网页上
  function setMessageInnerHTML(innerHTML) {
    document.getElementById('message').innerHTML += innerHTML + '<br/>';
  }

  //关闭WebSocket连接
  function closeWebSocket() {
    websocket.close();
  }

  //发送消息
  function send() {
    var message = document.getElementById('text').value;
    websocket.send(message);
  }
</script>
</html>

Java Web后端代码

package cn.com;
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;

import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;

/**
 * @ServerEndpoint 注解是一个类层次的注解,它的功能主要是将目前的类定义成一个websocket服务器端,
 * 注解的值将被用于监听用户连接的终端访问URL地址,客户端可以通过这个URL来连接到WebSocket服务器端
 * 每次请求,都会创建一个实例
 */
@ServerEndpoint("/websocket")
public class WebSocketTest {
  //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
  private static int onlineCount = 0;

  //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。若要实现服务端与单一客户端通信的话,可以使用Map来存放,其中Key可以为用户标识
  private static CopyOnWriteArraySet<WebSocketTest> webSocketSet = new CopyOnWriteArraySet<WebSocketTest>();

  //与某个客户端的连接会话,需要通过它来给客户端发送数据
  private Session session;

  /**
   * 连接建立成功调用的方法
   * @param session 可选的参数。session为与某个客户端的连接会话,需要通过它来给客户端发送数据
   */
  @OnOpen
  public void onOpen(Session session){
    this.session = session;
    webSocketSet.add(this);   //加入set中
    addOnlineCount();      //在线数加1
    System.out.println("有新连接加入!当前在线人数为" + getOnlineCount());
  }

  /**
   * 连接关闭调用的方法
   */
  @OnClose
  public void onClose(){
    webSocketSet.remove(this); //从set中删除
    subOnlineCount();      //在线数减1
    System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount());
  }

  /**
   * 收到客户端消息后调用的方法
   * @param message 客户端发送过来的消息
   * @param session 可选的参数
   */
  @OnMessage
  public void onMessage(String message, Session session) {
    System.out.println("来自客户端的消息:" + message);
    //群发消息
    for(WebSocketTest item: webSocketSet){
      try {
        item.sendMessage(message);
      } catch (IOException e) {
        e.printStackTrace();
        continue;
      }
    }
  }

  /**
   * 发生错误时调用
   * @param session
   * @param error
   */
  @OnError
  public void onError(Session session, Throwable error){
    System.out.println("发生错误");
    error.printStackTrace();
  }

  /**
   * 这个方法与上面几个方法不一样。没有用注解,是根据自己需要添加的方法。
   * @param message
   * @throws IOException
   */
  public void sendMessage(String message) throws IOException{
    this.session.getBasicRemote().sendText(message);
    //this.session.getAsyncRemote().sendText(message);
  }

  public static synchronized int getOnlineCount() {
    return onlineCount;
  }

  public static synchronized void addOnlineCount() {
    WebSocketTest.onlineCount++;
  }

  public static synchronized void subOnlineCount() {
    WebSocketTest.onlineCount--;
  }
}

打开两个浏览器,输入网址,直接运行

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • 一个Java程序猿眼中的前后端分离以及Vue.js入门(推荐)

    松哥的书里边,其实有涉及到 Vue,但是并没有详细说过,原因很简单,Vue 的资料都是中文的,把 Vue.js 官网的资料从头到尾浏览一遍该懂的基本就懂了,个人感觉这个是最好的 Vue.js 学习资料 ,因此在我的书里边就没有多说.但是最近总结小伙伴遇到的问题,感觉很多人对前后端分离开发还是两眼一抹黑,所以今天松哥想和大家聊一下前后端分离以及 Vue.js 的一点事,算是一个简单的入门科普吧. 前后端不分 后端模板:Jsp.FreeMarker.Velocity 前端模板:Thymeleaf 前

  • 详解前后端分离之Java后端

    前后端分离的思想由来已久,不妨尝试一下,从上手开始,先把代码写出来再究细节. 代码下载:https://github.com/jimolonely/AuthServer 前言 以前服务端为什么能识别用户呢?对,是session,每个session都存在服务端,浏览器每次请求都带着sessionId(就是一个字符串),于是服务器根据这个sessionId就知道是哪个用户了. 那么问题来了,用户很多时,服务器压力很大,如果采用分布式存储session,又可能会出现不同步问题,那么前后端分离就很好的解

  • Java后端产生验证码后台验证功能的实现代码

    直接跳severlet在java后台生成验证码: @RequestMapping(value="yzm.action") public void Yzm(HttpSession session,HttpServletResponse resp){ // 验证码图片的宽度. int width = 60; // 验证码图片的高度. int height = 20; // 验证码字符个数 int codeCount = 4; int x = 0; // 字体高度 int fontHeigh

  • 关于java后端的详解

    新手程序员通常会走入一个误区,就是认为学习了一门语言,就可以称为是某某语言工程师了.但事实上真的是这样吗?其实并非如此. 今天我们就来聊一聊,Java 开发工程师到底开发的是什么东西.准确点来说,Java后端到底在做什么? 大家都知道 Java 是一门后端语言,后端指的就是服务端,服务端代码一般运行在服务器上,通常我们运行Java 程序的服务器都是 Linux 服务器. 这些服务器在互联网公司中一般放在一个叫做机房的地方里,于是像我们这类 Java 程序员的代码一般也运行在这些机房里的服务器中.

  • 详解使用IntelliJ IDEA新建Java Web后端resfulAPI模板

    初始化项目 打开IntelliJ IDEA,我的版本是Version 2018.1.4.点击Create New Project.在左侧的列表中选择Maven.然后在右侧勾选Create from archetype. 然后在右侧的列表中选择org.apache.maven.archetypes:maven-archetype-webapp.点击next. 填写GroupId和ArtifactId.GroupId定义了项目属于哪个组织,例如,我们需要使用一个包,名字叫做fastjson,用户在项

  • JAVA实现JSON后端向前端传递数据

    1 后端两个辅助类 ConcurrentDateUtil.Java,用于生成我们需要格式的时间 import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class ConcurrentDateUtil { private static ThreadLocal<DateFormat> threadLo

  • Java后端WebSocket的Tomcat实现

    一.WebSocket简单介绍 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据. 我们知道,传统的HTTP协议是无状态的,每次请求(request)都要由客户端(如 浏览器)主动发起,服务端进行处理后返回response结果,而服务端很难主动向客户端发送数据:这种客户端是主动方,服务端是被动方的传统Web模式

  • Java 后端开发中Tomcat服务器运行不了的五种解决方案

    目录 方法一 方法二 方法三 方法四 方法五 方法一 查看Servers项目是否被关闭或者被删除,Servers是tomcat部署环境的配置项目,我们自己的项目能不能部署在Tomcat服务器上,Servers至关重要.观察该项目是否出于打开的状态: 方法二 查看Servers组件中的tomcat服务器中是否存在太多的被运行执行过的项目,如果存在,需要删除一些不再需要被运行的项目,保留当前需要运行的某个项目即可,因为保留太多的项目会增加tomcat服务器的运行时检索的压力,拖慢运行时间,如果其他项

  • Java后端Tomcat实现WebSocket实例教程

    一.WebSocket简单介绍 WebSocket protocol 是HTML5一种新的协议.它实现了浏览器与服务器全双工通信(full-duplex).一开始的握手需要借助HTTP请求完成握手. 随着互联网的发展,传统的HTTP协议已经很难满足Web应用日益复杂的需求了.近年来,随着HTML5的诞生,WebSocket协议被提出,它实现了浏览器与服务器的全双工通信,扩展了浏览器与服务端的通信功能,使服务端也能主动向客户端发送数据. WebSocket背景 在浏览器中通过http仅能实现单向的

  • 基于java实现websocket协议过程详解

    最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做出应答处理. 这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息. 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦.大多数 Web 应用程序将通过频繁的异步JavaScr

  • 基于java实现websocket代码示例

    最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向的应用层协议.它采用了请求/响应模型.通信请求只能由客户端发起,服务端对请求做出应答处理. 这种通信模型有一个弊端:HTTP 协议无法实现服务器主动向客户端发起消息. 这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦.大多数 Web 应用程序将通过频繁的异步JavaScr

  • java后端+前端使用WebSocket实现消息推送的详细流程

    目录 前言 创建WebSocket的简单实例操作流程 1.引入Websocket依赖 2.创建配置类WebSocketConfig 3.创建WebSocketServer 4.websocket调用 总结 前言 在项目的开发时,遇到实现服务器主动发送数据到前端页面的功能的需求.实现该功能不外乎使用轮询和websocket技术,但在考虑到实时性和资源损耗后,最后决定使用websocket.现在就记录一下用Java实现Websocket技术吧~ Java实现Websocket通常有两种方式:1.创建

  • 使用Java和WebSocket实现网页聊天室实例代码

    在没介绍正文之前,先给大家介绍下websocket的背景和原理: 背景 在浏览器中通过http仅能实现单向的通信,comet可以一定程度上模拟双向通信,但效率较低,并需要服务器有较好的支持; flash中的socket和xmlsocket可以实现真正的双向通信,通过 flex ajax bridge,可以在javascript中使用这两项功能. 可以预见,如果websocket一旦在浏览器中得到实现,将会替代上面两项技术,得到广泛的使用.面对这种状况,HTML5定义了WebSocket协议,能更

  • java 实现websocket的两种方式实例详解

    一.介绍 1.两种方式,一种使用tomcat的websocket实现,一种使用spring的websocket 2.tomcat的方式需要tomcat 7.x,JEE7的支持. 3.spring与websocket整合需要spring 4.x,并且使用了socketjs,对不支持websocket的浏览器可以模拟websocket使用 二.方式一:tomcat 使用这种方式无需别的任何配置,只需服务端一个处理类, 服务器端代码 package com.Socket; import java.io

  • Vue+Java 通过websocket实现服务器与客户端双向通信操作

    1. vue代码 methods: { //在方法里调用 this.websocketsend()发送数据给服务器 onConfirm () { //需要传输的数据 let data = { code: 1, item: '传输的数据' } this.websocketsend(JSON.stringify(data)) }, /* */ initWebSocket () { // 初始化weosocket let userinfo = getUserInfo() let username =

  • JAVA后端学习精华之网络通信项目进阶

    目录 一.网络通信解决的问题 二.计算机网络的概念 三.IP 四.域名 五.端口 六.利用telnet完成简单的网络通信 Java网络通信项目进阶 一.网络通信解决的问题 不同机器,不同程序之间的数据交换 二.计算机网络的概念 计算机网课是指将地理位置不同的具有独立功能的多台计算机及外部设备通过通信线路连接起来,在网络操作系统,网络管理软件及网络通信协议的管理和协调下,实现资源共享和信息传递的计算机系统. 三.IP ip地址:InetAddress 通过ip地址可以唯一定位一台网络上的计算机 1

随机推荐