目录
二、springboot内置定时器调用websocket向客户端发送请求
一、webSocket的基本配置
①、maven依赖部分
<!-- webSocket -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
②、websocket相关的Java代码部分
配置一个WebSocketConfig
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
@Configuration
public class WebSocketConfig {
@Bean
public ServerEndpointExporter serverEndpointExporter() {
return new ServerEndpointExporter();
}
}
配置一个连接类(因为我的需求是消息推送,所有只用到了sendInfo()这个方法,其他的还没研究!!)
import java.io.IOException;
import java.util.concurrent.CopyOnWriteArraySet;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
@RestController
@ServerEndpoint("/websocket")
public class WebSocketServer {
static Logger log=LoggerFactory.getLogger(WebSocketServer.class);
//静态变量,用来记录当前在线连接数。应该把它设计成线程安全的。
private static int onlineCount = 0;
//concurrent包的线程安全Set,用来存放每个客户端对应的MyWebSocket对象。
private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<WebSocketServer>();
//与某个客户端的连接会话,需要通过它来给客户端发送数据
private Session session;
//接收sid
private String sid="";
/**
* 连接建立成功调用的方法*/
@OnOpen
public void onOpen(Session session,@PathParam("sid") String sid) {
//获取地址
// String path = this.getClass().getProtectionDomain().getCodeSource().getLocation().getFile();
//Properties prop = new Properties();
// try {
// //装载配置文件
// //prop.load(new FileInputStream(new File("src/main/resources/application.properties")));
// //prop.load(new FileInputStream(new File(path+"/"+"application.properties")));
// } catch (IOException e) {
// e.printStackTrace();
// }
//返回获取的值
// String req_addr = prop.getProperty("req_addr");
RestTemplate restTemplate = new RestTemplate();
this.session = session;
webSocketSet.add(this); //加入set中
addOnlineCount(); //在线数加1
log.info("有新窗口开始监听:"+sid+",当前在线人数为" + getOnlineCount());
this.sid=sid;
try {
String reslut = restTemplate.postForObject("http://127.0.0.1/f/getmessage",sid,String.class);
sendMessage(reslut);
} catch (IOException e) {
log.error("websocket IO异常");
}
}
/**
* 连接关闭调用的方法
*/
@OnClose
public void onClose() {
webSocketSet.remove(this); //从set中删除
subOnlineCount(); //在线数减1
log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
}
/**
* 收到客户端消息后调用的方法
*
* @param message 客户端发送过来的消息*/
@OnMessage
public void onMessage(String message, Session session) {
log.info("收到来自窗口"+sid+"的信息:"+message);
//群发消息
for (WebSocketServer item : webSocketSet) {
try {
item.sendMessage(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* @param session
* @param error
*/
@OnError
public void onError(Session session, Throwable error) {
log.error("发生错误");
error.printStackTrace();
}
/**
* 实现服务器主动推送
*/
public void sendMessage(String message) throws IOException {
this.session.getBasicRemote().sendText(message);
}
/**
* 群发自定义消息
* */
public static void sendInfo(String message,@PathParam("sid") String sid) throws IOException {
log.info("推送消息到窗口"+sid+",推送内容:"+message);
for (WebSocketServer item : webSocketSet) {
try {
//这里可以设定只推送给这个sid的,为null则全部推送
if(sid==null) {
item.sendMessage(message);
}else if(item.sid.equals(sid)){
item.sendMessage(message);
}
} catch (IOException e) {
continue;
}
}
}
public static synchronized int getOnlineCount() {
return onlineCount;
}
public static synchronized void addOnlineCount() {
WebSocketServer.onlineCount++;
}
public static synchronized void subOnlineCount() {
WebSocketServer.onlineCount--;
}
}
二、springboot内置定时器调用websocket向客户端发送请求
定时器里的内容只是我的业务场景哦,你们只需看调用sendInfo()部分就可,因为我是向所有人提醒,所以sid的值为null,第一个字符串就是对应的message推送内容。
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class Scheduler {
@Autowired
private HolidayetableService holidayetableService;
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");
@Scheduled(cron="0 0/30 21/1 * * ? ")//每天21点开始,每30分钟一次(21:00:00--23:30:00)
//@Scheduled(cron="*/25 * * * * ?")
public void testTasks() throws IOException {
String findstate = holidayetableService.findstate(DateUtils.formatDate(new Date(), "yyyy-MM-dd"));
//为节假日
if("1".equals(findstate)) {
System.err.println("定时任务111执行时间(节假日执行):" + dateFormat.format(new Date()));
WebSocketServer webSocketServer=new WebSocketServer();
webSocketServer.sendInfo("zmjiaban", null);
}else {
System.err.println("定时任务111执行时间(工作日执行):" + dateFormat.format(new Date()));
WebSocketServer webSocketServer=new WebSocketServer();
webSocketServer.sendInfo("jiaban", null);
}
}
}
三、下面开始前端页面部分的代码了
①、js部分代码
这只是我业务场景的代码,其中webSocket.onmessage = function(event){}这个方法中,event.data的值就是刚刚后台发送过来的message的值,你可以根据这个值做各种自己业务上的事情
var webSocket = new WebSocket("ws://127.0.0.1:80/websocket");
webSocket.onopen = function(event){
console.log("连接成功");
//console.log(event);
};
webSocket.onerror = function(event){
console.log("连接失败");
//console.log(event);
};
webSocket.onclose = function(event){
console.log("Socket连接断开");
//console.log(event);
};
webSocket.onmessage = function(event){
//接受来自服务器的消息
var data = event.data;
var usercode = "${usercode}";
if(data!="1"){
var subdata = data.substring(0, 4);
if("jiab"== subdata){//加班登记(工作日加班)
//判断当前是否登记过加班,登记过则不弹提示框
$.post("${ctx}//addworktable/findAddWork",function(data){
if(data=="1"){
return;
}else{
$("#swdiv2").empty();
var newuri="${ctx}";
var val=" <div class=\"swiper-slide\">\n" +
" <a href=\"javascript:void(0)\" class=\"addTabPage\"data-tab-id=\"tabpanel-10qaw53482\" data-title=\"加班登记提醒\"\n" +
" data-href=\""+newuri+"/addworktable/form\">\n" + " <div class=\"img_div\"> \n" +
" <div class=\"img_att2\" style='border-radius:0'> \n" +
" <img src=\"/images/jbdj.png"+"\" class=\"img_size\" /> \n" +
" </div> \n" +
" </div> \n" +
" <div class=\"content_dive\">\n" +
" 请您及时登记今天的加班情况!" +
" </div>\n" +
" </a>\n" +
" </div>";
$("#swdiv2").append(val);
//弹出窗口
$(".fdbody2").animate({height:"show"},800);
bf();//提示音播放
}
})
}
else if("zmji"== subdata){//加班登记(节假日加班)
//判断当前是否登记过加班,登记过则不弹提示框
$.post("${ctx}/addworktable/findzmAddWork",function(data){
console.log(data);
if(data.type=="1"){
return;
}else{
$("#swdiv2").empty();
var newuri="${ctx}";
var val=" <div class=\"swiper-slide\">\n" +
" <a href=\"javascript:void(0)\" class=\"addTabPage\"data-tab-id=\"tabpanel-10qaw53482\" data-title=\"加班登记提醒\"\n" +
" data-href=\""+newuri+"/addworktable/form?id="+data.id+"\">\n" + " <div class=\"img_div\"> \n" +
" <div class=\"img_att2\" style='border-radius:0'> \n" +
" <img src=\"/static/images/jbdj.png"+"\" class=\"img_size\" /> \n" +
" </div> \n" +
" </div> \n" +
" <div class=\"content_dive\">\n" +
" 请您及时登记今天的加班情况!" +
" </div>\n" +
" </a>\n" +
" </div>";
$("#swdiv2").append(val);
//弹出窗口
$(".fdbody2").animate({height:"show"},800);
bf();//提示音播放
}
})
}
}
//myAuto.stop();
// myAuto.play();
}
②、html代码部分,即弹窗页面
<style>
.fdbody2{
display:none;
z-index: 1002;
background-image: none;
width: 330px;
height:172px;
background: #00c0ef;
border-right: 1px solid #78a3d2;
position:fixed;
bottom: 1px;
right:10px;
border: 1px solid #4e86c4;
}
.img_ioc2{
width:12px;
height:12px;
margin-top: -11px
}
</style>
<div id="jiaban" data-num="3" class="fdbody2">
<div style="color: #FFF; padding: 6px;">
<div style="margin: 0;height: 14px;width:14px;margin-top: 4px;" onmouseout="this.className='editor_close2';"
onmouseover="this.className='editor_close_mover2';"
class="editor_close2">
<img ondragstart="return false;" class="img_ioc2" src="${ctxStatic}/images/ico_closetip.gif">
</div>
<b style="font-size: 13px">加班登记提醒</b>
<audio src="${ctxStatic}/audio/audio.mp3" controls="controls" preload id="music1" hidden>
<span id="bf" onclick="bf();">播放/暂停</span>
</div>
<div style="background:#FFF; line-height:1.5;">
<div style="min-height: 97px">
<div class="swiper-container">
<div class="swiper-wrapper" id="swdiv2">
</div>
</div>
</div>
</div>
</div>
所有的代码基本上都是这些了,欢迎大佬们提出意见啊!!