1. maven 引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>javax.websocket</groupId>
<artifactId>javax.websocket-api</artifactId>
<version>1.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>7.0</version>
</dependency>
2. 编写map转换器,其实如果需要传递给页面一个map,需要把map转换成json【fastJson】格式
public class EncoderUtil implements Encoder.Text<Map<String, Object>>{
@Override
public void destroy() {}
@Override
public void init(EndpointConfig arg0) {}
@Override
public String encode(Map<String, Object> map) throws EncodeException {
return JSON.toJSONString(map);
}
}
3. 编写获取httpSession的配置,在webSocket获取session中用户登陆信息
public class GetHttpSessionConfigurator extends Configurator{
@Override
public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) {
HttpSession httpSession = (HttpSession)request.getHttpSession();
sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}
4. 编写webSocket,需要注意的是在这里无法注入service,我的做法是把查出来的数据封装好,调用webSocket推送数据
@Component
@ServerEndpoint(value ="/ws/webSocket",
encoders = { EncoderUtil.class },
configurator = GetHttpSessionConfigurator.class)
public class WebSocket {
private Session session;
private HttpSession httpSession;
private SysUser user;
private String username;
private static final Logger log = LoggerFactory.getLogger(WebSocket.class);
private static CopyOnWriteArraySet<WebSocket> webSocketSet = new CopyOnWriteArraySet<WebSocket>();
private static Map<String,Session> sessionMap = new ConcurrentHashMap<String,Session>();
@OnOpen
public void onOpen(Session session,EndpointConfig config) {
this.session = session;
webSocketSet.add(this);
httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
if(httpSession != null){
this.user = (SysUser) httpSession.getAttribute("login_user");
this.username = this.user.getUsername();
//log.info("【websocket消息】 user:{}",user);
sessionMap.put(this.username, session);
}
log.info("【websocket消息】 有新的连接,总数:{}",webSocketSet.size());
}
@OnClose
public void onClose() {
webSocketSet.remove(this);
sessionMap.remove(this.username);
log.info("【websocket消息】连接断开,总数:"+webSocketSet.size());
}
@OnMessage
public void onMessage(String message) throws IOException,InterruptedException {
log.info("【websocket消息】 收到客户端发来的消息:{}",message);
}
public void sendMessage(String message){
for (WebSocket webSocket : webSocketSet) {
log.info("【websocket消息】 广播消息:{}",message);
try {
webSocket.session.getBasicRemote().sendText(message);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* <p>Description: TODO</p>
* <p>Company: 梧州学院</p>
* @author 胡宇鹏
* @date 2018年1月23日 上午10:29:45
* @param json
* @param plagMusicFlag 播放声音标记:0.不播放 1.播放
*/
public void sendMessage(Map<String, Object> json,Integer plagMusicFlag) {
if(plagMusicFlag == null){
json.put("plagMusicFlag",0);
}
json.put("plagMusicFlag", plagMusicFlag);
for (WebSocket webSocket : webSocketSet) {
log.info("【websocket消息】 广播消息:map");
try {
webSocket.session.getBasicRemote().sendObject(json);
} catch (EncodeException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*
* <p>Description: 单独发送信息给指定的用户</p>
* <p>Company: 梧州学院</p>
* @author 胡宇鹏
* @date 2018年1月23日 上午10:29:04
* @param userList
* @param json 需要接收信息的用户集合
* @param plagMusicFlag 播放声音标记:0.不播放 1.播放
*/
public void sendMessage(List<SysUser> userList,Map<String, Object> json,Integer plagMusicFlag) {
if(userList.size() == 0 && json.size() > 0){
// 说明是拒绝的情况
sendMessage(json,0);
return ;
}
json.put("plagMusicFlag", plagMusicFlag);
if(plagMusicFlag == null){
json.put("plagMusicFlag",1);
}
Iterator<Entry<String,Session>> entries = sessionMap.entrySet().iterator();
while (entries.hasNext()) {
Map.Entry<String,Session> entry = entries.next();
for (SysUser user : userList) {
if(user.getUsername().equals(entry.getKey())){
try {
entry.getValue().getBasicRemote().sendObject(json);
continue;
} catch (IOException e) {
e.printStackTrace();
} catch (EncodeException e) {
e.printStackTrace();
}
}
}
}
}
public void sendMessage(SysUser user,Map<String, Object> json,Integer plagMusicFlag){
List<SysUser> userList = new ArrayList<SysUser>();
userList.add(user);
sendMessage(userList,json,plagMusicFlag);
}
}
5. 在service注入了webSocket之后直接调用webSocket.sendMessage(...)方法主动推送数据,根据个人的项目需要编写sendMessage(...)这个方法。其实也就是执行了增、删等操作的时候主动刷新待处理消息提示,在这里就不演示了
6. 编写webSocket.js,比如我在左侧的菜单栏引入了这个js
(function(){
var websocket = null;
//var url = '127.0.0.1:8080/cl'; // 本地测试
function getProjectPath(){
//获取当前网址,如: http://localhost:8083/uimcardprj/share/meun.jsp
var curWwwPath = window.document.location.href;
//获取主机地址之后的目录,如: uimcardprj/share/meun.jsp
var pathName = window.document.location.pathname;
var pos = curWwwPath.indexOf(pathName);
//获取主机地址,如: http://localhost:8083
var localhostPaht = curWwwPath.substring(7, pos); // 去除http://
//获取带"/"的项目名,如:/uimcardprj
var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1);
return (localhostPaht + projectName);
}
if('WebSocket' in window) {
websocket = new WebSocket('ws://' + getProjectPath() + '/ws/webSocket');
}else {
layer.msg('该浏览器不支持websocket!');
}
websocket.onopen = function (event) {
console.log('建立连接');
};
websocket.onclose = function (event) {
console.log('连接关闭');
};
websocket.onmessage = function (event) {
//console.log('收到消息:' + event.data);
var result = eval('(' + event.data + ')');
buildHtmlWaitCount(result.fAppr,"#waitFApprCount");
buildHtmlWaitCount(result.sAppr,"#waitSApprCount");
buildHtmlWaitCount(result.tAppr,"#waitTApprCount");
buildHtmlWaitCount(result.sch,"#waitSchCount");
buildHtmlWaitCount(result.rc,"#waitRCCount");
if(result.plagMusicFlag == 1){
document.getElementById('schTip').play(); // 播放声音
}
};
websocket.onerror = function () {
layer.msg('websocket通信发生错误!');
};
window.onbeforeunload = function () {
websocket.close();
};
function buildHtmlWaitCount(num,id){
if(num > 0){
$(id).html(num);
return;
}
$(id).html("");
}
})();