webSocket+定时任务实时通知前台变化

后台发生变化时,可以通过实事件触发或者是定时任务,此处用的是定时任务
1、WebSocketConfig配置类:

/**
 * @program: wealth_management
 * @description: WebSocketConfig配置类
 * @author: SGQ
 * @create: 2019/04/23
 */
@Configuration
public class WebSocketConfig {
    @Bean
    public ServerEndpointExporter serverEndpointExporter() {
        return new ServerEndpointExporter();
    }
}

2、WebSocketServer服务端,给前端调用:

/**
 * @program: wealth.product.service
 * @description: WebSocketServer核心类-实时获取产品剩余额度
 * @author: SGQ
 * @create: 2019/05/15
 */
@ServerEndpoint("/product/webSocket/RemainAmountServer/{appointmentId}/{productCode}")
@Component
public class RemainAmountWebSocketServer {
    private static final Logger logger = LoggerFactory.getLogger(RemainAmountWebSocketServer.class);

    // 解决WebSocket不能注入的问题
    private static ApplicationContext applicationContext;

    public static void setApplicationContext(ApplicationContext context) {
        applicationContext = context;
    }

    private ProductService productService;

    //静态变量,用来记录当前在线连接数
    private static int onlineCount = 0;
    //ConcurrentHashMap的线程安全map,用来存放每个客户端对应的MyWebSocket对象。
    private static ConcurrentHashMap<String, RemainAmountWebSocketServer> socketMap = new ConcurrentHashMap<>();

    private static ConcurrentHashMap<String, TaskScheduler> taskMap = new ConcurrentHashMap<>();

    //与某个客户端的连接会话,需要通过它来给客户端发送数据
    private Session session;

    //接收appointmentId
    private String appointmentId = "";


    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("appointmentId") String appointmentId, @PathParam("productCode") String productCode) {
        this.session = session;
        socketMap.put(appointmentId, this); // 添加到Map中
        addOnlineCount();           //在线数加1
        this.appointmentId = appointmentId;
        logger.info("有新窗口开始监听:" + appointmentId + ",当前在线人数为" + getOnlineCount());
        try {
            // 获得service实例
            productService = applicationContext.getBean(ProductServiceImpl.class);
            ResponseCommonType responseCommonType = new ResponseCommonType();
            responseCommonType.setSuccess(false);
            ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
            scheduler.initialize(); // 初始化
            TaskScheduler task = new TaskScheduler(scheduler);
            task.startCron(new Runnable() {
                @Override
                public void run() {
                    logger.info("系统轮询获取剩余额度中。。。");
                    RemainAmountDTO remainAmountDTO = productService.getProductRemainAmount(productCode);
                    if (remainAmountDTO == null) {
                        responseCommonType.setSuccess(false);
                        responseCommonType.setResponseMessage(appointmentId + ":failed");
                        responseCommonType.setData("无此产品");
                    } else {
                        responseCommonType.setSuccess(true);
                        responseCommonType.setResponseMessage(appointmentId + ":success");
                        responseCommonType.setData(remainAmountDTO);
                    }
                    sendInfo(JSON.toJSONString(responseCommonType), appointmentId);
                }
            }, new CronTrigger("0/2 * * * * *"));
            // 在关闭连接时关闭定时任务
            taskMap.put(appointmentId, task);
        } catch (Exception e) {
            logger.error("websocket 异常:" + e.toString(), e);
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        socketMap.remove(appointmentId);  //从map中删除
        if (taskMap.get(appointmentId) != null) {
            taskMap.get(appointmentId).stopCron();
            taskMap.remove(appointmentId);
            logger.info("轮询任务关闭:" + appointmentId);
        }
        subOnlineCount();           //在线数减1
        logger.info("有一连接关闭!当前在线人数为" + getOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, Session session) {
        logger.info("收到来自窗口" + appointmentId + "的信息:" + message);
        //群发消息
        for (Map.Entry<String, RemainAmountWebSocketServer> entry : socketMap.entrySet()) {
            try {
                entry.getValue().sendMessage(message);
            } catch (Exception e) {
                logger.error("收到客户端消息后调用的方法 error:" + e.toString(), e);
            }
        }
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        logger.error("发生错误:" + error.toString(), error);
    }

    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) {
        try {
            this.session.getBasicRemote().sendText(message);
        } catch (Exception e) {
            logger.error("sendMessage error: " + e.toString(), e);
        }

    }


    /**
     * 群发自定义消息
     */
    public static void sendInfo(String message, String appointId) {
        try {
            //这里可以设定只推送给这个sid的,为null则全部推送
            if (StringUtils.isEmpty(appointId)) {
                for (Map.Entry<String, RemainAmountWebSocketServer> entry : socketMap.entrySet()) {
                    entry.getValue().sendMessage(message);
                }
            } else {
                socketMap.get(appointId).sendMessage(message);
            }
        } catch (Exception e) {
            logger.error("推送消息到窗口 error: " + e.toString(), e);
        }
        logger.info("推送消息到窗口" + appointId + ",推送内容:" + message);

    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        RemainAmountWebSocketServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        RemainAmountWebSocketServer.onlineCount--;
    }
}

3、定时任务task:

/**
 * @program: demo
 * @description: 定时任务处理类
 * @author: SGQ
 * @create: 2019/04/25
 */

public class TaskScheduler {
    private static final Logger logger = LoggerFactory.getLogger(TaskScheduler.class);

    private ThreadPoolTaskScheduler threadPoolTaskScheduler;

    /**
     * 在ScheduledFuture中有一个cancel可以停止定时任务。
     */
    private ScheduledFuture<?> future;

    public TaskScheduler(ThreadPoolTaskScheduler threadPoolTaskScheduler) {
        this.threadPoolTaskScheduler = threadPoolTaskScheduler;
    }


    /**
     * 启动任务
     **/

    public void startCron(Runnable runnable, CronTrigger cronTrigger) {
        logger.info("TaskScheduler#startCron()");
        future = threadPoolTaskScheduler.schedule(runnable, cronTrigger);
    }

    /**
     * 停止任务
     **/
    public void stopCron() {
        logger.info("TaskScheduler#stopCron()");
        if (future != null) {
            future.cancel(true);
        }
    }

    /**
     * 变更任务间隔,再次启动
     **/

    public void changeCron(Runnable runnable, CronTrigger cronTrigger) {
        logger.info("TaskScheduler#changeCron()");
        stopCron();// 先停止,在开启.
        future = threadPoolTaskScheduler.schedule(runnable, cronTrigger);
    }
}
  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值