websocket @ServerEndpoint注解說明


首先我們查看一下ServerEndpoint類源碼:

@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE})
public @interface ServerEndpoint {
 
    public String value();
 
    public String[] subprotocols() default {};
 
    public Class<? extends Decoder>[] decoders() default {};
 
    public Class<? extends Encoder>[] encoders() default {};
 
    public Class<? extends ServerEndpointConfig.Configurator> configurator() default ServerEndpointConfig.Configurator.class;
}
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

代碼示例:可以指定為自己的一個消息對象

package com.zlxls.information;
 
import com.alibaba.fastjson.JSON;
import com.common.model.SocketMsg;
import javax.websocket.EncodeException;
import javax.websocket.Encoder;
import javax.websocket.EndpointConfig;
 
/**
 * 配置WebSocket解碼器,用於發送請求的時候可以發送Object對象,實則是json數據
 * sendObject()
 * @ClassNmae:ServerEncoder   
 * @author zlx-雄雄
 * @date    2017-11-3 15:47:13
 *
 */
public class ServerEncoder implements Encoder.Text<SocketMsg> {  
 
    @Override  
    public void destroy() {  
        // TODO Auto-generated method stub  
 
    }  
 
    @Override  
    public void init(EndpointConfig arg0) {  
        // TODO Auto-generated method stub  
 
    }  
 
    @Override  
    public String encode(SocketMsg socketMsg) throws EncodeException {  
        try {  
            return JSON.toJSONString(socketMsg);  
        } catch (Exception e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
            return "";  
        }  
    }  
 
}  
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.


package com.zlxls.information;
 
import com.common.model.SocketMsg;
import javax.websocket.DecodeException;
import javax.websocket.Decoder;
import javax.websocket.EndpointConfig;
/**
 * 解碼器執,它讀入Websocket消息,然后輸出java對象
 * @ClassNmae:ServerDecoder   
 * @author zlx-雄雄
 * @date    2017-11-11 9:12:09
 *
 */
public class ServerDecoder implements Decoder.Text<SocketMsg>{
 
    @Override
    public void init(EndpointConfig ec){}
 
    @Override
    public void destroy(){}
 
    @Override
    public SocketMsg decode(String string) throws DecodeException{
        // Read message...
        return new SocketMsg();
    }
 
    @Override
    public boolean willDecode(String string){
        // Determine if the message can be converted into either a
        // MessageA object or a MessageB object...
        return false;
    }
}
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:

 

/**
     * 發生錯誤是調用方法
     * @param t
     * @throws Throwable
     */  
    @OnError  
    public void onError(Throwable t) throws Throwable {  
        System.out.println("錯誤: " + t.toString());  
    }  
為一個注解式的端點指定一個處理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.

代碼示例:

package com.zlxls.information;
 
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
/**
 * 由於websocket的協議與Http協議是不同的,
 * 所以造成了無法直接拿到session。
 * 但是問題總是要解決的,不然這個websocket協議所用的場景也就沒了
 * 重寫modifyHandshake,HandshakeRequest request可以獲取httpSession
 * @ClassNmae:GetHttpSessionConfigurator   
 * @author zlx-雄雄
 * @date    2017-11-3 15:47:13
 *
 */
public class GetHttpSessionConfigurator extends Configurator{
    @Override
    public void modifyHandshake(ServerEndpointConfig sec,HandshakeRequest request, HandshakeResponse response) {
        
        HttpSession httpSession=(HttpSession) request.getHttpSession();
        
        sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
        
    }
}
@OnOpen
public void open(Session s, EndpointConfig conf){
    
    HandshakeRequest req = (HandshakeRequest) conf.getUserProperties().get("sessionKey");
 
}
@ServerEndpoint(

value = "/myendpoint",

configurator=GetHttpSessionConfigurator.class

)

不過要特別說一句:
HandshakeRequest req = (HandshakeRequest) conf.getUserProperties().get("sessionKey");  目前獲取到的是空值。會報錯:java.lang.NullPointerException,這個錯誤信息,大家最熟悉不過了。

原因是:請求頭里面並沒有把相關的信息帶上

這里就需要實現一個監聽,作用很明顯:將所有request請求都攜帶上httpSession,這樣就可以正常訪問了

說明:注解非常簡單可以直接使用注解@WebListener,也可以再web.xml配置監聽


package com.zlxls.information;
 
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
 
/**
 * http://www.cnblogs.com/zhuxiaojie/p/6238826.html
 * 配置監聽器,將所有request請求都攜帶上httpSession
 * 用於webSocket取Session
 * @ClassNmae:RequestListener   
 * @author zlx-雄雄
 * @date    2017-11-4 11:27:33
 *
 */
@WebListener
public class RequestListener implements ServletRequestListener {
    @Override
    public void requestInitialized(ServletRequestEvent sre)  {
        
        //將所有request請求都攜帶上httpSession
        ((HttpServletRequest) sre.getServletRequest()).getSession();
        
    }
    public RequestListener() {}
 
    @Override
    public void requestDestroyed(ServletRequestEvent arg0)  {}
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM