nutz websocket nginx maven 配合使用
起因
很久以前,用jetty玩过websocket,为了nutz.cn的自动提醒功能,又实践了一次websocket.
websocket需要服务器端,nginx,页面端,同时配合,才能工作.
页面端
var ws;
var WS_URL = window.location.host+"${base}/yvr/topic/socket";
if (location.protocol == 'http:') { // 需要特别注意的地方,根据http/https协议选不同的websocket前缀
ws = new WebSocket("ws://"+WS_URL); // 普通http用ws,全称WebSocket
} else {
ws = new WebSocket("wss://"+WS_URL); // https环境下需要wss协议,全称WebSocket Secure
}
ws.onmessage = function(event) { // onmessage 特指服务器端发送消息过来
var re = JSON.parse(event.data);
_replies_count = re.count;
var n = new Notification(re.data, re.options); // 这里使用了Chrome Notification API
n.onclick = function() {
location.reload();
};
};
window.setInterval(function(){ // 定时查询
ws.send(JSON.stringify({id:'${obj.topic.id}',replies:_replies_count}));
}, 5000);
服务器端
// 省略import
@ServerEndpoint("/yvr/topic/socket")
public class YvrTopicWebSocket {
private static final Log log = Logs.get();
@OnMessage
public void onMessage(String message, Session session) {
if (yvrService == null) // 从全局ioc容器取出需要的ioc bean
yvrService = Mvcs.ctx().getDefaultIoc().get(YvrService.class);
try {
NutMap map = Json.fromJson(NutMap.class, message); // 看页面端,发送过来的是json字符串
String topicId = map.getString("id");
int replies = map.getInt("replies");
Object re = yvrService.check(topicId, replies);
if (re instanceof Map) {
// 消息反馈回去, 会调用js中的onmessage方法
session.getBasicRemote().sendText(Json.toJson(re));
}
}
catch (Throwable e) {
log.debug("message="+message, e);
}
}
YvrService yvrService; // 注意,并非注入
}
Maven配置
编译依赖:
<dependencies>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
</dependency>
</dependencies>
jetty插件需要的依赖
必须加websocket-server,否则不扫描websocket相关的注解
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.3.8.v20160314</version>
<configuration>
<jvmArgs>-Dfile.encoding=UTF-8</jvmArgs>
</configuration>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>9.3.8.v20160314</version>
</dependency>
</dependencies>
</plugin>
Nginx配置
这个我也是后来测试才发现,需要加点东西, websocket才能传到后端去
location / {
proxy_http_version 1.1; #版本也必须是http 1.1
client_max_body_size 10m;
proxy_pass http://nutz;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_redirect http:// https://;
#add_header Access-Control-Allow-Origin "*";
# 下面两行是为了websocket特意加的.
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
分析一下YvrTopicWebSocket可否注入
在其构造方法打印堆栈信息,显示如下, 而且是第一次访问时才打印(即第一次访问时才创建对象)
java.lang.Throwable
at net.wendal.nutzbook.module.yvr.YvrTopicWebSocket.<init>(YvrTopicWebSocket.java:21)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at java.lang.Class.newInstance(Class.java:442)
at org.apache.tomcat.websocket.server.DefaultServerEndpointConfigurator.getEndpointInstance(DefaultServerEndpointConfigurator.java:36)
at org.apache.tomcat.websocket.pojo.PojoEndpointServer.onOpen(PojoEndpointServer.java:50)
at org.apache.tomcat.websocket.server.WsHttpUpgradeHandler.init(WsHttpUpgradeHandler.java:138)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:701)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1500)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.run(NioEndpoint.java:1456)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
可以看到是DefaultServerEndpointConfigurator这个类调用clazz.newInstance生成实例
依赖ServiceLoader加载的,但还没成功,明天再说了.
blog comments powered by Disqus