Spring整合websocket整合應(yīng)用示例(下)
在Spring整合websocket整合應(yīng)用示例(上)文章中,我們已經(jīng)實(shí)現(xiàn)了websocket,但還有一個(gè)核心的業(yè)務(wù)實(shí)現(xiàn)類(lèi)沒(méi)有實(shí)現(xiàn),這里我們就實(shí)現(xiàn)這個(gè)業(yè)務(wù)核心類(lèi),因?yàn)槔戏騾⑴c的這個(gè)系統(tǒng)使用websocket發(fā)送消息,所以其實(shí)現(xiàn)就是如何發(fā)送消息了。
7. NewsListenerImpl的實(shí)現(xiàn)
package cn.bridgeli.websocket;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.lagou.common.base.util.date.DateUtil;
import com.lagou.platform.news.api.enumeration.PlatNewsCategoryType;
import com.lagou.platform.news.web.dao.ext.model.PlatNewsVo;
import com.lagou.platform.news.web.dao.ext.model.SearchCondition;
import com.lagou.platform.news.web.quartz.impl.TimingJob;
import com.lagou.platform.news.web.service.PlatNewsService;
import org.apache.commons.lang.StringUtils;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.TextMessage;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Description : 站內(nèi)消息監(jiān)聽(tīng)器實(shí)現(xiàn)
* @Date : 16-3-7
*/
@Component
public class NewsListenerImpl implements NewsListener{
private static final Logger logger = LoggerFactory.getLogger(NewsListenerImpl.class);
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
//線(xiàn)程池
private ExecutorService executorService = Executors.newCachedThreadPool();
//任務(wù)調(diào)度
private SchedulerFactory sf = new StdSchedulerFactory();
@Autowired
private PlatNewsService platNewsService;
@Override
public void afterPersist(PlatNewsVo platNewsVo) {
logger.info("監(jiān)聽(tīng)到有新消息添加。。。");
logger.info("新消息為:"+gson.toJson(platNewsVo));
//啟動(dòng)線(xiàn)程
if(null != platNewsVo && !StringUtils.isBlank(platNewsVo.getCurrentoperatoremail())){
//如果是定時(shí)消息
if(platNewsVo.getNewsType() == PlatNewsCategoryType.TIMING_TIME.getCategoryId()){
startTimingTask(platNewsVo); //定時(shí)推送
}else{
//立即推送
executorService.execute(new AfterConnectionEstablishedTask(platNewsVo.getCurrentoperatoremail()));
}
}
}
@Override
public void afterConnectionEstablished(String email) {
logger.info("建立websocket連接后推送新消息。。。");
if(!StringUtils.isBlank(email)){
executorService.execute(new AfterConnectionEstablishedTask(email));
}
}
/**
* @Description : 如果新添加了定時(shí)消息,啟動(dòng)定時(shí)消息任務(wù)
* @param platNewsVo
*/
private void startTimingTask(PlatNewsVo platNewsVo){
logger.info("開(kāi)始定時(shí)推送消息任務(wù)。。。");
Date timingTime = platNewsVo.getTimingTime();
if(null == timingTime){
logger.info("定時(shí)消息時(shí)間為null。");
return;
}
logger.info("定時(shí)推送任務(wù)時(shí)間為:"+DateUtil.date2String(timingTime));
JobDetail jobDetail= JobBuilder.newJob(TimingJob.class)
.withIdentity(platNewsVo.getCurrentoperatoremail()+"定時(shí)消息"+platNewsVo.getId(), "站內(nèi)消息")
.build();
//傳遞參數(shù)
jobDetail.getJobDataMap().put("platNewsService",platNewsService);
jobDetail.getJobDataMap().put("userEmail",platNewsVo.getCurrentoperatoremail());
Trigger trigger= TriggerBuilder
.newTrigger()
.withIdentity("定時(shí)消息觸發(fā)"+platNewsVo.getId(), "站內(nèi)消息")
.startAt(timingTime)
.withSchedule(SimpleScheduleBuilder.simpleSchedule()
.withIntervalInSeconds(0) //時(shí)間間隔
.withRepeatCount(0) //重復(fù)次數(shù)
)
.build();
//啟動(dòng)定時(shí)任務(wù)
try {
Scheduler sched = sf.getScheduler();
sched.scheduleJob(jobDetail,trigger);
if(!sched.isShutdown()){
sched.start();
}
} catch (SchedulerException e) {
logger.info(e.toString());
}
logger.info("完成開(kāi)啟定時(shí)推送消息任務(wù)。。。");
}
/**
* @Description : 建立websocket鏈接后的推送線(xiàn)程
*/
class AfterConnectionEstablishedTask implements Runnable{
String email ;
public AfterConnectionEstablishedTask(String email){
this.email = email;
}
@Override
public void run() {
logger.info("開(kāi)始推送消息給用戶(hù):"+email+"。。。");
if(!StringUtils.isBlank(email)){
SearchCondition searchCondition = new SearchCondition();
searchCondition.setOperatorEmail(email);
JSONArray jsonArray = new JSONArray();
for(PlatNewsCategoryType type : PlatNewsCategoryType.values()){
searchCondition.setTypeId(type.getCategoryId());
int count = platNewsService.countPlatNewsByExample(searchCondition);
JSONObject object = new JSONObject();
object.put("name",type.name());
object.put("description",type.getDescription());
object.put("count",count);
jsonArray.add(object);
}
if(null != jsonArray && jsonArray.size()>0){
UserSocketVo userSocketVo = WSSessionLocalCache.get(email);
TextMessage reMessage = new TextMessage(gson.toJson(jsonArray));
try {
if(null != userSocketVo){
//推送消息
userSocketVo.getWebSocketSession().sendMessage(reMessage);
//更新推送時(shí)間
userSocketVo.setLastSendTime(DateUtil.getNowDate());
logger.info("完成推送新消息給用戶(hù):"+userSocketVo.getUserEmail()+"。。。");
}
} catch (IOException e) {
logger.error(e.toString());
logger.info("站內(nèi)消息推送失敗。。。"+e.toString());
}
}
}
logger.info("結(jié)束推送消息給"+email+"。。。");
}
}
}
這個(gè)類(lèi)就是websocket的核心業(yè)務(wù)的實(shí)現(xiàn),其具體肯定和業(yè)務(wù)相關(guān),由于業(yè)務(wù)的不同,實(shí)現(xiàn)肯定不同,因?yàn)槔戏騾⑴c的系統(tǒng)是發(fā)送消息,所以里面最核心的一句就是:
userSocketVo.getWebSocketSession().sendMessage(reMessage);
通過(guò)WebSocketSession的sendMessage方法把我們的消息發(fā)送出去。另外,這主要是后端的實(shí)現(xiàn),至于前端的實(shí)現(xiàn),因?yàn)槔戏蚴呛蠖顺绦蛟潮容^關(guān)注后端,所以前端就不多做介紹了,大家可以自己去網(wǎng)上查資料。最后需要說(shuō)明的是,老夫之前搜一些學(xué)習(xí)資料的時(shí)候,發(fā)現(xiàn)老夫該同事的寫(xiě)法和有一篇文章幾乎一樣,我想該同事應(yīng)該是參考了這篇文章,所以列在下面,算作參考資料。
- Spring WebSocket 404錯(cuò)誤的解決方法
- Spring和Websocket相結(jié)合實(shí)現(xiàn)消息的推送
- 完美解決spring websocket自動(dòng)斷開(kāi)連接再創(chuàng)建引發(fā)的問(wèn)題
- java中實(shí)現(xiàn)兼容ie6 7 8 9的spring4+websocket
- 詳解WebSocket+spring示例demo(已使用sockJs庫(kù))
- Spring整合WebSocket應(yīng)用示例(上)
- 詳解在Spring Boot框架下使用WebSocket實(shí)現(xiàn)消息推送
- SpringBoot webSocket實(shí)現(xiàn)發(fā)送廣播、點(diǎn)對(duì)點(diǎn)消息和Android接收
- 詳解spring boot Websocket使用筆記
- Spring集成webSocket頁(yè)面訪(fǎng)問(wèn)404問(wèn)題的解決方法
相關(guān)文章
Java中ArrayList去除重復(fù)元素(包括字符串和自定義對(duì)象)
本文主要介紹了Java中ArrayList去除重復(fù)元素(包括字符串和自定義對(duì)象)的方法。具有很好的參考價(jià)值。下面跟著小編一起來(lái)看下吧2017-03-03
SpringBoot?@InitBinder注解綁定請(qǐng)求參數(shù)的過(guò)程詳解
這篇文章主要介紹了SpringBoot?@InitBinder注解綁定請(qǐng)求參數(shù),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04
MyBatis中有關(guān)int和Integer的使用方式
這篇文章主要介紹了MyBatis中有關(guān)int和Integer的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Java面向?qū)ο蠡A(chǔ)知識(shí)之委托和lambda
這篇文章主要介紹了Java面向?qū)ο蟮闹泻?lambda,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很好的幫助,需要的朋友可以參考下2021-11-11
Java中Collection與Collections的區(qū)別詳解
這篇文章主要為大家詳細(xì)介紹了Java中Collection與Collections的區(qū)別,文中有詳細(xì)的代碼示例,具有一定的參考價(jià)值,感興趣的同學(xué)可以參考一下2023-06-06
Java中數(shù)組的使用與注意事項(xiàng)詳解(推薦)
數(shù)組是一組地址連續(xù)、長(zhǎng)度固定的具有相同類(lèi)型的數(shù)據(jù)的集合,通過(guò)數(shù)組下標(biāo)我們可以指定數(shù)字中的每一個(gè)元素,下面這篇文章主要給大家介紹了關(guān)于Java中數(shù)組的使用與注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下2021-08-08

