前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【方向盘】版本历史&代码示例之:WebSocket、JSTL

【方向盘】版本历史&代码示例之:WebSocket、JSTL

作者头像
YourBatman
发布2022-11-03 16:04:11
7430
发布2022-11-03 16:04:11
举报
文章被收录于专栏:BAT的乌托邦

通透,是技术人应有的追求。 本文已被https://yourbatman.cn收录;女娲Knife-Initializr工程可公开访问啦;程序员专用网盘https://wangpan.yourbatman.cn

你好,我是方向盘(YourBatman、方哥)。笔者的公号(Java方向盘)是保留地,只分享原创,不转载、不发商务广告!!!

✍前言

若你还不太清楚Java EE是什么,可先移步这里:什么是Java EE?

紧接着上一篇讲完Servlet、JSP、EL表达式后,本文尝试把WebSocket和JSTL再疏通疏通。

在这里插入图片描述
在这里插入图片描述
所属专栏
相关下载
版本约定
  • Java EE:6、7、8
  • Jakarta EE:8、9、9.1

✍正文

在这里插入图片描述
在这里插入图片描述

WebSocket

WebSocket是一种在单个TCP连接上进行全双工通信的协议。随着HTML5的诞生,WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。

WebSocket协议本质上是一个基于TCP的协议,它由通信协议和编程API组成,WebSocket能够在浏览器和服务器之间建立双向连接,以基于事件的方式,赋予浏览器实时通信能力。

WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在WebSocket API中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。工作流程如下图:

在这里插入图片描述
在这里插入图片描述

Java API for WebSocket是Java的Web套接字,在2013年6月份伴随着Java EE 7推出(1.0版本),Java EE 8升级到1.1版本。

注意:WebSocket的Client可以是浏览器,也可是WebSocket的终端(如Java应用、Go应用)

代码语言:javascript
复制
<!-- javax命名空间版本(Tomcat 9.x及以下版本支持) -->
<dependency>
    <groupId>javax.websocket</groupId>
    <artifactId>javax.websocket-api</artifactId>
    <version>1.1</version>
    <scope>provided</scope>
</dependency>

<!-- jakarta命名空间版本(Tomcat 10.x及以上版本支持) -->
<dependency>
    <groupId>jakarta.websocket</groupId>
    <artifactId>jakarta.websocket-api</artifactId>
    <version>2.0.0</version>
    <!-- <version>1.1.2</version> 此版本命名空间同javax -->
    <scope>provided</scope>
</dependency>

除此之外,一般情况下我们直接使用Web容器提供的Jar即可,如Tomcat
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-websocket</artifactId>
    <version>Tomcat版本号</version>
</dependency>
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-websocket</artifactId>
    <version>Tomcat版本号</version>
</dependency>

✌版本历程

版本 | 发布日期 | JSR版本 | 对应Java EE版本 -------- | ----- | ----- | ----- | ----- WS 1.0 | 2013.06 | JSR 356 | Java EE 7 WS 1.1 | 2017.08 | JSR 356 | Java EE 8 WS 2.0 | 2020.11 | Jakarta管理 | Java EE 9

servlet-3.1版本开始支持。WebSocket 1.1 版与 1.0 版完全向后兼容,只在javax.websocket.Session中添加了两个方法:

代码语言:javascript
复制
<T> void addMessageHandler(Class<T> clazz, MessageHandler.Partial<T> handler) throws IllegalStateException;
<T> void addMessageHandler(Class<T> clazz, MessageHandler.Whole<T> handler) throws IllegalStateException;

✌生存现状

作为Http协议的“补充”,很好的弥补了其不足,在Web领域实时推送,也被称作Realtime技术。这种技术大大提升交互体验,拥有广泛的应用场景:在线聊天(如web版微信)、在线客服系统、评论系统等等。

总的来讲,WebSocket作为新贵,生存现状挺好,前景一片光明。

✌实现(框架)

WebSocket其实是构建在Http协议之上的,所以对于Java语言来讲它依旧由Web容器来提供实现。

概念区分:Web容器不一定是Servlet容器,而Servlet容器一定是Web容器

除此之外也有独立实现:

  • client端实现:org.eclipse.jetty.websocket:javax-websocket-client-impl
  • server端实现:org.eclipse.jetty.websocket:javax-websocket-server-impl

对于Client来讲,一般都是浏览器。

✌代码示例

前面有提到,WebSocket的Client端既可以是浏览器(现代的浏览器100%都支持此协议,若需要考虑浏览器兼容问题(比如国外现在依旧有使用老版IE浏览器的),可以使用socketio框架哈),也可以是Java应用。本示例就加点“难度”,用Java应用作为WebSocket的客户端。当然喽,服务端肯定也是Java应用呀。

创建demo项目,结构如下:

在这里插入图片描述
在这里插入图片描述

其中client为jar,server为war。

书写Server端代码,提供一个服务端点:

代码语言:javascript
复制
/**
 * 在此处添加备注信息
 *
 * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a>
 * @site https://yourbatman.cn
 * @date 2021/9/12 15:29
 * @since 0.0.1
 */
@ServerEndpoint("/websocket/chat")
public class WsServer {

    // 当前连接上来的连接们(每一个连接都是一个WsServerDemo实例,包含一个Session会话)
    private static Set<WsServer> webSocketSet = new CopyOnWriteArraySet<>();
    // 会话
    private Session session;

    /**
     * 建连成功的回调
     */
    @OnOpen
    public void onOpen(Session session) {
        this.session = session;
        webSocketSet.add(this); // 保存当前连接
        System.out.println("Server有新连接加入!当前在线人数为" + webSocketSet.size());
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        webSocketSet.remove(this);
        System.out.println("Server有一连接关闭!当前在线人数为" + webSocketSet.size());
    }

    /**
     * 收到客户端消息后调用的方法
     */
    @OnMessage
    public void onMessage(String message) throws IOException {
        System.out.println("Server来自客户端的消息:" + message);
        sendMessage("会话[" + session.getId() + "]的消息已经收到,内容为:" + message);
        // // =======群发消息=========
        // for (WsServerDemo item : webSocketSet) {
        //     try {
        //         item.sendMessage(message);
        //     } catch (IOException e) {
        //         continue;
        //     }
        // }
    }

    /**
     * 发生错误时调用
     */
    @OnError
    public void onError(Throwable error) {
        System.out.println("Server发生错误:" + error.getMessage());
    }

    /**
     * 发送消息
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }

}

我这里简便起见,使用web容器直接实现。有兴趣/想深究websocket的同学,可使用org.eclipse.jetty.websocket:javax-websocket-server-impl通过API方式去启动Server,本文只演示用该方式启动client哈,二者兼顾嘛。

使用编程方式书写client端代码:

代码语言:javascript
复制
/**
 * 在此处添加备注信息
 *
 * @author YourBatman. <a href=mailto:yourbatman@aliyun.com>Send email to me</a>
 * @site https://yourbatman.cn
 * @date 2021/9/12 15:31
 * @since 0.0.1
 */
@ClientEndpoint
public class WsClient {

    // 会话(与服务端建立的会话)
    private Session session;

    /**
     * 建连成功的回调
     */
    @OnOpen
    public void onOpen(Session session) throws IOException {
        this.session = session;
        System.out.println("Client连接到服务端成功,会话ID:" + session.getId());
        sendMessage("这是一条来自Client端,会话["+session.getId()+"]的消息");
    }

    @OnMessage
    public void onMessage(String message) {
        System.out.println("Client端收到消息: " + message);
    }

    @OnClose
    public void onClose() {
        System.out.println("Client会话" + session.getId() + "已断开");
    }

    /**
     * 发送消息
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
}

用main方法启动Client端,去连接Server端并发送消息:

代码语言:javascript
复制
public class ClientApp {

    private static URI uri = URI.create("ws://localhost:8080/websocket/chat");
    private static Session session;

    public static void main(String[] args) throws DeploymentException, IOException, InterruptedException {
        WebSocketContainer container = ContainerProvider.getWebSocketContainer();

        // 顺序执行5次会话,端口后再建立新会话
        for (int i = 0; i < 5; i++) {
            session = container.connectToServer(WsClient.class, uri);
            session.close();
            TimeUnit.SECONDS.sleep(2);
        }
    }
}

client端控制台日志:

代码语言:javascript
复制
Client连接到服务端成功,会话ID:1
Client端收到消息: 会话[0]的消息已经收到,内容为:这是一条来自Client端,会话[1]的消息
Client会话1已断开
Client连接到服务端成功,会话ID:2
Client端收到消息: 会话[1]的消息已经收到,内容为:这是一条来自Client端,会话[2]的消息
Client会话2已断开
Client连接到服务端成功,会话ID:3
Client端收到消息: 会话[2]的消息已经收到,内容为:这是一条来自Client端,会话[3]的消息
Client会话3已...

server端控制台日志:

代码语言:javascript
复制
Server有新连接加入!当前在线人数为1
Server来自客户端的消息:这是一条来自Client端,会话[1]的消息
Server有一连接关闭!当前在线人数为0
Server有新连接加入!当前在线人数为1
Server来自客户端的消息:这是一条来自Client端,会话[2]的消息
Server有一连接关闭!当前在线人数为0
Server有新连接加入!当前在线人数为1
Server来自客户端的消息:这是一条来自Client端,会话[3]的消息
Server有一连接关闭!当前在线人数为0

说明:本文特意使用Java应用作为Client端是想让你更深刻的理解WebSocket的用法,实际场景中,其实大都是B/S模式,通过JavaScript作为客户端建立连接(相对简单)。

工程源代码https://github.com/yourbatman/FXP-java-ee

JSTL

Java server pages standarded tag library,即JSP标准标签库。主要提供给Java Web开发人员一个标准通用的标签库,开发人员可以利用这些标签取代 JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度。

JSTL强依赖于JSP的存在而存在。

JSTL和EL表达式的目的是一样的:取代JSP页面上写Java代码。它比EL更为强大些,可以完成一些结构化逻辑任务,如:迭代、条件判断、XML文档操作、国际化、SQL等,下面简要介绍其主要标签。

  • 核心标签:也是著名C标签。在JSP文件开头引入c标签<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>,支持的常用函数有:
代码语言:javascript
复制
1. <c:out>:用于在页面输出
	- <c:out value="expression" default="expression" escapeXml="boolean"/>
2. <c:if>:逻辑判断
	- <c:if test="expression" var="name" scope="scope">  
	      body content  
	  </c:if>
3. <c:choose>:逻辑判断。when和otherwise的父标签
4. <c:when>: <c:otherwise>:
	- <c:choose>  
	    <c:when test="expression">  
	        body content  
	    </c:when>  
		...
	    <c:otherwise>  
		    body content  
		</c:otherwise>  
	  </c:choose>
	
5. <c:foreach>:
	- <c:forEach var="name" items="expression" varStatus="name" begin="expression" end="expression" step="expression">  
	      body content  
	  </c:forEach>

6. <c:url>:使用可选的查询参数创造一个URL地址
7. <c:set>:设置数据
8. <c:remove>:删除数据
  • 格式化标签:可对数字、日期时间等格式化。<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>,主要函数:
代码语言:javascript
复制
1. <fmt:formatNumber>:格式化数字
2. <fmt:parseNumber>:解析字符串到数字、货币、百分比
3. <fmt:formatDate>:
4. <fmt:parseData>:
  • JSTL函数:一般用于辅助标签控制行为。<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>,主要函数:
代码语言:javascript
复制
1. fn:contains:判断字符串是否包含另外一个字符串	
	- <c:if test="${fn:contains(name, searchString)}">
2. fn:indexOf:子字符串在母字符串中出现的位置	
	- ${fn:indexOf(name, '-')}
3. fn:toLowerCase:转为小写
	- ${fn.toLowerCase(product.name)}
  • SQL标签,<%@ taglib prefix="sql" uri="http://java.sun.com/jsp/jstl/sql" %>。主要函数:
代码语言:javascript
复制
1. <sql:setDataSource>、<sql:query>、<sql:update>
  • XML标签,<%@ taglib prefix="x" uri="http://java.sun.com/jsp/jstl/xml" %>。主要函数:
代码语言:javascript
复制
1. <x:parse>、<x:if>、<x:forEach>

除此之外,还提供了扩展点:自定义标签

代码语言:javascript
复制
<!-- javax命名空间版本(Tomcat 9.x及以下版本支持) -->
<dependency>
    <groupId>javax.servlet.jsp.jstl</groupId>
    <artifactId>jstl-api</artifactId>
    <version>1.2</version>
</dependency>

<!-- jakarta命名空间版本(Tomcat 10.x及以上版本支持) -->
<dependency>
    <groupId>jakarta.servlet.jsp.jstl</groupId>
    <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
    <version>2.0.0</version>
    <!-- <version>1.2.7</version> 此版本命名空间同javax -->
</dependency>

说明:之前可能需要有jstl.jar和standard.jar两个Jar,但从1.2版本后这一个GAV即可。当然喽,99.99%情况下该jar无需你导入,由web容器负责

✌版本历程

JSTL也依赖于JSP而存在,所以和JSP版本有强关系。

版本

发布日期

JSR版本

对应JSP版本

对应Servlet版本

JSTL 1.0

2002.07

JSR 52

JSP 1.2

Servlet 2.3

JSTL 1.1

2003.11

JSR 52

JSP 2.0

Servlet 2.4

JSTL 1.2

2006.05

JSR 52

JSP 2.1

Servlet 2.5

JSTL 2.0

2020.11

Jakarta管理

JSP 3.0

Servlet 5.0

JSTL 1.2版本可断定是最后一个版本,因为JSP已走到尽头,所以它也会随之消亡。

✌生存现状

同JSP。

✌实现(框架)

与Servlet相同的Web容器,由Web容器提供解析能力。如tomcat的标签库实现:http://tomcat.apache.org/taglibs

✌代码示例

实在没有应用场景了,略。

工程源代码https://github.com/yourbatman/FXP-java-ee

✍总结

WebSocket作为长连接的轻量级解决方案,会是B/S的新宠,一举替掉之前的长轮训等方案。滚滚长江东逝水,这或许就印证着技术在进步,时代在发展。

作为老一辈程序员的我,对EL表达式、JSTL这类技术依旧有记忆存留,但新时代的程序员可能没有必要再接触。本文就当做自留地,封存这段学习的记忆吧。

本专栏文章

我是方向盘(YourBatman):前25年不会写Hallo World、早已毕业的大龄程序员。高中时期《梦幻西游》骨灰玩家,网瘾失足、清考、延期毕业、房产中介、保险销售、送外卖…是我不可抹灭的黑标签

  • 🎓2013.07 清考、毕业答辩3次未通过、延期毕业
  • 🏷2013.08-2014.07 宁夏中介公司卖二手房1年,毕业后第1份工作
  • ️️🏷2014.07-2015.05 荆州/武汉,泰康人寿卖保险3月、饿了么送外卖2月,还有炸鸡排、直销等第2345份工作
  • 🏷2015.08 开始从事Java开发,闯过外包,呆过大厂!擅长抽象思维,任基础架构团队负责人
  • 🏷2021.08 因“双减政策”失业!历经9面,终获美团外卖L8的offer
  • 🙅🏻‍♀️Java架构师、Spring开源贡献者、CSDN博客之星年度Top 10、领域建模专家、写作大赛1/2届评委
  • 📚高质量代码、规范践行者;DDD领域驱动深度实践;即将出版书籍《Spring奇淫巧技》

序号

专栏名称

简介

01

【方向盘】-程序人生

程序人生,人生程序

02

【方向盘】-资讯/新特性

IDEA、JDK、Spring技术栈…新特性

03

【方向盘】-IntelliJ IDEA

熟练使用IDEA就相当拥有物理外挂,助你高效编码

04

【方向盘】-Bean Validation

熟练掌握数据校验,减少90%的垃圾代码

05

【方向盘】-日期时间

帮你解决JDK Date、JSR 310日期/其实 的一切问题

06

【方向盘】-Spring类型转换

Spring类型转换-框架设计的基石

07

【方向盘】-Spring static

static关键字在Spring里的应用

08

【方向盘】-Cors跨域

关于跨域请求问题,本专栏足矣

09

【方向盘】-Jackson

Almost Maybe是最好的Jackson专栏

10

【方向盘】-Spring配置类

专讲@Configuration配置类,你懂的

11

【方向盘】-Spring技术栈

暂无所属小分类的,Spring技术栈大分类

12

【方向盘】-JDK

暂无所属小分类的,JDK技术栈大分类

13

【方向盘】-Servlet

Servlet规范、Web相关内容专题

14

【方向盘】-Java EE

从Java EE到Jakarta EE,30年弹指一挥间

15

【方向盘】-工具/提效

开发工具、软件工具,目标是提效

16

【方向盘】-Spring技术栈新特性

Spring Framework、Spring Boot、Spring Cloud、Spring其它技术

17

【方向盘】-基本功

每个Javaer,都需要有扎实的基本功

99

源代码库

大多数专栏均配有源代码,都在这里

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-10-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ✍前言
  • ✍正文
    • WebSocket
      • ✌版本历程
      • ✌生存现状
      • ✌实现(框架)
      • ✌代码示例
    • JSTL
      • ✌版本历程
      • ✌生存现状
      • ✌实现(框架)
      • ✌代码示例
  • ✍总结
    • 本专栏文章
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档