大神可以去看看(反正我也基本看不懂)https://my.oschina.net/u/136848/blog/781896
1.不用配置WebRoot/WEB-INF下的web.xml文件
2.config只配置一句(其实还有后面有补充)
AlarmThreadController.getInstance().start();//这里就是关键
package com.bytech.common;
import com.bytech.controller.AlarmCodeController;
import com.bytech.controller.AlarmController;
import com.bytech.controller.AlarmThreadController;
import com.bytech.controller.AppSystemController;
import com.bytech.controller.CustomerController;
import com.bytech.controller.IndexController;
import com.bytech.controller.ShellController;
import com.bytech.controller.StatusController;
import com.bytech.controller.SystemBrandController;
import com.bytech.controller.SystemCustomerController;
import com.bytech.controller.UserController;
import com.bytech.controller.UserOperationController;
import com.bytech.handler.WebSocketHandler;
import com.bytech.model.Alarm;
import com.bytech.model.AlarmCode;
import com.bytech.model.AppSystem;
import com.bytech.model.Customer;
import com.bytech.model.Status;
import com.bytech.model.SystemBrand;
import com.bytech.model.SystemCustomer;
import com.bytech.model.User;
import com.bytech.utiltool.ServerPush;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.JFinalConfig;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.ext.interceptor.SessionInViewInterceptor;
import com.jfinal.handler.Handler;
import com.jfinal.kit.PathKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.c3p0.C3p0Plugin;
import com.jfinal.render.ViewType;
public class CommonConfig extends JFinalConfig {
@Override
public void configConstant(Constants me) {
// TODO Auto-generated method stub
loadPropertyFile("config.properties");
me.setDevMode(getPropertyToBoolean("devMode", false));
me.setEncoding("UTF-8");
me.setViewType(ViewType.JSP);
me.setUploadedFileSaveDirectory(PathKit.getWebRootPath()+"\\uploads");
}
@Override
public void configPlugin(Plugins me) {
// TODO Auto-generated method stub
C3p0Plugin c3p0Plugin =new C3p0Plugin(getProperty("jdbcUrl"),
getProperty("user"),getProperty("password").trim());
me.add(c3p0Plugin);
ActiveRecordPlugin arp=new ActiveRecordPlugin(c3p0Plugin);
me.add(arp);
/*************************
* 添加表映射
************************/
arp.addMapping("customer", "CustomerId",Customer.class);
arp.addMapping("customer_system", "SystemId",SystemCustomer.class);
arp.addMapping("status", "id",Status.class);
arp.addMapping("system_brand", "id",SystemBrand.class);
arp.addMapping("alarm", "AlarmId",Alarm.class);
arp.addMapping("system_log", "LogId",AppSystem.class);
arp.addMapping("alarm_code", "AlarmCode",AlarmCode.class);
arp.addMapping("user", "id",User.class);
AlarmThreadController.getInstance().start();//这里就是关键
}
@Override
public void configInterceptor(Interceptors me) {
// TODO Auto-generated method stub
me.add(new SessionInViewInterceptor(true));
}
@Override
public void configHandler(Handlers me) {
// TODO Auto-generated method stub
me.add(new WebSocketHandler());
}
@Override
public void configRoute(Routes me) {
// TODO Auto-generated method stub
me.add("/customer", CustomerController.class, "");
me.add("/systemcustomer", SystemCustomerController.class, "");
me.add("/status", StatusController.class, "");
me.add("/systemBrand", SystemBrandController.class, "");
me.add("/alarm", AlarmController.class, "");
me.add("/appSystem", AppSystemController.class, "");
me.add("/userOperation", UserOperationController.class, "");
me.add("/alarmCode", AlarmCodeController.class, "");
me.add("/user", UserController.class, "");
//shell脚本
me.add("/shell", ShellController.class, "");
me.add("/",IndexController.class);
}
}
2.创建AlarmThreadController这个controller类。
package com.bytech.controller;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import com.bytech.model.Alarm;
import com.bytech.utiltool.ServerPush;
public class AlarmThreadController extends Thread {
private static class SingletonHolder {
private static AlarmThreadController instance = new AlarmThreadController();
}
public static AlarmThreadController getInstance() {
return SingletonHolder.instance;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();//
while (true) {
try {
// this.sleep(30000); //这个是启动时间,必须确保config映射表内容走完。
//其他内容运行完毕才走
//AlarmThreadController.getInstance().start();//这里就是关键
// Date now = new Date(); // 当前时间// SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");// String newTime = sf.format(now).toString();// List<Alarm> list = Alarm.dao.find("select AlarmId from alarm where AlarmTime >= ? ", newTime);// String idsJSON="";// if(list.size()!=0){// for (int i = 0; i < list.size(); i++) {// if(i==0){// idsJSON+=list.get(i).toJson();// }else if(i>0 && i<list.size()-1){// idsJSON+=","+list.get(i).toJson();// }else{// idsJSON+=","+list.get(i).toJson();// }// }// System.out.println(idsJSON);// String type="success";// String message="告警日志,新添加了"+list.size()+"条数据,请自行查看。";// ServerPush.broadcastAll(type,message,idsJSON);//这也是关键。// }} catch (Exception e) {e.printStackTrace();}}}// 把数据库里的数据,进行处理,转成long 和现在时间进行比较//public static long getDateLongVal(String str) {// int one = str.indexOf("AlarmTime:");// String str1 = str.substring(one + 10, one + 29);// String st1 = str1.replaceAll("-", "").replaceAll(":", "").replaceAll(" ", "");// return Long.parseLong(st1);//}}
上面AlarmThreadController继承了Thread(线程)重写了run方法
在run方法里我调用了ServerPush类里的broadcastAll(type,message,idsJSON)方法
ServerPush.broadcastAll(type,message,idsJSON);//这也是关键。
3.创建ServerPush类
package com.bytech.utiltool;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.logging.Logger;
import javax.websocket.CloseReason;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
//注意此访问地址格式如:"ws://"+ window.location.host+"/${pageContext.request.contextPath}/game"是ws开头的,而不是以http:开头的.
@ServerEndpoint(value = "/socket")
public class ServerPush {
private Logger logger = Logger.getLogger(this.getClass().getName());
static Map<String,Session> sessionMap = new Hashtable<String,Session>();
@OnOpen
public void onOpen(Session session) {
System.out.println("ServerPush="+session.getId());
sessionMap.put(session.getId(), session);
}
@OnMessage
public void onMessage(String unscrambledWord, Session session) {
System.out.println("来自客户端的消息:" + unscrambledWord);
//取消报警
/* if(unscrambledWord.startsWith("cancel"))
{
String[] strarray = unscrambledWord.split(":");
AlarmMonitorThread.cancelAlarm(strarray[1], strarray[2]);
}*/
try {
session.getBasicRemote().sendText("{type:'message',text:'"+unscrambledWord+"'}");
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
@OnMessage
public void receiveMessage(ByteBuffer b,Session session)
{
for(int i=0;i<b.capacity();i++)
{
System.out.println("msg="+b.getChar(i));
}
}
/**
* 广播给所有人
* @param message
*/
public static void broadcastAll(String type,String message,String data){
Set<Map.Entry<String,Session>> set = sessionMap.entrySet();
for(Map.Entry<String,Session> i: set){
try {
i.getValue().getBasicRemote().sendText("{type:'"+type+"',text:'"+message+"',data:'"+data+"'}");
} catch (Exception e) {
e.printStackTrace();
}
}
}
@OnClose
public void onClose(Session session, CloseReason closeReason) {
sessionMap.remove(session.getId());
logger.info(String.format("Session %s closed because of %s", session.getId(), closeReason));
}
@OnError
public void error(Session session, java.lang.Throwable throwable){
sessionMap.remove(session.getId());
System.err.println("session "+session.getId()+" error:"+throwable);
}
}
这个类你创建在那里就行。(我也基本看不懂)其主要目的就是调用broadcastAll方法广播给所有人。
i.getValue().getBasicRemote().sendText("{type:'"+type+"',text:'"+message+"',data:'"+data+"'}");这句话就是把对应的值传个前台。
4.config配置handler(不好意意思,之前忘了说了。不过我还是写了的)
@Override
public void configHandler(Handlers me) {
// TODO Auto-generated method stub
me.add(new WebSocketHandler());
}
5.创建WebSocketHandler类,直接附上源码
package com.bytech.handler;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.jfinal.handler.Handler;
public class WebSocketHandler extends Handler {
public WebSocketHandler() {
// TODO Auto-generated constructor stub
}
@Override
public void handle(String target, HttpServletRequest request,
HttpServletResponse response, boolean[] isHandled) {
// TODO Auto-generated method stub
int index = target.indexOf("/socket");
if (index == -1) {
nextHandler.handle(target, request, response, isHandled);
}
}
}
至于为什么写和配置handler,作用应该是给"/socket"(这个路径进行放行。)
6.写webSocket的前端js代码
var socket;
if ('WebSocket' in window) {
socket = new WebSocket("ws://"+ window.location.host
+ "/DaHuaOperationCollect/socket");
} else {
console.log('不支持websocket');
}
//连接创建后调用
socket.onopen = function() {
console.log("连接成功...<br/>");
};
//接收到服务器消息后调用
socket.onmessage = function(obj) {
// console.log(obj); //在页面观察它的数据
var d = eval("(" + obj.data + ")"); //把数据转成json,不然不好用,后台传的是String
var idsJSON = d.data;
// var type = d.type;
var msg = d.text;
// console.log(idsJSON);
// console.log(msg);
//async: false,
jQuery.ajax({
url : "./alarm/webSocketUpdataRowCon",
type : "POST",
data : {"ids" : idsJSON},
success : function(obj) {
// console.log("state" + obj.state)
if (obj.state == "0") {
var r = obj.row;
var len=r.length;
//var str="";
console.log("len="+len);
queryAlarmPage1(len);
// console.log("zzzzzzzzzzzzzz");
/* for (var i = 0; i<r.length; i++) {
str+="<tr class=\"danger\">"+
"<td style=\"text-align: center; \">"+r[i].CustomerName+"</td>"+
"<td style=\"text-align: center; \">"+r[i].SystemId+"</td>"+
"<td style=\"text-align: center; \">"+r[i].AlarmContent+"</td>"+
"<td style=\"text-align: center; \">"+r[i].AlarmTime+"</td>"+
"<td style=\"text-align: center; \">"+r[i].DevIp+"</td>"+
"<td style=\"text-align: center; \">"+r[i].Remark+"</td>"+
"</tr>";
}
$("#customerlist tbody tr:first").before(str); */
layer.alert(msg, {
skin : 'layui-layer-molv'//样式类名
,closeBtn : 0
});
} else {
layer.alert('实施更新数据失败。', {
skin : 'layui-layer-molv'//样式类名
,closeBtn : 0
});
}
},
error : function() {
layer.alert('系统错误', {
skin : 'layui-layer-molv'//样式类名
,closeBtn : 0
});
},
complete : function(obj) {
if (obj.status == 200);
}
})
};
//关闭连接的时候调用
socket.onclose = function() {
console.log("close");
};
//出错时调用
socket.onerror = function() {
console.log("error");
};
好了以上就是jfinal webSocket的配置 和实现的全部内容。
//接收到服务器消息后调用
socket.onmessage = function(obj) {把你要写的逻辑实现代码写在这里就行。}若是不懂,仔细再看看,多打桩(就是用输出语句输出值看看)。(我也不怎会)
AlarmThreadController 文件重发一下
package com.bytech.controller;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.logging.Logger;
import com.bytech.model.Alarm;
import com.bytech.utiltool.ServerPush;
public class AlarmThreadController extends Thread {
private static String lastId = "0";
private Logger logger = Logger.getLogger(this.getClass().getName());
private static class SingletonHolder {
private static AlarmThreadController instance = new AlarmThreadController();
}
public static AlarmThreadController getInstance() {
return SingletonHolder.instance;
}
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
Alarm alarm = Alarm.dao.findFirst("select max(AlarmId) as maxId from alarm");
if(alarm != null && alarm.getInt("maxId") != null )
{
lastId = String.valueOf(alarm.getInt("maxId"));
}
logger.info("begin ID:" + lastId);
while (true) {
try {
sleep(30000);
List<Alarm> list = Alarm.dao.find("select AlarmId from alarm where AlarmId>? group by AlarmId desc", lastId);
String idsJSON="";
if(list != null && list.size() > 0){
for (int i = 0; i < list.size(); i++) {
if(i==0){
lastId = String.valueOf(list.get(i).getInt("AlarmId"));
idsJSON += list.get(i).getInt("AlarmId");
}else if(i>0 && i<list.size()-1){
idsJSON+=","+list.get(i).getInt("AlarmId");
}else{
idsJSON+=","+list.get(i).getInt("AlarmId");
}
}
//System.out.println(idsJSON);
String type="success";
String message="告警日志,新添加了"+list.size()+"条数据,请自行查看。";
ServerPush.broadcastAll(type,message,idsJSON);
}
logger.info("last Id:" + lastId);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 把数据库里的数据,进行处理,转成long 和现在时间进行比较
public static long getDateLongVal(String str) {
int one = str.indexOf("AlarmTime:");
String str1 = str.substring(one + 10, one + 29);
String st1 = str1.replaceAll("-", "").replaceAll(":", "").replaceAll(" ", "");
return Long.parseLong(st1);
}
}