java websocket @ServerEndpoint注解说明

摘要:
公共类<configurationr()默认ServerEndpointConfig.configurator.class;编码器输入java对象;然后输出java对象编码器代码;/***配置WebSocket解码器;

http://www.blogjava.net/qbna350816/archive/2016/07/24/431302.html

https://segmentfault.com/q/1010000004955225

https://www.cnblogs.com/interdrp/p/4091056.html

框架是workerman
socket.io

使用四种框架分别实现百万websocket常连接的服务器

首先我们查看一下ServerEndpoint类源码:

[html] view plain copy
 
  1. @Retention(value = RetentionPolicy.RUNTIME)  
  2. @Target(value = {ElementType.TYPE})  
  3. public @interface ServerEndpoint {  
  4.   
  5.     public String value();  
  6.   
  7.     public String[] subprotocols() default {};  
  8.   
  9.     public Class<? extends Decoder>[] decoders() default {};  
  10.   
  11.     public Class<? extends Encoder>[] encoders() default {};  
  12.   
  13.     public Class<? extends ServerEndpointConfig.Configurator> configurator() default ServerEndpointConfig.Configurator.class;  
  14. }  

Encoders and Decoders(编码器和解码器):

WebSocket Api 提供了encoders 和 decoders用于 Websocket Messages 与传统java 类型之间的转换

An encoder takes a Java object and produces a representation that can be transmitted as a WebSocket message;

编码器输入java对象,生成一种表现形式,能够被转换成Websocket message

for example, encoders typically produce JSON, XML, or binary representations.

例如:编码器通常生成json、XML、二进制三种表现形式

A decoder performs the reverse function; it reads a WebSocket message and creates a Java object.

解码器执行相反的方法,它读入Websocket消息,然后输出java对象

编码器编码:

looks for an encoder that matches your type and uses it to convert the object to a WebSocket message.

利用RemoteEndpoint.Basic 或者RemoteEndpoint.Async的sendObject(Object data)方法将对象作为消息发送,容器寻找一个符合此对象的编码器,

利用此编码器将此对象转换成Websocket message

代码示例:可以指定为自己的一个消息对象

[html] view plain copy
 
  1. package com.zlxls.information;  
  2.   
  3. import com.alibaba.fastjson.JSON;  
  4. import com.common.model.SocketMsg;  
  5. import javax.websocket.EncodeException;  
  6. import javax.websocket.Encoder;  
  7. import javax.websocket.EndpointConfig;  
  8.   
  9. /**  
  10.  * 配置WebSocket解码器,用于发送请求的时候可以发送Object对象,实则是json数据  
  11.  * sendObject()  
  12.  * @ClassNmae:ServerEncoder     
  13.  * @author zlx-雄雄  
  14.  * @date    2017-11-3 15:47:13  
  15.  *   
  16.  */  
  17. public class ServerEncoder implements Encoder.Text<SocketMsg> {    
  18.     
  19.     @Override    
  20.     public void destroy() {    
  21.         // TODO Auto-generated method stub    
  22.     
  23.     }    
  24.     
  25.     @Override    
  26.     public void init(EndpointConfig arg0) {    
  27.         // TODO Auto-generated method stub    
  28.     
  29.     }    
  30.     
  31.     @Override    
  32.     public String encode(SocketMsg socketMsg) throws EncodeException {    
  33.         try {    
  34.             return JSON.toJSONString(socketMsg);    
  35.         } catch (Exception e) {    
  36.             // TODO Auto-generated catch block    
  37.             e.printStackTrace();    
  38.             return "";    
  39.         }    
  40.     }    
  41.    
  42. }    

Then, add the encodersparameter to the ServerEndpointannotation as follows:

@ServerEndpoint(

value = "/myendpoint",

encoders = { ServerEncoder.class, ServerEncoder1.class }

)

解码器解码:

Decoder.Binary<T>for binary messages

These interfaces specify the willDecode and decode methods.

the container calls the method annotated with @OnMessage that takes your custom Java type as a parameter if this method exists.

[html] view plain copy
 
  1. package com.zlxls.information;  
  2.   
  3. import com.common.model.SocketMsg;  
  4. import javax.websocket.DecodeException;  
  5. import javax.websocket.Decoder;  
  6. import javax.websocket.EndpointConfig;  
  7. /**  
  8.  * 解码器执,它读入Websocket消息,然后输出java对象  
  9.  * @ClassNmae:ServerDecoder     
  10.  * @author zlx-雄雄  
  11.  * @date    2017-11-11 9:12:09  
  12.  *   
  13.  */  
  14. public class ServerDecoder implements Decoder.Text<SocketMsg>{  
  15.   
  16.     @Override  
  17.     public void init(EndpointConfig ec){}  
  18.   
  19.     @Override  
  20.     public void destroy(){}  
  21.   
  22.     @Override  
  23.     public SocketMsg decode(String string) throws DecodeException{  
  24.         // Read message...  
  25.         return new SocketMsg();  
  26.     }  
  27.   
  28.     @Override  
  29.     public boolean willDecode(String string){  
  30.         // Determine if the message can be converted into either a  
  31.         // MessageA object or a MessageB object...  
  32.         return false;  
  33.     }  
  34. }  

Then, add the decoderparameter to the ServerEndpointannotation as follows:

@ServerEndpoint(

value = "/myendpoint",

encoders = { ServerEncoder.class, ServerEncoder1.class },

decoders = {ServerDecoder.class }

)

处理错误:

To designate a method that handles errors in an annotated WebSocket endpoint, decorate it with @OnError:

[html] view plain copy
 
  1. /**   
  2.      * 发生错误是调用方法   
  3.      * @param t   
  4.      * @throws Throwable   
  5.      */    
  6.     @OnError    
  7.     public void onError(Throwable t) throws Throwable {    
  8.         System.out.println("错误: " + t.toString());    
  9.     }    

为一个注解式的端点指定一个处理error的方法,为此方法加上@OnError注解:

This method is invoked when there are connection problems, runtime errors from message handlers, or conversion errors when decoding messages.

当出现连接错误,运行时错误或者解码时转换错误,该方法才会被调用

指定端点配置类:

The Java API for WebSocket enables you to configure how the container creates server endpoint instances.

Websocket的api允许配置容器合适创建server endpoint 实例

You can provide custom endpoint configuration logic to:

Access the details of the initial HTTP request for a WebSocket connection

Perform custom checks on the OriginHTTP header

Modify the WebSocket handshake response

Choose a WebSocket subprotocol from those requested by the client

Control the instantiation and initialization of endpoint instances

To provide custom endpoint configuration logic, you extend the ServerEndpointConfig.Configurator class and override some of its methods.

继承ServerEndpointConfig.Configurator 类并重写一些方法,来完成custom endpoint configuration 的逻辑代码

In the endpoint class, you specify the configurator class using the configurator parameter of the ServerEndpoint annotation.

代码示例:

[html] view plain copy
 
  1. package com.zlxls.information;  
  2.   
  3. import javax.servlet.http.HttpSession;  
  4. import javax.websocket.HandshakeResponse;  
  5. import javax.websocket.server.HandshakeRequest;  
  6. import javax.websocket.server.ServerEndpointConfig;  
  7. import javax.websocket.server.ServerEndpointConfig.Configurator;  
  8. /**  
  9.  * 由于websocket的协议与Http协议是不同的,  
  10.  * 所以造成了无法直接拿到session。  
  11.  * 但是问题总是要解决的,不然这个websocket协议所用的场景也就没了  
  12.  * 重写modifyHandshake,HandshakeRequest request可以获取httpSession  
  13.  * @ClassNmae:GetHttpSessionConfigurator     
  14.  * @author zlx-雄雄  
  15.  * @date    2017-11-3 15:47:13  
  16.  *   
  17.  */  
  18. public class GetHttpSessionConfigurator extends Configurator{  
  19.     @Override  
  20.     public void modifyHandshake(ServerEndpointConfig sec,HandshakeRequest request, HandshakeResponse response) {  
  21.           
  22.         HttpSession httpSession=(HttpSession) request.getHttpSession();  
  23.           
  24.         sec.getUserProperties().put(HttpSession.class.getName(),httpSession);  
  25.           
  26.     }  
  27. }  
[html] view plain copy
 
  1. @OnOpen  
  2. public void open(Session s, EndpointConfig conf){  
  3.       
  4.     HandshakeRequest req = (HandshakeRequest) conf.getUserProperties().get("sessionKey");  
  5.   
  6. }  

@ServerEndpoint(

value = "/myendpoint",

configurator=GetHttpSessionConfigurator.class

)

不过要特别说一句:

HandshakeRequest req = (HandshakeRequest) conf.getUserProperties().get("sessionKey");  目前获取到的是空值。会报错:java.lang.NullPointerException,这个错误信息,大家最熟悉不过了。

原因是:请求头里面并没有把相关的信息带上

这里就需要实现一个监听,作用很明显:将所有request请求都携带上httpSession,这样就可以正常访问了

说明:注解非常简单可以直接使用注解@WebListener,也可以再web.xml配置监听

[html] view plain copy
 
    1. package com.zlxls.information;  
    2.   
    3. import javax.servlet.ServletRequestEvent;  
    4. import javax.servlet.ServletRequestListener;  
    5. import javax.servlet.annotation.WebListener;  
    6. import javax.servlet.http.HttpServletRequest;  
    7.   
    8. /**  
    9.  * http://www.cnblogs.com/zhuxiaojie/p/6238826.html  
    10.  * 配置监听器,将所有request请求都携带上httpSession  
    11.  * 用于webSocket取Session  
    12.  * @ClassNmae:RequestListener     
    13.  * @author zlx-雄雄  
    14.  * @date    2017-11-4 11:27:33  
    15.  *   
    16.  */  
    17. @WebListener  
    18. public class RequestListener implements ServletRequestListener {  
    19.     @Override  
    20.     public void requestInitialized(ServletRequestEvent sre)  {  
    21.           
    22.         //将所有request请求都携带上httpSession  
    23.         ((HttpServletRequest) sre.getServletRequest()).getSession();  
    24.           
    25.     }  
    26.     public RequestListener() {}  
    27.   
    28.     @Override  
    29.     public void requestDestroyed(ServletRequestEvent arg0)  {}  
    30. }  

免责声明:文章转载自《java websocket @ServerEndpoint注解说明》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇如何使用putty登录群晖ds218play的linux系统SQL SERVER 内存学习系列(一)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

SimpleDateFormat并发隐患及其解决

此文已由作者姚太行授权网易云社区发布。 欢迎访问网易云社区,了解更多网易技术产品运营经验。 SimpleDateFormat被大量使用于处理时间格式化过程,由于该类在创建时会指定一个pattern用于标明固定的时间格式,所以在使用中,一般会创建一个作用域较大(static修饰或某类的私有属性)的对象用于重复使用。由于时间转换过程遇到的多线程并发的使用场景...

终于搞定2.0下头痛的输入法问题

        用过DOTNET2.0编写WINFORM程序应都会发现那个全角问题,虽然微软发布一个布丁但好似不起什么作用,另外还有一个输入法在某种条件下会丢失的情形:我们遇到的一个情况就是每次打印完,并闭当前窗体,再打开下一个输入时,发现只能输入英文,直接调用DOTNET2.0下提供的方法重新设置输入法也不行.        对第一个问题,网上有许多解决...

C# DataGridView显示行号的三种方法 (转载)

C# DataGridView显示行号的三种方法(转载) 源贴地址:https://blog.csdn.net/xieyufei/article/details/9769631 方法一: 网上最常见的做法是用DataGridView的RowPostPaint事件在RowHeaderCell中绘制行号: 但是这种方法在大数据量的时候性能比较差,每次滚动数据都...

ElementUI中的el-table怎样实现绑定对象数组时每一列不同控件的动态数据绑定

场景 ElementUI中的el-table中实现动态添加一行、删除一行、清空所有行: https://mp.csdn.net/console/editor/html/107815187 上面实现的效果如下 其中每一行都是动态添加的,每一行对应的是一个对象,每一列对应的是一个对象的属性。 所以整个el-table绑定的数据源就是一个对象的数组。 但是在...

C# DllImport 方法,出现 The system cannot find the file specified 错误

最近使用 C# 调用 dll 中的 UpdateDriverForPlugAndPlayDevices() 方法去安装驱动,遇到了 “The system cannot find the file specified” 问题, 看着错误提示,是指系统没有找到指定文件,但是我检查硬盘,该文件确实存在,但是因为我测试时使用的是 Hebrew 希伯来语的系统,我...

yiifiltersAccessControl 访问权限控制

Class yiifiltersAccessControl所有类 | 属性 | 方法   继承 yiifiltersAccessControl » yiiaseActionFilter » yiiaseBehavior » yiiaseBaseObject 实现 yiiaseConfigurable 可用版本自 2.0 源码 https:...