回调:
package com.ireal.crpas.test.SerachSnmp.callback_interface; import com.ireal.crpas.apps.model.DeviceInfo; import com.ireal.crpas.test.SerachSnmp.model.SnmpCallBackVo; import javax.websocket.Session; import java.util.List; public interface CallBack_Snmp { public void getSnmpList(Session session, DeviceInfo deviceInfo, List<SnmpCallBackVo> spList) throws Exception; }
接口interface 定义回调时的返回调用方法 session 为当前会话session websocket中的session
deviceinfo是存放值的参数
splist是我返回的值
package com.ireal.crpas.test.SerachSnmp.SerachDevice; import com.ireal.crpas.apps.model.DeviceInfo; import com.ireal.crpas.test.SerachSnmp.*; import com.ireal.crpas.test.SerachSnmp.callback_interface.CallBack_Snmp; import com.ireal.crpas.test.SerachSnmp.model.SnmpCallBackVo; import com.ireal.crpas.test.SerachSnmp.socket.MpInfoWebSocket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.websocket.Session; import java.util.HashMap; import java.util.List; import java.util.concurrent.*; public class SerachDeviceManager implements CallBack_Snmp { public Logger logger = LoggerFactory.getLogger(getClass()); //核心线程数量 private Integer corePoolSize; //延迟时间 private Integer initialDelay; //周期 private Integer period; //时间单位 private TimeUnit timeUnit; public SerachDeviceManager(Integer corePoolSize,Integer initialDelay,Integer period,TimeUnit timeUnit) { this.corePoolSize=corePoolSize; this.initialDelay=initialDelay; this.period=period; this.timeUnit=timeUnit; } private ThreadPoolExecutor executor; //线程调度池 private ScheduledThreadPoolExecutor scheuldService= null; private HashMap<Object,Object> backMap = new HashMap<>(); public void init() { scheuldService=new ScheduledThreadPoolExecutor(corePoolSize); } public boolean beginSerach(Session sesssion, DeviceInfo deviceInfo, List<SnmpCallBackVo> spList)throws Exception{ //线程 // new Thread(new SerachSnmpThread(this,deviceInfo,spList)).start(); // 线程池 try { scheuldService.scheduleAtFixedRate(new SerachSnmpThread(sesssion,this,deviceInfo,spList),initialDelay,period,timeUnit); }catch (Exception e){ System.out.println("终止线程池"); scheuldService.shutdown(); } return true; } @Override public void getSnmpList(Session session,DeviceInfo deviceInfo, List<SnmpCallBackVo> spList) throws Exception { logger.info("------------------线程回调--------------------"+deviceInfo+spList); MpInfoWebSocket myWebSocket = new MpInfoWebSocket(); myWebSocket.reciveBack(session,spList); // MonitorpointInfoController monitorpointInfoController = new MonitorpointInfoController(); // monitorpointInfoController.getResult(backMap); } /*public List<Object> getSnmpForDeivce() throws Exception { Init(); //数据库里存在model的设备 List<DeviceInfo> deviceInfos = dataCache.getDeviceDao().queryDeviceInfoofModel(); SerachDivceInfoVo serachDivceInfoVo = null; Map<String, String> mapfromxml = null; ArrayList<SerachDivceInfoVo> serachList = new ArrayList<>(); ArrayList<Object> objList = new ArrayList<Object>(); ArrayList<FutureTask> futures = new ArrayList<>(); //循环查出来的设备 for (DeviceInfo deviceInfo : deviceInfos) { serachDivceInfoVo = new SerachDivceInfoVo(); //根据model去查出来xml文件 DevicetypeInfo deviceType = dataCache.getDevicetypeInfoDao().getId(null, String.valueOf(deviceInfo.getModel())); String path = deviceType.getSubtypename() + ".xml"; mapfromxml = snmpXmlUtils.getMapfromxml(path);//baseOid 和 mptype //根据设备id取出来监控点 List<SerachMonitorPointVo> list = dataCache.getDeviceMonitorpointInfoDao().queryListByDeviceId(deviceInfo.getDeviceId()); //根据读取出来的文件中的mptype跟数据库中list的mptype做对比取出来xml文件的map中的baseoid for (SerachMonitorPointVo vo : list) { vo.setBaseOid(mapfromxml.get(String.valueOf(vo.getMptype()))); } serachDivceInfoVo.setList(list); serachDivceInfoVo.setIp(deviceInfo.getIp()); serachDivceInfoVo.setDeviceName(deviceInfo.getDeviceName()); serachDivceInfoVo.setDeviceId(deviceInfo.getDeviceId()); //此设备的监控点list存储到一个设备对象中 serachList.add(serachDivceInfoVo); } //线程池-- Rules.getInstance().setN(1); List<List<SerachDivceInfoVo>> snmplist = Rules.getInstance().getSnmplist(serachList); for (List list :snmplist){ SerachSnmpThreadBylist serachSnmpThreadBylist = new SerachSnmpThreadBylist(list); FutureTask<List<SnmpCallBackVo>> listFutureTask = new FutureTask<List<SnmpCallBackVo>>(serachSnmpThreadBylist); //executorService.submit(listFutureTask); // executorService.scheduleAtFixedRate(snmpThreadFutureTask,1,3, TimeUnit.SECONDS); futures.add(listFutureTask); } for(FutureTask future : futures){ // System.out.println(future.get()); objList.add(future.get()); } return objList; }*/ //停止线程池 public void shutDown(){ if(scheuldService!=null){ scheuldService.shutdownNow(); } } //往线程池的队列中添加数据 public void addSnmpQueue(Runnable runnable){ scheuldService .getQueue().add(runnable); } //查看线程池中是否有空闲线程 public Boolean checkedPoolIsEmpty(){ if(scheuldService==null){ //scheuldService= new ScheduledThreadPoolExecutor(); } if(scheuldService.getActiveCount()<executor.getCorePoolSize()){ return true; } return false; } //future public static void main(String[] args) throws InterruptedException { /* SerachDeviceManager serachDeviceManager = new SerachDeviceManager(); serachDeviceManager.Init(); Thread.sleep(1000); System.out.println("init后-activeCount:线程活跃数"+serachDeviceManager.executor.getActiveCount() +"总任务数taskCount---"+serachDeviceManager.executor.getTaskCount()+"---" + "线程池设置的容量:"+serachDeviceManager.executor.getCorePoolSize() + "线程池设置的最大容量:"+serachDeviceManager.executor.getMaximumPoolSize() +"已完成任务数" + serachDeviceManager.executor.getCompletedTaskCount() ); for (int i =0;i<10;i++){ if(serachDeviceManager.checkedPoolIsEmpty()){ serachDeviceManager.executor.execute(new ThreadTest()); System.out.println("执行添加"+"活跃线程的数量:"+serachDeviceManager.executor.getActiveCount()); Thread.sleep(3000); }else { serachDeviceManager.addSnmpQueue(new ThreadTest()); System.out.println("else添加队列后的数量:"+serachDeviceManager.executor.getQueue().size()+"活跃线程的数量:"+serachDeviceManager.executor.getActiveCount()); } System.out.println(serachDeviceManager.list); } serachDeviceManager.addSnmpQueue(new ThreadTest()); serachDeviceManager.addSnmpQueue(new ThreadTest()); serachDeviceManager.addSnmpQueue(new ThreadTest()); serachDeviceManager.addSnmpQueue(new ThreadTest()); System.out.println("模拟执行时间前的队列中的数量"+serachDeviceManager.executor.getQueue().size());; // serachDeviceManager.checkedPool(); Thread.sleep(3000); System.out.println("添加队列后-activeCount:线程活跃数"+serachDeviceManager.executor.getActiveCount() +"总任务数taskCount---"+serachDeviceManager.executor.getTaskCount()+"---" + "线程池设置的容量:"+serachDeviceManager.executor.getCorePoolSize() + "线程池设置的最大容量:"+serachDeviceManager.executor.getMaximumPoolSize() +"已完成任务数" + serachDeviceManager.executor.getCompletedTaskCount() +"线程池中队列的数量:"+serachDeviceManager.executor.getQueue().size() );*/ /* SerachDeviceManager serachDeviceManager = new SerachDeviceManager(); serachDeviceManager.Init(); for(int i =0 ;i<10;i++){ serachDeviceManager.scheuldService.scheduleAtFixedRate(new ThreadTest(i),3,2,TimeUnit.SECONDS); }*/ } //重写线程池 失败 // SerachSnmpThreadPool serachSnmpThreadPool = new SerachSnmpThreadPool(4, 5, 5, TimeUnit.MINUTES, new LinkedBlockingDeque<>(), serachList); public void back(List<String> list){ System.out.println(list); } public Integer getCorePoolSize() { return corePoolSize; } public void setCorePoolSize(Integer corePoolSize) { this.corePoolSize = corePoolSize; } public Integer getInitialDelay() { return initialDelay; } public void setInitialDelay(Integer initialDelay) { this.initialDelay = initialDelay; } public Integer getPeriod() { return period; } public void setPeriod(Integer period) { this.period = period; } public TimeUnit getTimeUnit() { return timeUnit; } public void setTimeUnit(TimeUnit timeUnit) { this.timeUnit = timeUnit; } }
这个类实现了接口callback 所以要重写callback中的方法getdevicelist 目的是beginSerach委托另一个线程办完事后调用当前类的这个方法来返回值 且需要把自己需要的条件传过去 因为websocket 推送消息session要保持唯一 也要传session
package com.ireal.crpas.test.SerachSnmp; import com.ireal.crpas.apps.model.DeviceInfo; import com.ireal.crpas.test.SerachSnmp.SerachDevice.SerachDeviceMain; import com.ireal.crpas.test.SerachSnmp.callback_interface.CallBack_Snmp; import com.ireal.crpas.test.SerachSnmp.model.SnmpCallBackVo; import com.ireal.crpas.test.SnmpAbout.Snmp_api; import com.ireal.crpas.test.SnmpCpu.SnmpCpuThread; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.websocket.Session; import java.util.List; public class SerachSnmpThread implements Runnable { private static final Logger log = LoggerFactory.getLogger(SnmpCpuThread.class); private DeviceInfo deviceInfo; private List<SnmpCallBackVo> callBacklist; private CallBack_Snmp callBack_snmp; private Session session; private SerachDeviceMain serachDeviceMain = new SerachDeviceMain(); public SerachSnmpThread(){ } public SerachSnmpThread(Session session ,CallBack_Snmp callBack_snmp, DeviceInfo deviceInfo, List<SnmpCallBackVo> list){ this.deviceInfo=deviceInfo; this.callBacklist=list; this.callBack_snmp=callBack_snmp; this.session=session; } private Snmp_api api= new Snmp_api(); @Override public void run() { try { serachDeviceMain.getDeviceSnmpList(session,callBack_snmp,deviceInfo,callBacklist); } catch (Exception e) { e.printStackTrace(); } } /* private SerachDivceInfoVo vo; public SerachSnmpThread(SerachDivceInfoVo vo){ this.vo=vo; }*/ /* public void run(){ String ip = vo.getIp(); List<SerachMonitorPointVo> list = vo.getList(); for(SerachMonitorPointVo vo :list){ String s = api.get(ip, vo.getBaseOid() + "." + vo.getMindex()); log.info("-------:"+" "+vo.getMpname()+"--"+s); } }*/ /* @Override public List<SnmpCallBackVo> call() throws Exception { log.info("--------当前线程为-----------"+Thread.currentThread().getName()); String ip = vo.getIp(); List<SerachMonitorPointVo> list = vo.getList(); SnmpCallBackVo backVo = null; List<SnmpCallBackVo> list1= new ArrayList<SnmpCallBackVo>(); for(SerachMonitorPointVo vo :list){ backVo=new SnmpCallBackVo(); String s = api.get(ip, vo.getBaseOid() + "." + vo.getMindex()); backVo.setMpName(vo.getMpname()); backVo.setMpType(String.valueOf(vo.getMptype())); backVo.setValue(s); backVo.setDeviceId(vo.getDeviceid()); list1.add(backVo); } return list1; }*/ }
此线程就是调用了具体实现的方法 从而达到异步回调的目的
package com.ireal.crpas.test.SerachSnmp.SerachDevice; import com.ireal.crpas.apps.model.DeviceInfo; import com.ireal.crpas.apps.model.DevicetypeInfo; import com.ireal.crpas.container.DataCache; import com.ireal.crpas.test.SerachSnmp.callback_interface.CallBack_Snmp; import com.ireal.crpas.test.SerachSnmp.model.SerachDivceInfoVo; import com.ireal.crpas.test.SerachSnmp.model.SnmpCallBackVo; import com.ireal.crpas.test.SnmpAbout.Snmp_api; import com.ireal.crpas.test.SerachSnmp.model.SerachMonitorPointVo; import com.ireal.crpas.test.SerachSnmp.utils.snmpXmlUtils; import javax.websocket.Session; import java.util.List; import java.util.Map; //具体实现 public class SerachDeviceMain { private CallBack_Snmp callBack_snmp; private Snmp_api api=new Snmp_api(); private DataCache dataCache=null; public SerachDeviceMain(){ this.dataCache=DataCache.newInstance(); } public boolean regFun(CallBack_Snmp callBack_snmp){ this.callBack_snmp=callBack_snmp; return true; } //具体实现 public void getDeviceSnmpList(Session session, CallBack_Snmp callBack_snmp, DeviceInfo deviceInfo, List<SnmpCallBackVo> backVoList) throws Exception{ Map<String, String> mapfromxml = null; SerachDivceInfoVo serachDivceInfoVo = new SerachDivceInfoVo(); //根据model去查出来xml文件 DevicetypeInfo deviceType = dataCache.getDevicetypeInfoDao().getId(null, String.valueOf(deviceInfo.getModel())); // DeviceInfo deviceType = DataCache.newInstance().getDeviceDao().getId(deviceInfo.getDeviceId()); String path = deviceType.getSubtypename() + ".xml"; mapfromxml = snmpXmlUtils.getMapfromxml(path);//baseOid 和 mptype //根据设备id取出来监控点 List<SerachMonitorPointVo> list = dataCache.getDeviceMonitorpointInfoDao().queryListByDeviceId(deviceInfo.getDeviceId()); //根据读取出来的文件中的mptype跟数据库中list的mptype做对比取出来xml文件的map中的baseoid for (SerachMonitorPointVo vo : list) { vo.setBaseOid(mapfromxml.get(String.valueOf(vo.getMptype()))); } serachDivceInfoVo.setList(list); serachDivceInfoVo.setIp(deviceInfo.getIp()); serachDivceInfoVo.setDeviceName(deviceInfo.getDeviceName()); serachDivceInfoVo.setDeviceId(deviceInfo.getDeviceId()); String ip = serachDivceInfoVo.getIp(); List<SerachMonitorPointVo> mplist = serachDivceInfoVo.getList(); SnmpCallBackVo backVo = null; for(SerachMonitorPointVo vo :mplist){ backVo=new SnmpCallBackVo(); String s = api.get(ip, vo.getBaseOid() + "." + vo.getMindex()); backVo.setMpName(vo.getMpname()); backVo.setMpType(String.valueOf(vo.getMptype())); backVo.setValue(s); backVo.setMpid(vo.getMpid()); backVo.setDeviceName(deviceInfo.getDeviceName()); backVo.setDeviceId(vo.getDeviceid()); backVo.setIndex(vo.getMindex()); backVoList.add(backVo); } //回调 callBack_snmp.getSnmpList(session,deviceInfo,backVoList); } }
manager中的beginsearch 的具体实现 实现完会调用manager中的getsnmplist来把结果回调回去
@Override public void getSnmpList(Session session,DeviceInfo deviceInfo, List<SnmpCallBackVo> spList) throws Exception { logger.info("------------------线程回调--------------------"+deviceInfo+spList); MpInfoWebSocket myWebSocket = new MpInfoWebSocket(); myWebSocket.reciveBack(session,spList); // MonitorpointInfoController monitorpointInfoController = new MonitorpointInfoController(); // monitorpointInfoController.getResult(backMap); }
这是实现了回调接口 重写的回调方法 每当有线程调用了manager中的getsnmplist时 都会在这个中再次调用mywebsocket的reciveback 方法 来传递信息。 从而不断地向前端推送。
package com.ireal.crpas.test.SerachSnmp.socket; import com.ireal.crpas.apps.dao.DeviceInfoDao; import com.ireal.crpas.apps.model.DeviceInfo; import com.ireal.crpas.container.DataCache; import com.ireal.crpas.test.SerachSnmp.SerachDevice.SerachDeviceManager; import com.ireal.crpas.test.SerachSnmp.model.SnmpCallBackVo; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Component; import javax.naming.directory.SearchControls; import javax.websocket.*; import javax.websocket.server.PathParam; import javax.websocket.server.ServerEndpoint; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; @ServerEndpoint(value = "/serachSnmp") @Component public class MpInfoWebSocket { //静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。 private static AtomicInteger onlineCount = new AtomicInteger(0); //concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。 private static CopyOnWriteArraySet<MpInfoWebSocket> webSocketSet = new CopyOnWriteArraySet<MpInfoWebSocket>(); private static Integer state; SerachDeviceManager serachDeviceManager=null; //与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; private String deviceId; private List<SnmpCallBackVo> allist=new ArrayList<SnmpCallBackVo>(); /** * 连接建立成功调用的方法*/ @OnOpen public void onOpen(Session session) throws Exception { state=1; // this.deviceId=deviceId; this.session = session; webSocketSet.add(this); //加入set中 addOnlineCount(); //在线数加1 //this.serach(); System.out.println("连接成功"); } public void serach() throws Exception { serachDeviceManager= new SerachDeviceManager(3, 0, 10, TimeUnit.SECONDS); serachDeviceManager.init(); DeviceInfoDao deviceDao = DataCache.newInstance().getDeviceDao(); //数据库里存在model的设备 list 不用; /* List<DeviceInfo> deviceInfos = deviceDao.queryDeviceInfoofModel(); for (DeviceInfo info:deviceInfos){ ArrayList<SnmpCallBackVo> snmpCallBackVos = new ArrayList<>(); serachDeviceManager.beginSerach(session,info, snmpCallBackVos); }*/ DeviceInfo info = deviceDao.getId(deviceId); if(info==null||info.getModel()==0){ sendInfo("该设备没有model"); }else{ ArrayList<SnmpCallBackVo> snmpCallBackVos = new ArrayList<>(); serachDeviceManager.beginSerach(session,info, snmpCallBackVos); } } public void reciveBack(Session session,List<SnmpCallBackVo> list){ this.session=session; // allist.addAll(list); this.sendToWeb(list); list.clear(); } private void sendToWeb(List<SnmpCallBackVo> allist) { System.out.println(allist.size()); if(state==1){ try { synchronized (state){ this.session.getBasicRemote().sendText(allist.toString()); } } catch (Exception e) { e.printStackTrace(); } }else{ if(serachDeviceManager!=null){ serachDeviceManager.shutDown(); } System.out.println("websocket已断开"); } } /** * 连接关闭调用的方法 */ @OnClose public void onClose() { state=0; if(serachDeviceManager!=null){ serachDeviceManager.shutDown(); } webSocketSet.remove(this); //从set中删除 subOnlineCount(); //在线数减1 System.out.println("有一连接关闭!当前在线人数为" + getOnlineCount()); } /** * 收到客户端消息后调用的方法 * * @param message 客户端发送过来的消息*/ @OnMessage public void onMessage(String deviceId, Session session) { System.out.println("来自客户端的消息:" + deviceId); DeviceInfo id = DataCache.newInstance().getDeviceDao().getId(deviceId); if(id!=null){ this.deviceId=deviceId; try { serach(); } catch (Exception e) { System.out.println("未知错误"); e.printStackTrace(); } } /* //群发消息 for (MpInfoWebSocket item : webSocketSet) { try { item.sendMessage(deviceId); } catch (Exception e) { e.printStackTrace(); } }*/ } /** * 发生错误时调用 */ @OnError public void onError(Session session, Throwable error) { System.out.println("发生错误"); serachDeviceManager.shutDown(); error.printStackTrace(); } public void sendMessage(String message) throws IOException, EncodeException { // this.session.getBasicRemote().sendText(message); if(StringUtils.isNotBlank(message)){ this.session.getAsyncRemote().sendText(message); } } /** * 群发自定义消息 * */ public static void sendInfo(String message) throws IOException { for (MpInfoWebSocket item : webSocketSet) { try { item.sendMessage(message); } catch (Exception e) { continue; } } } public static synchronized int getOnlineCount() { return onlineCount.get(); } public static synchronized void addOnlineCount() { // MyWebSocket.onlineCount++; onlineCount.getAndIncrement(); } public static synchronized void subOnlineCount() { //MyWebSocket.onlineCount--; onlineCount.getAndDecrement(); } }
websocket 建立连接后 收到deviceid 随后调用serach方法 然后就是调用之前的实现回调接口的类来beginserach 启动线程池新建线程来调用具体的实现方法 实现完之后再调用manager中的getsnmplist方法将值带回来 然后再调用websocket中的recieveback 将数据传输到websocket中 websocket接收到值就进行发送操作。