站长网 语言 版本历史代码范例之 WebSocket、JSTL

版本历史代码范例之 WebSocket、JSTL

前言 你好,我是方同学(YourBatman) 若你还不太清楚Java EE是什么,可先移步这里:什么是Java EE? 紧接着上一篇讲完Servlet、JSP、EL表达式后,本文尝试把WebSocket和JSTL再疏通疏通。 所属专栏 BATutopia-Java EE 相关下载 工程源代码:https://github.com

前言
你好,我是方同学(YourBatman)
 
若你还不太清楚Java EE是什么,可先移步这里:什么是Java EE?
 
紧接着上一篇讲完Servlet、JSP、EL表达式后,本文尝试把WebSocket和JSTL再疏通疏通。
 
 
 
所属专栏
BATutopia-Java EE
 
相关下载
工程源代码:https://github.com/yourbatman/BATutopia-java-ee
【女娲Knife-Initializr工程】访问地址:http://152.136.106.14:8761
Java开发软件包(Mac):https://wangpan.yourbatman.cn/s/rEH0 提取码:javakit
程序员专用网盘上线啦,开放注册送1G超小容量,帮你实践做减法:https://wangpan.yourbatman.cn
版本约定
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应用)。
 
 
<!– 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>
版本历程
 
 
servlet-3.1版本开始支持。WebSocket 1.1 版与 1.0 版完全向后兼容,只在javax.websocket.Session中添加了两个方法:
 
 
<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端代码,提供一个服务端点:
 
 
/**
 * 在此处添加备注信息
 *
 * @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端代码:
 
/**
 * 在此处添加备注信息
 *
 * @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端并发送消息:
 
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端控制台日志:
 
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端控制台日志:
 
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/BATutopia-java-ee
 
JSTL
Java server pages standarded tag library,即JSP标准标签库。主要提供给Java Web开发人员一个标准通用的标签库,开发人员可以利用这些标签取代 JSP页面上的Java代码,从而提高程序的可读性,降低程序的维护难度。
 
JSTL强依赖于JSP的存在而存在。
 
JSTL和EL表达式的目的是一样的:取代JSP页面上写Java代码。它比EL更为强大些,可以完成一些结构化逻辑任务,如:迭代、条件判断、XML文档操作、国际化、SQL等,下面简要介绍其主要标签。

本文来自网络,不代表站长网立场,转载请注明出处:https://www.tzzz.com.cn/html/biancheng/yuyan/2021/1105/20291.html

作者: dawei

【声明】:站长网内容转载自互联网,其相关言论仅代表作者个人观点绝非权威,不代表本站立场。如您发现内容存在版权问题,请提交相关链接至邮箱:bqsm@foxmail.com,我们将及时予以处理。
联系我们

联系我们

0577-28828765

在线咨询: QQ交谈

邮箱: xwei067@foxmail.com

工作时间:周一至周五,9:00-17:30,节假日休息

返回顶部