java使⽤websocket,并且获取HttpSession,源码分析
转载请在页⾸注明作者与出处
此⽂不仅仅局限于spring boot,普通的spring⼯程,甚⾄是servlet⼯程,都是⼀样的,只不过配置⼀些的⽅法不同⽽已。
本⽂经过作者实践,确认完美运⾏。
websocket本⾝是servlet容器所提供的服务,所以需要在web容器中运⾏,像我们所使⽤的tomcat,当然,spring boot中已经内嵌了tomcat。
websocket遵循了javaee规范,所以需要引⼊javaee的包
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
<scope>provided</scope>
</dependency>
当然,其实tomcat中已经⾃带了这个包。
如果是在spring boot中,还需要加⼊websocket的starter
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
<version>1.4.0.RELEASE</version>
</dependency>
如果不是spring boot项⽬,那就不需要进⾏这样的配置,因为如果在tomcat中运⾏的话,tomcat会扫描带有@ServerEndpoint的注解成为websocket,⽽spring boot项⽬中需要由这个bean来提供注册管理。
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
使⽤websocket的核⼼,就是⼀系列的websocket注解,@ServerEndpoint是注册在类上⾯开启。@ServerEndpoint(value = "/websocket")
@Component
public class MyWebSocket {
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
/**
* 连接成功*/
@OnOpen
public void onOpen(Session session) {
this.session = session;
}
/**
* 连接关闭调⽤的⽅法
*/
@OnClose
public void onClose() {
}
/**
* 收到消息
*websocket和socket
* @param message
*/
@OnMessage
public void onMessage(String message, Session session) {
System.out.println("来⾃浏览器的消息:" + message);
//发消息
for (MyWebSocket item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 发⽣错误时调⽤
*/
@OnError
public void onError(Session session, Throwable error) {
System.out.println("发⽣错误");
error.printStackTrace();
}
public void sendMessage(String message) throws IOException {
BasicRemote().sendText(message);//同步
//AsyncRemote().sendText(message);//异步
}
}
其实我也感觉很奇怪,为什么不使⽤接⼝来规范。即使是因为@ServerEndpoint注解中其它属性中可以定义出⼀些额外的参数,但相信也是可以抽象出来的,不过想必javaee这样做,应该是有它的⽤意吧。
浏览器端的代码需要浏览器⽀持websocket,当然,也有socket.js可以⽀持到ie7,但是这个我没⽤过。毕竟ie基本上没⼈⽤的,市⾯上的浏览器基本上全部都⽀持websocket。
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
</body>
<script type="text/javascript">
var websocket = null;
//判断当前浏览器是否⽀持WebSocket
if('WebSocket' in window){
websocket = new WebSocket("ws://localhost:9999/websocket");
}
else{
alert('不⽀持websocket')
//连接发⽣错误
};
//连接成功
}
//接收到消息
var msg = event.data;
alert("收到消息:" + msg);
}
//连接关闭
}
//监听窗⼝关闭事件,当窗⼝关闭时,主动去关闭websocket连接,防⽌连接还没断开就关闭窗⼝,server端会抛异常。
websocket.close();
}
//发送消息
function send(message){
websocket.send(message);
}
</script>
</html>
如此就连接成功了。
获取HttpSession是⼀个很有必要讨论的问题,因为java后台需要知道当前是哪个⽤户,⽤以处理该⽤户的业务逻辑,或者是对该⽤户进⾏授权之类的,但是由于websocket的协议与Http协议是不同的,所以造成了⽆法直接拿到session。但是问题总是要解决的,不然这个websocket协议所⽤的场景也就没了。
我们先来看⼀下@ServerEndpoint注解的源码
package javax.websocket.server;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.websocket.Decoder;
import javax.websocket.Encoder;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ServerEndpoint {
/**
* URI or URI-template that the annotated class should be mapped to.
* @return The URI or URI-template that the annotated class should be mapped
* to.
*/
String value();
String[] subprotocols() default {};
Class<? extends Decoder>[] decoders() default {};
Class<? extends Encoder>[] encoders() default {};
public Class<? extends ServerEndpointConfig.Configurator> configurator()
default ServerEndpointConfig.Configurator.class;
}
我们看到最后的⼀个⽅法,也就是加粗的⽅法。可以看到,它要求返回⼀个ServerEndpointConfig.Configurator的⼦类,我们写⼀个类去继承它。
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;
public class HttpSessionConfigurator extends Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
//怎么搞?
}
}
当我们覆盖modifyHandshake⽅法时,可以看到三个参数,其中后⾯两个参数让我们感觉有点见过的感觉,我们查看⼀HandshakeRequest 的源码
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论