java spring整合websocket

这几天项目中需要整合websocket来支持业务,从网上看了好多资料。但是都很杂乱,我尝试了好多回,走了很多弯路,跳了很多坑~~~~~~。通过两天的调试终于成功!!!现在把调试步骤和容易出现的问题都列出来,让和我这样的新手有点帮助。开始上代码.........

备注:spring的版本4.0+ ,tomcat :7.50 + , jdk:1.8

java Spring 整合 websocket 有两种方法 :

1:配置方法 [网上有很多]

(地址:http://blog.csdn.net/stickallthetime/article/details/44587413     这位大哥写的很详细)

2:注解方法 [推荐使用这种方法,简洁。我用的就是这种方法]

第一步:pom文件添加jar包

<!-- WEB SOCKET API -->
  <dependency>
     <groupId>javax.websocket</groupId>
     <artifactId>javax.websocket-api</artifactId>
     <version>1.0</version>
     <scope>provided</scope>
   </dependency>
  <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>

第二步:添加 websocket 配置

@Configuration
@EnableWebMvc
@EnableWebSocket
public class WebSocketConfig extends WebMvcConfigurerAdapter implements WebSocketConfigurer{ 
    @Override 
    public void registerWebSocketHandlers(WebSocketHandlerRegistry registry) {
     System.out.println("......注册......");

//这个类的标红的代码 解释 问题2

        //配置webSocket路径 
        registry.addHandler(systemWebSocketHandler(),"/websocket").addInterceptors(new MyHandshakeInterceptor()).setAllowedOrigins("*");

        //配置webSocket路径 支持前端使用socketJs
        registry.addHandler(systemWebSocketHandler(), "/sockjs/websocket").setAllowedOrigins("*").addInterceptors(new MyHandshakeInterceptor()).withSockJS();
    }
    @Bean 
    public WebSocketHandler systemWebSocketHandler(){
     System.out.println("......创建WebSocketHandler......");
        return new SystemWebSocketHandler(); 
    } 
}

public class MyHandshakeInterceptor extends HttpSessionHandshakeInterceptor{ 
 @Override 
    public boolean beforeHandshake(ServerHttpRequest request, 
            ServerHttpResponse response, WebSocketHandler wsHandler, 
            Map<String, Object> attributes) throws Exception { 
        logger.info("Before Handshake");  

//获得 session 和request对象(解释问题3)
        ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
        //获得session
//  HttpSession session = servletRequest.getServletRequest().getSession(false);
        //获得httpServletRequest
        HttpServletRequest httpRequest = servletRequest.getServletRequest();
        return super.beforeHandshake(request, response, wsHandler, attributes);
    }
    @Override 
    public void afterHandshake(ServerHttpRequest request, 
            ServerHttpResponse response, WebSocketHandler wsHandler, 
            Exception ex) { 
        logger.info("After Handshake"); 
        super.afterHandshake(request, response, wsHandler, ex); 
    }
}

public class SystemWebSocketHandler implements WebSocketHandler {
   public SystemWebSocketHandler(){}
   private static final ArrayList<WebSocketSession> users = new ArrayList<WebSocketSession>();
   @Override
   public void afterConnectionEstablished(WebSocketSession session) throws Exception {
    System.out.println("......连接之后After......"+"ConnectionEstablished");
    System.out.println("getId:" + session.getId());
    System.out.println("getLocalAddress:" + session.getLocalAddress().toString());
    System.out.println("getUri:" + session.getUri().toString());
    System.out.println("getPrincipal:" + session.getPrincipal());
    //连接进来的用户添加到用户集合中方便以后发送消息
    users.add(session);
    session.sendMessage(new TextMessage("你好:  webSocket connect 成功!!!"));
   }
   @Override
   public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
    System.out.println("发送信息" + message.toString()+" .session. "+session.getId());
    session.sendMessage(new TextMessage(message.getPayload()+"---"+ReportUtils.long2DateString(System.currentTimeMillis(), ReportUtils.FORMAT_DATE_TIME) + ""));
   }
   @Override
   public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
       if(session.isOpen()){
           session.close();
       }
       users.remove(session);
       System.out.println("异常出现handleTransportError" + exception.getMessage());
   }
   @Override
   public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) throws Exception {
       users.remove(session);
       System.out.println("关闭afterConnectionClosed" + closeStatus.getReason());
   }
   @Override
   public boolean supportsPartialMessages() {
       return false;
   }

   /**
    * 给所有在线用户发送消息
    *
    * @param message
    */
   public void sendMessageToUsers(TextMessage message) {
       for (WebSocketSession user : users) {
           try {
               if (user.isOpen()) {
                   user.sendMessage(message);
               }
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }
   /**
    * 给指定用户发消息
    * @param username
    * @param message
    */
   public void sendMessageToUser(String username,TextMessage message) {
  for (WebSocketSession user : users) {
   if (user.getAttributes().get("username").equals(username)) {
    try {
     if (user.isOpen()) {
      user.sendMessage(message);
     }
    } catch (IOException e) {
     e.printStackTrace();
    }
    break;
   }
  }
 }
}

第三步:页面clinet

<!DOCTYPE HTML>
<html>
  <head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>My WebSocket</title>
  </head>
  <body>
    Welcome<br/>
    <input id="text" type="text" /><button onclick="send()">Send</button>    <button onclick="closeWebSocket()">Close</button>
    <div id="message">
    </div>
  </body>
  <script type="text/javascript">
      var websocket = null;
      //判断当前浏览器是否支持WebSocket
      if('WebSocket' in window){
       //                    路径+端口号                    项目名         webSocket路径
       var wsPath = window.location.host + "/ipos-mobile/websocket";
       var param = "?token=123&aid=a2s2";
       console.info(wsPath + param);
          websocket = new WebSocket("ws://"+wsPath+param);
      }
      else{
          alert('Not support websocket')
      }
      //连接发生错误的回调方法
      websocket.onerror = function(){
          setMessageInnerHTML("error");
      };
      //连接成功建立的回调方法
      websocket.onopen = function(event){
          setMessageInnerHTML("页面clinet打开websocket连接-----open");
      }
      //接收到消息的回调方法
      websocket.onmessage = function(){
          setMessageInnerHTML(event.data);
      }
      //连接关闭的回调方法
      websocket.onclose = function(){
          setMessageInnerHTML("页面clinet关闭websocket连接-----close");
      }
      //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
      window.onbeforeunload = function(){
          websocket.close();
      }
      //将消息显示在网页上
      function setMessageInnerHTML(innerHTML){
          document.getElementById('message').innerHTML += innerHTML + '<br/>';
      }
      //关闭连接
      function closeWebSocket(){
          websocket.close();
      }
      //发送消息
      function send(){
          var message = document.getElementById('text').value;
          websocket.send(message);
      }
  </script>
</html>

 到此websocket 已经配置完成。搭建过程中出现很多问题,下面把我遇到的问题公布一下:

问题1:

页面client 连接 websocket 的时候经常出现的问题 

404:路径错误,仔细看一下。

403:先看一下路径,要是路径没问题,那看看你的项目中的filter 是不是把websocket的路劲拦截了

400:后台肯定是报错啦,看一下什么问题,解决一下就好了。

【这三个4开头的问题大部分都是和 webSocket的路径被拦截有关系 仔细看一下filtere】

问题2:

你的项目已经跑通了,在本机也能运行起来了,但是局域网不能访问(就是localhost 能访问,但是ip地址就访问不了

答案在 【第二步 webSocket 配置有解释 移步】

 问题3:

怎么在webSocket中获得session  或者是httpServletRequest 答案在【第二步 websocket配置解释 移步】

本页内容版权归属为原作者,如有侵犯您的权益,请通知我们删除。

Java命令行classpath的设置 - 2016-09-21 17:09:03

在练习JavaDB Embedded模式的Java编程时候,直接用编辑器开发,所以需要用平时不怎么用的命令行来编译代码,按照普通的方式进行编译之后,开始运行,结果弹出错误提示。 java -classpath derby.jar JavaDBTest 错误: 找不到或无法加载主类 JavaDBTest 想不通是怎么回事。后来发现,需要将当前目录也加入到ClassPath中 java -classpath .;derby.jar JavaDBTest 这样才能成功运行 Load the EmbeddedDri

java 虚拟机-内存管理 - 2016-09-21 14:09:23

      本地方法 非java代码实现的java方法,使用native关键字,除abstract外可与java关键字连用 程序计数器 可以看作是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支,循环,跳转,异常处理,线程恢复等基础功能。该区域时java虚拟机规范中没有规定outofmeroryError情况的区域 虚拟机栈   1、生命周期同线程一致 2、程序员通常指的栈内存区,更确切的是指虚拟机栈中的局部变量表部分 3、局部变量表存
jAVA基础 提高文件复制性能之多线程复制文件 利用IO流中的随机访问文件 RandomAccessFile 和文件通道 FileChanne 复制文件可大大提高文件的读写效率,在此基础上利用多线程复制文件使其性能更优。因线程的个数可根据文件的大小及需求而定。其大概原理是根据给定的线程个数,将文件分段,每个线程负责的数据大小=文件长度/线程个数,将不能除尽的部分留给最后一段文件所分配的线程处理。以下是实现代码及自己理解的注释,多有偏差请见谅。下面是兄弟连java培训总结的一些代码:供参考。 程序实现类代码
这个是我一个技术相当好的哥们去面试的时候碰到的奇葩问题,那天,这个面试官的答案是不能。后来就带着这个问题去国内外的论坛上搜了一把,也是各说纷纭,实在是没有一个统一的答案,简直有点公说公有理,婆说婆有理的架势。     几个意见大致如下,第一,不能,因为“进程是CPU进行调度的单位,而JVM是一个进程,于是就只能跑在一个CPU上”。第二,“进程是CPU进行调度的单位,这没错,但是OS负责将一个进程在不同的CPU上调度到另外一个CPU上,而这个进程,则是由不同的线程构成的,那么说,线程还是在不同的CPU上运行了
1、一个简单的订单号生成器: 从代码可以看出: long orderNo = (Long.parseLong((date))) * 10000;   orderNo += orderNum + Long.parseLong(RandomStringUtils.randomNumeric(3)); 每毫秒可以保证,10000-999个订单号不重复。     import java.text.SimpleDateFormat;import java.util.Date;import org.apache.co
Java是世界上最流行的程序语言,从1995年问世以来,Java的生态系统在一直在蓬勃的发展着。作为一门健壮的技术,Java社区为广大开发者提供了包括框架、库、web开发sdk、JVM语言等资源。在各种科技行业都能够找到关于Java编程的相关资源,这就是为什么Java会如此受人喜爱。 在今天,发达的网络技术推动了Java的发展,越来越多的人选择在网上学习,查看技术大牛的博客并进行交流成为了日常学习的一个重要手段。在这里,我整理了国外最流行的十大Java技术博客,它们都是由Java技术专家维护的,无论是初学
druid是号称目前最好的java数据库连接池,温少写点代码中有很多设计模式的思想,其中最重要的一个就是filter-chain设计模式给druid所带来的可扩展性。对此,我很感兴趣,并希望日后借鉴,所以看了看他的源码,以此记录一下。 druid中设计到filter-chain设计模式的类或接口主要有一下几个Filter、FilterAdapter、FilterChain、FilterChainImpl、FilterEventAdapter、FilterManager 以及举例讲讲两个具体的filter:

mysql外键实战 - 2016-09-21 14:09:05

一、基本概念 1、MySQL中“键”和“索引”的定义相同,所以外键和主键一样也是索引的一种。不同的是MySQL会自动为所有表的主键进行索引,但是外键字段必须由用户进行明确的索引。用于外键关系的字段必须在所有的参照表中进行明确地索引,InnoDB不能自动地创建索引。 2、外键可以是一对一的,一个表的记录只能与另一个表的一条记录连接,或者是一对多的,一个表的记录与另一个表的多条记录连接。 3、如果需要更好的性能,并且不需要完整性检查,可以选择使用MyISAM表类型,如果想要在MySQL中根据参照完整性来建立表
会联网前沿技术文档,各大公司技术架构,欢迎各位浏览!!!网址: http://dwz.cn/4bwqKb  

Java的文件读写操作 - 2016-09-20 18:09:14

file(内存)----输入流----【程序】----输出流----file(内存) 当我们读写文本文件的时候,采用Reader是非常方便的,比如FileReader,InputStreamReader和BufferedReader。其中最重要的类是InputStreamReader, 它是字节转换为字符的桥梁。你可以在构造器重指定编码的方式,如果不指定的话将采用底层操作系统的默认编码方式,例如GBK等。使用FileReader读取文件: FileReader fr = new FileReader("mi