tomcat7(或8)中实现websocket连接,服务端建立有两种方式:
1. 注解@ServerEndpoint(value = " ")
2. 继承Endpoint
然而多数情况下是注解实现,继承实现较少。
1
package com.socket;
import javax.websocket.OnClose;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value = "/websocketAnno.servlet")
public class WebsocketWithAnno {
private Session session;
@OnOpen
public void open(Session session, @PathParam(value = "user")String user) {
this.session = session;
System.out.println("*** WebSocket opened from sessionId " + session.getId());
}
@OnMessage
public void inMessage(String message) {
System.out.println("*** WebSocket Received from sessionId " + this.session.getId() + ": " + message);
}
@OnClose
public void end() {
System.out.println("*** WebSocket closed from sessionId " + this.session.getId());
}
}
2
package com.socket;
import java.io.IOException;
import java.nio.ByteBuffer;
import javax.websocket.CloseReason;
import javax.websocket.Endpoint;
import javax.websocket.EndpointConfig;
import javax.websocket.MessageHandler;
import javax.websocket.RemoteEndpoint;
import javax.websocket.Session;
public class WebsocketWithoutAnno extends Endpoint{
@Override
public void onOpen(Session session, EndpointConfig config) {
RemoteEndpoint.Basic remoteEndpointBasic = session.getBasicRemote();
System.out.print("opend");
}
@Override
public void onClose(Session session, CloseReason reason){
}
@Override
public void onError(Session session, Throwable error){
}
}
客户端主要通过发送ws或者wss请求来实现。
在搭建注解实现的时候,上述1代码就能完成了,但是继承实现还需要对其进行配置。这里建立了一个WebsocketConfig。
package com.socket;
import java.util.HashSet;
import java.util.Set;
import javax.websocket.Endpoint;
import javax.websocket.server.ServerApplicationConfig;
import javax.websocket.server.ServerEndpointConfig;
/*
* ServerApplicationConfig:
* Applications may provide an implementation of this interface to filter the discovered WebSocket endpoints that are deployed.
* Implementations of this class will be discovered via an ServletContainerInitializer scan.
*
* scanned:
* get all WebSocket endpoints (defined by annotations or not) in the web
*
*/
public class WebsocketConfig implements ServerApplicationConfig{
@Override
public Set<ServerEndpointConfig> getEndpointConfigs(Set<Class<? extends Endpoint>> scanned) {
Set<ServerEndpointConfig> result = new HashSet<>();
if (scanned.contains(WebsocketWithoutAnno.class)) {
result.add(ServerEndpointConfig.Builder.create(WebsocketWithoutAnno.class, "/websocket.servlet").build());
}
return result;
}
@Override
public Set<Class<?>> getAnnotatedEndpointClasses(Set<Class<?>> scanned) {
Set<Class<?>> result = new HashSet<>();
// Filter out all others to avoid issues when running; if all the annotated endpoints are used, delete this class.
for (Class<?> clazz : scanned) {
if (clazz.getPackage().getName().startsWith("com.socket")) {
result.add(clazz);
}
}
return result;
}
}
需要说明的是
ServerApplicationConfig实现类是在tomcat启动时被加载的,其中两个方法分别管理注解和实现类;
scanned中存储的是websokcet服务类。
方法getEndpointConfigs中是对继承Endpoint的类进行访问路径映射;
方法getAnnotatedEndpointClasses中的for循环是过滤注解下一些不需要的websocket
也就是说返回值result中存储的是想要被使用的websocket。
具体可以看api:http://docs.oracle.com/javaee/7/api/javax/websocket/server/ServerApplicationConfig.html。
看tomcat中examples中例子更好。