运行环境tomcat7以上
1.创建@ServerEndpoint注解类
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpSession;
import javax.websocket.CloseReason;
import javax.websocket.EndpointConfig;
import javax.websocket.OnClose;
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.OnOpen;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value="/echo",configurator=GetHttpSessionConfigurator.class)
public class EndPointServer {
public static List sessionList= new ArrayList();
public Session session ;
@OnOpen
public void onOpen(Session session,EndpointConfig config) throws IOException {
//以下代码省略...
System.out.println("用户"+session.getId()+"链接");
this.session = session;
sessionList.add(this);
HttpSession httpSession= (HttpSession) config.getUserProperties().get(HttpSession.class.getName());
httpSession.setAttribute("scoketSessionId", session.getId());
}
@OnMessage
public void onMessage(Session session,String message) {
}
@OnError
public void onError(Throwable t) {
//以下代码省略...
System.err.println("出错了");
}
@OnClose
public void onClose(Session session, CloseReason reason) {
//以下代码省略...
sessionList.remove(this);
System.out.println(session.getId()+"退出链接");
}
}
OnOpen、OnClose、OnError、OnMessage分别是前端发起链接、关闭链接、出错时、发送消息时的响应事件
configurator用于客户端建立长连接时可以获取httpsession,另外该动作还需要一个ServletRequest监听器和一个ServerEndpointConfig.Configurator子类,如果缺少则会出现httpsession空指针异常。
1)以下是ServletRequest监听器
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
@WebListener
public class RequestListener implements ServletRequestListener {
@Override
public void requestDestroyed(ServletRequestEvent arg0) {
// TODO Auto-generated method stub
}
@Override
public void requestInitialized(ServletRequestEvent arg0) {
((HttpServletRequest) arg0.getServletRequest()).getSession();
}
}
另外web.xml配置监听器
<listener>
<listener-class>包名路径.RequestListenerlistener-class>
listener>
2)以下是ServerEndpointConfig.Configurator子类
import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;
/** * scoket获取session * @author Administrator * */
public class GetHttpSessionConfigurator extends Configurator {
@Override
public void modifyHandshake(ServerEndpointConfig sec,
HandshakeRequest request, HandshakeResponse response) {
// TODO Auto-generated method stub
HttpSession httpSession=(HttpSession) request.getHttpSession();
sec.getUserProperties().put(HttpSession.class.getName(),httpSession);
}
}
2.前端H5 发起webscoket长连接 js代码
<html>
<head>
<meta charset="UTF-8">
<title>WebScoketAPItitle>
head>
<body>
<input type="text" id='msg'/>
<button onclick='tosend()'>发送button>
<button>退出button>
<br>
<textarea id='mymess'>textarea>
body>
<script type="text/javascript" src="js/jquery-1.8.3.min.js">script>
<script type="text/javascript"> var ws = new WebSocket("ws://localhost:8080/WeChatService/echo"); ws.onmessage = function(evt){ console.log(evt.data); $("#mymess").append(evt.data+"
"); }; ws.onerror = function(evt){ console.log("WebSocketError"); }; /* ws.onopen = function(){ ws.send(msg); }; ws.onclose = function(evt){ console.log("WebSocketClosed"); }; */ function tosend(){ var msg=$("#msg").val(); $("#mymess").append(msg+"
"); ws.send(msg); } script>
html>
主要创建WebSocket对象与服务器握手,握手后就会处于长链接状态,当服务器有推送的消息进来时,前端的onmessage方法就会触发
3.使用springMVC 访问URL对某个session推送消息
代码如下:
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpSession;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.xjt.util.JsonUtil;
/** * 推送控制层 * @author Administrator * */
@Controller
public class PushController {
/** * 查询所有在线人员的sid * @param modelMap * @param session * @return */
@ResponseBody
@RequestMapping("getAllOnline")
public String getAllOnline(ModelMap modelMap,HttpSession session){
List ids=new ArrayList();
for (EndPointServer endPointServer : EndPointServer.sessionList) {
ids.add(endPointServer.session.getId());
}
modelMap.put("ids", ids);
return JsonUtil.toJson(modelMap);
}
/** * 向用户发送消息 * @param modelMap * @param session * @param sid * @param msg * @return */
@ResponseBody
@RequestMapping("toSendMsg")
public String toSendMsg(ModelMap modelMap,HttpSession session,String sid,String msg){
if (sid!=null&&sid.length()>0&&msg!=null&&msg.length()>0) {
for (EndPointServer endPointServer : EndPointServer.sessionList) {
if (sid.equals(endPointServer.session.getId())) {
try {
endPointServer.session.getBasicRemote().sendText(msg);
modelMap.put("msg", 1);//发送成功
} catch (IOException e) {
// TODO Auto-generated catch block
modelMap.put("msg", 0);//发送失败
e.printStackTrace();
}
}
}
}else {
modelMap.put("msg", -1);//参数错误
}
return JsonUtil.toJson(modelMap);
}
/** * 广播发送消息 * @param modelMap * @param session * @param msg * @return */
@ResponseBody
@RequestMapping("toBroadCastMsg")
public String toBroadCastMsg(ModelMap modelMap,HttpSession session,String msg){
if (msg!=null&&msg.length()>0) {
for (EndPointServer endPointServer : EndPointServer.sessionList) {
try {
endPointServer.session.getBasicRemote().sendText(msg);
modelMap.put("msg", 1);//发送成功
} catch (IOException e) {
// TODO Auto-generated catch block
modelMap.put("msg", 0);//发送失败
e.printStackTrace();
}
}
}else {
modelMap.put("msg", -1);//参数错误
}
return JsonUtil.toJson(modelMap);
}
/** * 查询所有sid * @param modelMap * @param session * @return */
@ResponseBody
@RequestMapping("getScoketSessionId")
public String getScoketSessionId(ModelMap modelMap,HttpSession session){
if (session.getAttribute("scoketSessionId")!=null) {
modelMap.put("sid", session.getAttribute("scoketSessionId"));
}else {
modelMap.put("sid", "null");
}
return JsonUtil.toJson(modelMap);
}
}
发送消息主要通过websocket.Session类的getBasicRemote().sendText()方法进行推送。
以上代码可以根据需要进行修改,比如分组等、sessionId与业务逻辑实际用户关联,因为可以获取用户的httpsession那么可以做的事情就很多了。
以上代码的汇总来自以下链接,感谢以下资料的提供者:
WebSocket实战
WebSocket之获取HttpSession
Websocket - httpSession returns null
尚学堂_高明鑫史上最易懂Websocket视频教程