java实现websocket 终极指南

Posted 咸蛋超人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java实现websocket 终极指南相关的知识,希望对你有一定的参考价值。

1、pom中添加依赖

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
            <version>${spring-version}</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
            <version>${spring-version}</version>
        </dependency>

 2、spring-mvc.xml 中添加websocket拦截

 <websocket:handlers allowed-origins="*">
        <websocket:mapping path="/ws" handler="myHandler"/>
        <websocket:handshake-interceptors>
            <bean class="com.cloudunicomm.interceptor.HandshakeInterceptor"/>
        </websocket:handshake-interceptors>
    </websocket:handlers>

    <bean id="myHandler" class="com.cloudunicomm.interceptor.MySocketHandler"/>

 3、添加MySocketHandler类

package com.cloudunicomm.interceptor;

import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import com.alibaba.fastjson.JSONObject;
import com.cloudunicomm.vo.User;
   
public class MySocketHandler extends TextWebSocketHandler {  
   
	private static final Logger logger = LoggerFactory.getLogger(MySocketHandler.class);
    // 线上人数  
    private static int count;  
    private static CopyOnWriteArraySet<WebSocketSession> set = new CopyOnWriteArraySet<>(); 
    public static Map<String,WebSocketSession> sessionid = new HashMap<String,WebSocketSession>();
    private WebSocketSession session;  
    
    @Autowired
	private RedisTemplate<String,String> redisTemplate;
    
    
    @Override  
    public void afterConnectionEstablished(WebSocketSession session) {  
    	Map<String, Object> map = session.getAttributes();
    	String userid = map.get("userid").toString();
    	sessionid.put(userid, session);
       this.session = session;  
       try{  
           set.add(this.session);  
       }catch(Exception e) {  
           e.printStackTrace();  
       }  
       MySocketHandler.addOnlineCount();  
       System.out.println("目前连接人数:" + getOnlineCount());  
    }  

    public void afterConnectionClosed(WebSocketSession session,CloseStatus closeStatus) {  
       this.session = session;
       String userid = session.getAttributes().get("userid").toString();
       redisTemplate.delete("SEAT_"+userid);
       session.getAttributes().remove("userid");
       set.remove(this.session);  
       subOnlineCount();  
       System.out.println("目前连接人数:" + getOnlineCount());  
    }  
     
    public void handleMessage(WebSocketSession session,WebSocketMessage<?>message){  
       System.out.println("来自客户端消息: "+message.getPayload()+ "_"+ session.getId() ); 
       //发送给所有人
      /* for(WebSocketSession ssion : set) {  
           try {  
              ssion.sendMessage(message); 
           }catch(IOException e) {  
              e.printStackTrace();  
           }  
       } */
       //解析message 修改用户状态
       try{
    	   //id:state,
    	   //username:sip:[email protected]:9060
    	
	       String[] state =   message.getPayload().toString().split("_");
	       ListOperations<String,String> value = redisTemplate.opsForList();
	       String val = value.rightPop("SEAT_"+state[0]).toString();
	       User user = (User)JSONObject.toJavaObject(JSONObject.parseObject(val), User.class);
	       user.setState(Integer.parseInt(state[1]));
	       //实际是解析出来得 现在先写死
	       user.setNext_hop("123.57.144.26:9060/udp");
	       user.setTo("<sip:[email protected]:9060>");
	       String struser = JSONObject.toJSONString(user);
	       value.leftPush("SEAT_"+user.getId().toString(), struser);
       }catch(Exception e){
    	   logger.error(e.getMessage(),e);
       }
    }  
     
    public static int getOnlineCount() {  
       return count;  
    }  
   
    public static void addOnlineCount() {  
       count++;  
    }  
   
    public static void subOnlineCount() {  
       count--;  
    } 
    /** 
     * 给指定连接推消息 
     * @param session 
     * @param message 
     */  
    public String pushMsg(String sessionid, String message){  
        for(WebSocketSession ssion : set) {  
           try {  
               if(sessionid.equals(ssion.getId())){  
                  ssion.sendMessage(new TextMessage(message));  
                  return "机器:" + sessionid+ "推送成功";  
               }  
           }catch(IOException e) {  
               e.printStackTrace();  
           }  
        }  
        return "推送失败";  
    }  
       
    /** 
     * 给全部连接 
     * @param message 
     * @return 
     */  
    public String pushMsg(String message) {  
        int i = 0;  
        for(WebSocketSession ssion : set) {  
           try {  
               ssion.sendMessage(new TextMessage(message));  
               i++;  
           }catch(IOException e) {  
               e.printStackTrace();  
           }  
        }  
        return "共有" + i + "得到推送";  
       }
}  

  4、添加 HandshakeInterceptor 类

 

package com.cloudunicomm.interceptor;

import java.util.Map;

import javax.servlet.http.HttpSession;

import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
   
public class HandshakeInterceptor extends HttpSessionHandshakeInterceptor {  
	  
    /* 
     * 握手前处理动作 
     */  
    @Override  
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler handler,  
           Map<String,Object> map)throws Exception {  
       System.out.println("握手前");  
       
      if(request instanceof ServletServerHttpRequest){
    	   ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
           HttpSession httpSession = servletRequest.getServletRequest().getSession(true);
          if(null != httpSession){
        	// String userid =  httpSession.getAttribute("userid").toString();
        	 String userid = httpSession.getAttribute("userid").toString();
             map.put("userid",userid);
          }
       }
       return super.beforeHandshake(request, response, handler, map);  
    }  
     
    @Override  
    public void afterHandshake(ServerHttpRequest request,ServerHttpResponse response,WebSocketHandler wsHandler,Exception ex) {  
       super.afterHandshake(request, response, wsHandler, ex);  
    }  
 
}  

  5、添加TestController

package com.cloudunicomm.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller  
@RequestMapping("/im")  
public class TestController {  
    
	/*@Bean  
    public MySorketHandle mySorketHandle() {  
       return new MySorketHandle();  
    }  */
	
    @RequestMapping("/page")  
    public String page(HttpServletRequest request, HttpServletResponse response) { 
    
       return "IMpage";  
    }  
    
    /*@ResponseBody  
    @RequestMapping("/push")  
    public String push(@RequestParam(required = false) String sessionId,  
           HttpServletResponse response){  
       String msg= "";  
       if (StringUtils.isEmpty(sessionId)) {  
           msg =mySorketHandle().pushMsg("服务器推送信息了");  
           System.out.println(msg);  
       }else{  
           msg =mySorketHandle().pushMsg(sessionId, "服务器推送信息了");  
           System.out.println(msg);  
       }  
       return msg;  
    }  */
} 

 6、添加 jsp 

<%@ page language="java" contentType="text/html; charset=utf-8"
    pageEncoding="utf-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>  
    <head>  
       <meta charset="UTF-8">  
       <title>socket</title>  
       <script type="text/javascript" src="http://cdn.static.runoob.com/libs/jquery/2.1.1/jquery.min.js"></script>  
    </head>  
    <body>  
       welcome<br />  
       <input id="text" type="text"/>  
       <button onclick="sendMsg()">sendMsg</button>  
       <hr/>  
       <button onclick="closeWebSocket()">close WebSocketconnection</button>  
       <hr/>  
       <div id="message"></div>  
    </body>  
     
    <script type="text/javascript">  
    
       var websocket = null;  
       //判断浏览器是否支持websocket  
       if(‘WebSocket‘ in window) {  
           websocket = new WebSocket("ws://localhost:8081/preSend/websocket");  
       }else{  
           $("#message").html("该浏览器不支持实时通信功能");  
       }  
       window.onbeforeunload = function () {
    	    alert("x帆帆帆帆");
    	   websocket.close();
    	 }
       websocket.onopen= function() {  
           console.log("websocket连接成功");  
       }  
        
       websocket.onclose= function() {  
    	   closewebsocket();
           console.log("websocket连接关闭");  
       }  
        
       websocket.onmessage= function(event) {  
           console.log("接收消息");  
           console.log(event);  
           printMsg(event.data);  
       }  
        
       //打印消息  
       function printMsg(msg) {  
           $("#message").append(msg+ "<br/>");  
       }  
        
       function sendMsg() {  
           var msg = $("#text").val();  
           websocket.send("3_0");
       }  
        
       function closeWebSocket(){  
           websocket.close();  
       } 
       //离线
       function closewebsocket(){
    	   alert("用户离线了");
    	   
       }
       
    </script>  
</html>  

 7、登陆controller

package com.cloudunicomm.controller;

import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.alibaba.fastjson.JSONObject;
import com.cloudunicomm.service.UserService;
import com.cloudunicomm.utils.ResultMessage;
import com.cloudunicomm.vo.User;

@Controller
public class LoginController {
	
	@Autowired
	private UserService userService;
	@Autowired
	private RedisTemplate<String,String> redisTemplate;
	
	@CrossOrigin(origins = "*",maxAge = 3000)
	@RequestMapping("login")
	@ResponseBody
	public ResultMessage login(HttpServletRequest request,HttpServletResponse response,
			@RequestParam(name="username",required=false)String username,
			@RequestParam(name="password",required=false)String password){
		if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){
			return ResultMessage.getFail().setMessage("用户名密码不能为空!");
		}
		User user = userService.AuthUserNmaAndPassword(username,password);
		if(user == null){
			return ResultMessage.getFail().setMessage("用户名密码错误!");
		}
		String str = redisTemplate.opsForList().rightPopAndLeftPush("SEAT_"+user.getId(), "SEAT_"+user.getId());
		if(null != str){
			return ResultMessage.getFail().setMessage("请勿重复登陆!");
		}
		//登陆成功 添加 用户到redis中 islogin修改为在线    state修改为闲
		user.setIslogin(0);
		user.setState(0);
		ListOperations<String,String> redislist = redisTemplate.opsForList();
		String struser = JSONObject.toJSONString(user);
		//从左向右存压栈
		redislist.leftPush("SEAT_"+user.getId().toString(), struser);
		request.getSession().setAttribute("userid", user.getId());
		return ResultMessage.getSuccess().setData(user.getId());
	}
	
	
}

  

 

8、注意事项

  1)项目中又拦截器要注释掉 否则websocket会链接失败

  2)如果是远程调用测试时地址必须是同一个

 

以上是关于java实现websocket 终极指南的主要内容,如果未能解决你的问题,请参考以下文章

使用JMeter进行负载测试——终极指南

Java8新特性终极指南

Java日志终极指南

Java 8新特性终极指南

用Java创建JMeter变量 - 终极指南

数据库实现中文汉字排序终极指南