JAVA前后端实现WebSocket消息推送(针对性推送)

JAVA前后端实现WebSocket消息推送(针对性推送)

1、需要添加依赖包,在pom.xml文件中添加

			

	javax
        javaee-api
	7.0
	provided


2、客户端代码

在这里我为了做成httpsession登录后是同一个,所以我做成两个页面,一个登录跳转页面,一个用于链接WebSocket接收消息

a.登录页面




	
		
		WebSocket
		
		
	

	
		
		tiaozhuan
	


b.接收消息推送页面




	
		
		WebSocket
		
		
	

	
		

3、关于后端代码这边事由4个文件

一个通用msg文件、一个用于获取当前会话的httpsession、一个用监听有没有httpsession(没有则创建)、一个用于WebSocket链接和发送消息

a.通用msg文件

package com.boli.srcoin.websocket;

import java.util.Date;

/**
 * @author : admin
* @DESC :

WebSocket消息模型


*/ public class Msg { // 推送人ID private String fromUid; // 定点推送人ID private String toUid; // 定点推送单位ID private String toOrgId; // 消息体 private String data; // 推送时间 private Date createDate = new Date(); // 消息状态 private Integer flag; public Msg() { } public Msg(String fromUid, String toUid, String toOrgId, String data, Date createDate, Integer flag) { this.fromUid = fromUid; this.toUid = toUid; this.toOrgId = toOrgId; this.data = data; this.createDate = createDate; this.flag = flag; } public String getFromUid() { return fromUid; } public void setFromUid(String fromUid) { this.fromUid = fromUid; } public String getToUid() { return toUid; } public void setToUid(String toUid) { this.toUid = toUid; } public String getToOrgId() { return toOrgId; } public void setToOrgId(String toOrgId) { this.toOrgId = toOrgId; } public String getData() { return data; } public void setData(String data) { this.data = data; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public Integer getFlag() { return flag; } public void setFlag(Integer flag) { this.flag = flag; } @Override public String toString() { return "Msg{" + "fromUid='" + fromUid + '\'' + ", toUid='" + toUid + '\'' + ", toOrgId='" + toOrgId + '\'' + ", data='" + data + '\'' + ", createDate=" + createDate + ", flag=" + flag + '}'; } }

b.用于在WebSocket或去httpsession

package com.boli.srcoin.websocket;

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;

/**
 * @author : admin
* @DESC :

讲http request的session 存入websocket的session内


*/ public class HttpSessionConfigurator extends Configurator { @Override public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) { // 获取当前Http连接的session HttpSession httpSession = (HttpSession) request.getHttpSession(); // 将http session信息注入websocket session sec.getUserProperties().put(HttpSession.class.getName(), httpSession); } }

c.用于监听有没有httpsession,没有则创建

package com.boli.srcoin.websocket;

import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;

@WebListener
public class RequestListener implements ServletRequestListener {
    
    public void requestInitialized(ServletRequestEvent sre)  { 
        //将所有request请求都携带上httpSession
        ((HttpServletRequest) sre.getServletRequest()).getSession();
        
    }
    public RequestListener() {
        // TODO Auto-generated constructor stub
    }

    public void requestDestroyed(ServletRequestEvent arg0)  { 
         // TODO Auto-generated method stub
    }
}

d.接收WebSocket链接和发送消息

package com.boli.srcoin.websocket;

import com.alibaba.fastjson.JSON;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

import javax.servlet.http.HttpSession;
import javax.websocket.*;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

/**
 * @author : admin
* @DESC :

注解{@link ServerEndpoint}声明websocket 服务端


*/ @ServerEndpoint(value = "/chat", configurator = HttpSessionConfigurator.class) public class WSServer { static private Logger logger = Logger.getLogger(WSServer.class); // 在线人数 线程安全 private static int onlineCount = 0; // 连接集合 userId => server 键值对 线程安全 static public final ConcurrentMap map = new ConcurrentHashMap<>(); // 与某个客户端的连接会话,需要通过它来给客户端发送数据 private Session session; // 当前会话的httpsession private HttpSession httpSession; /** * @param session websocket连接sesson * @param config {@link com.github.websocket.configuration.HttpSessionConfigurator} * @DESC

注解{@link OnOpen} 声明客户端连接进入的方法

*/ @OnOpen public void onOpen(Session session, EndpointConfig config) { // 得到httpSession this.httpSession = (HttpSession) config.getUserProperties().get(HttpSession.class.getName()); // 获取session对象 SObject(这个就是java web登入后的保存的session对象,此处为用户信息,包含了userId) String user = (String) this.httpSession.getAttribute("user"); this.session = session; System.out.println(user+"-------"+this.session.getId()); //针对一个用户只能有一个链接 if(map.get(user)!=null){ // 移除连接 map.remove(user); // 连接数-1 subOnlineCount(); } // 将连接session对象存入map map.put(user, this); // 连接数+1 addOnlineCount(); logger.info("有新的连接,当前连接数为:" + getOnlineCount()); } /** *

{@link OnClose} 关闭连接

*/ @OnClose public void onClose() { /** * 获取当前连接信息 {@code CommonConstant.USER_LOGIN_SESSION} 为Http session 名 */ String user = (String) this.httpSession.getAttribute("user"); // 移除连接 map.remove(user); // 连接数-1 subOnlineCount(); logger.info("有一连接断开,当前连接数为:" + getOnlineCount()); } /** *

{@link OnMessage} 消息监听处理方法

* * @param message 消息对象{@link com.github.websocket.msg.Msg}的JSON对象 * @throws IOException 异常 */ @OnMessage public void onMessage(String message) throws IOException { // 将消息转Msg对象 Msg msg = JSON.parseObject(message, Msg.class); //TODO 可以对msg做些处理... // 根据Msg消息对象获取定点发送人的userId WSServer _client = map.get(msg.getToUid()); // 定点发送 if (StringUtils.isNotEmpty(msg.getToUid())) { if (null != _client) { // 是否连接判断 if (_client.session.isOpen()) // 消息发送 _client.session.getBasicRemote().sendText(JSON.toJSONString(msg)); } } // 群发 if (StringUtils.isEmpty(msg.getToUid())) { // 群发已连接用户 for (WSServer client : map.values()) { client.session.getBasicRemote().sendText(JSON.toJSONString(msg)); } } } /** *

{@link OnError} websocket系统异常处理

* * @param t 异常 */ @OnError public void onError(Throwable t) { logger.error(t); t.printStackTrace(); } /** *

系统主动推送 这是个静态方法在web启动后可在程序的其他合适的地方和时间调用,这就实现了系统的主动推送

* * @param msg 消息对象{@link com.github.websocket.msg.Msg}的JSON对象 */ static public void pushBySys(Msg msg) { //TODO 也可以实现定点推送 //msg传输的时候会带上需要发送消息给谁msg.getToUid() //通过map去获取那个用户所在的session WSServer ws=map.get(msg.getToUid()); try { if(ws!=null){ ws.session.getBasicRemote().sendText("123456"); } } catch (IOException e1) { e1.printStackTrace(); } // 群发 /*for (WSServer client : map.values()) { try { client.session.getBasicRemote().sendText(JSON.toJSONString(msg)); } catch (IOException e) { e.printStackTrace(); } }*/ } // 获取连接数 private static synchronized int getOnlineCount() { return WSServer.onlineCount; } // 增加连接数 private static synchronized void addOnlineCount() { WSServer.onlineCount++; } // 减少连接数 private static synchronized void subOnlineCount() { WSServer.onlineCount--; } }


4、在后端的调用,也就是登录和调用发送消息

package com.boli.srcoin.member.service.impl;

import java.util.HashMap;
import java.util.Map;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.boli.framework.system.result.StandardResult;
import com.boli.framework.utils.WebUtil;
import com.boli.srcoin.member.form.MemberLoginForm;
import com.boli.srcoin.member.service.LoginMemberService;
import com.boli.srcoin.websocket.Msg;
import com.boli.srcoin.websocket.WSServer;

@Service
public class LoginMemberServiceImpl implements LoginMemberService{
	
	@Override
	@Transactional(readOnly = false)
	public StandardResult toLogin(MemberLoginForm loginForm) {
		WebUtil.getSession().setAttribute("user", loginForm.getUser());
		Map map=new HashMap<>();
		map.put("sessionId", WebUtil.getSession().getId());
		map.put("user", loginForm.getUser());
		System.out.println("调用登录方法:"+WebUtil.getSession().getId()+loginForm.getUser());
		return StandardResult.ok(map);
	}
	
	@Override
	@Transactional(readOnly = false)
	public StandardResult tishi() {
		Msg msg=new Msg();
		msg.setToUid("ppp");
		WSServer.pushBySys(msg);
		return StandardResult.ok();
	}
	

}

5、调用结果如图

JAVA前后端实现WebSocket消息推送(针对性推送)_第1张图片

JAVA前后端实现WebSocket消息推送(针对性推送)_第2张图片

JAVA前后端实现WebSocket消息推送(针对性推送)_第3张图片

附带源码链接:http://download.csdn.net/download/qq_31151929/10207702


你可能感兴趣的:(java,websocket,httpsession)