├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── README.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── cictec │ │ └── stomp │ │ ├── RabbitmqApplication.java │ │ ├── config │ │ └── ProducerConfig.java │ │ └── controller │ │ └── ProducerMessage.java └── resources │ ├── application.properties │ └── static │ ├── demo.html │ ├── inner.html │ ├── js │ ├── jquery.js │ ├── sockjs.js │ └── stomp.js │ └── test.html └── test └── java └── com └── cictec └── stomp └── RabbitmqApplicationTests.java /.gitignore: -------------------------------------------------------------------------------- 1 | /target/ 2 | !.mvn/wrapper/maven-wrapper.jar 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | .sts4-cache 12 | 13 | ### IntelliJ IDEA ### 14 | .idea 15 | *.iws 16 | *.iml 17 | *.ipr 18 | 19 | ### NetBeans ### 20 | /nbproject/private/ 21 | /build/ 22 | /nbbuild/ 23 | /dist/ 24 | /nbdist/ 25 | /.nb-gradle/ -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hzoboy/rabbitmq-websocket/d6659e66064d6e737d8ef35196c4e83ca1526584/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rabbitmq-websocket 2 | JavaScript连接rabbitmq 3 | -------------------------------------------------------------------------------- /mvnw: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # ---------------------------------------------------------------------------- 3 | # Licensed to the Apache Software Foundation (ASF) under one 4 | # or more contributor license agreements. See the NOTICE file 5 | # distributed with this work for additional information 6 | # regarding copyright ownership. The ASF licenses this file 7 | # to you under the Apache License, Version 2.0 (the 8 | # "License"); you may not use this file except in compliance 9 | # with the License. You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, 14 | # software distributed under the License is distributed on an 15 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | # KIND, either express or implied. See the License for the 17 | # specific language governing permissions and limitations 18 | # under the License. 19 | # ---------------------------------------------------------------------------- 20 | 21 | # ---------------------------------------------------------------------------- 22 | # Maven2 Start Up Batch script 23 | # 24 | # Required ENV vars: 25 | # ------------------ 26 | # JAVA_HOME - location of a JDK home dir 27 | # 28 | # Optional ENV vars 29 | # ----------------- 30 | # M2_HOME - location of maven2's installed home dir 31 | # MAVEN_OPTS - parameters passed to the Java VM when running Maven 32 | # e.g. to debug Maven itself, use 33 | # set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 34 | # MAVEN_SKIP_RC - flag to disable loading of mavenrc files 35 | # ---------------------------------------------------------------------------- 36 | 37 | if [ -z "$MAVEN_SKIP_RC" ] ; then 38 | 39 | if [ -f /etc/mavenrc ] ; then 40 | . /etc/mavenrc 41 | fi 42 | 43 | if [ -f "$HOME/.mavenrc" ] ; then 44 | . "$HOME/.mavenrc" 45 | fi 46 | 47 | fi 48 | 49 | # OS specific support. $var _must_ be set to either true or false. 50 | cygwin=false; 51 | darwin=false; 52 | mingw=false 53 | case "`uname`" in 54 | CYGWIN*) cygwin=true ;; 55 | MINGW*) mingw=true;; 56 | Darwin*) darwin=true 57 | # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home 58 | # See https://developer.apple.com/library/mac/qa/qa1170/_index.html 59 | if [ -z "$JAVA_HOME" ]; then 60 | if [ -x "/usr/libexec/java_home" ]; then 61 | export JAVA_HOME="`/usr/libexec/java_home`" 62 | else 63 | export JAVA_HOME="/Library/Java/Home" 64 | fi 65 | fi 66 | ;; 67 | esac 68 | 69 | if [ -z "$JAVA_HOME" ] ; then 70 | if [ -r /etc/gentoo-release ] ; then 71 | JAVA_HOME=`java-config --jre-home` 72 | fi 73 | fi 74 | 75 | if [ -z "$M2_HOME" ] ; then 76 | ## resolve links - $0 may be a link to maven's home 77 | PRG="$0" 78 | 79 | # need this for relative symlinks 80 | while [ -h "$PRG" ] ; do 81 | ls=`ls -ld "$PRG"` 82 | link=`expr "$ls" : '.*-> \(.*\)$'` 83 | if expr "$link" : '/.*' > /dev/null; then 84 | PRG="$link" 85 | else 86 | PRG="`dirname "$PRG"`/$link" 87 | fi 88 | done 89 | 90 | saveddir=`pwd` 91 | 92 | M2_HOME=`dirname "$PRG"`/.. 93 | 94 | # make it fully qualified 95 | M2_HOME=`cd "$M2_HOME" && pwd` 96 | 97 | cd "$saveddir" 98 | # echo Using m2 at $M2_HOME 99 | fi 100 | 101 | # For Cygwin, ensure paths are in UNIX format before anything is touched 102 | if $cygwin ; then 103 | [ -n "$M2_HOME" ] && 104 | M2_HOME=`cygpath --unix "$M2_HOME"` 105 | [ -n "$JAVA_HOME" ] && 106 | JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 107 | [ -n "$CLASSPATH" ] && 108 | CLASSPATH=`cygpath --path --unix "$CLASSPATH"` 109 | fi 110 | 111 | # For Migwn, ensure paths are in UNIX format before anything is touched 112 | if $mingw ; then 113 | [ -n "$M2_HOME" ] && 114 | M2_HOME="`(cd "$M2_HOME"; pwd)`" 115 | [ -n "$JAVA_HOME" ] && 116 | JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`" 117 | # TODO classpath? 118 | fi 119 | 120 | if [ -z "$JAVA_HOME" ]; then 121 | javaExecutable="`which javac`" 122 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then 123 | # readlink(1) is not available as standard on Solaris 10. 124 | readLink=`which readlink` 125 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then 126 | if $darwin ; then 127 | javaHome="`dirname \"$javaExecutable\"`" 128 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" 129 | else 130 | javaExecutable="`readlink -f \"$javaExecutable\"`" 131 | fi 132 | javaHome="`dirname \"$javaExecutable\"`" 133 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 134 | JAVA_HOME="$javaHome" 135 | export JAVA_HOME 136 | fi 137 | fi 138 | fi 139 | 140 | if [ -z "$JAVACMD" ] ; then 141 | if [ -n "$JAVA_HOME" ] ; then 142 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 143 | # IBM's JDK on AIX uses strange locations for the executables 144 | JAVACMD="$JAVA_HOME/jre/sh/java" 145 | else 146 | JAVACMD="$JAVA_HOME/bin/java" 147 | fi 148 | else 149 | JAVACMD="`which java`" 150 | fi 151 | fi 152 | 153 | if [ ! -x "$JAVACMD" ] ; then 154 | echo "Error: JAVA_HOME is not defined correctly." >&2 155 | echo " We cannot execute $JAVACMD" >&2 156 | exit 1 157 | fi 158 | 159 | if [ -z "$JAVA_HOME" ] ; then 160 | echo "Warning: JAVA_HOME environment variable is not set." 161 | fi 162 | 163 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher 164 | 165 | # traverses directory structure from process work directory to filesystem root 166 | # first directory with .mvn subdirectory is considered project base directory 167 | find_maven_basedir() { 168 | 169 | if [ -z "$1" ] 170 | then 171 | echo "Path not specified to find_maven_basedir" 172 | return 1 173 | fi 174 | 175 | basedir="$1" 176 | wdir="$1" 177 | while [ "$wdir" != '/' ] ; do 178 | if [ -d "$wdir"/.mvn ] ; then 179 | basedir=$wdir 180 | break 181 | fi 182 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) 183 | if [ -d "${wdir}" ]; then 184 | wdir=`cd "$wdir/.."; pwd` 185 | fi 186 | # end of workaround 187 | done 188 | echo "${basedir}" 189 | } 190 | 191 | # concatenates all lines of a file 192 | concat_lines() { 193 | if [ -f "$1" ]; then 194 | echo "$(tr -s '\n' ' ' < "$1")" 195 | fi 196 | } 197 | 198 | BASE_DIR=`find_maven_basedir "$(pwd)"` 199 | if [ -z "$BASE_DIR" ]; then 200 | exit 1; 201 | fi 202 | 203 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} 204 | echo $MAVEN_PROJECTBASEDIR 205 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" 206 | 207 | # For Cygwin, switch paths to Windows format before running java 208 | if $cygwin; then 209 | [ -n "$M2_HOME" ] && 210 | M2_HOME=`cygpath --path --windows "$M2_HOME"` 211 | [ -n "$JAVA_HOME" ] && 212 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` 213 | [ -n "$CLASSPATH" ] && 214 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` 215 | [ -n "$MAVEN_PROJECTBASEDIR" ] && 216 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` 217 | fi 218 | 219 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 220 | 221 | exec "$JAVACMD" \ 222 | $MAVEN_OPTS \ 223 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ 224 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ 225 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" 226 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | @REM ---------------------------------------------------------------------------- 2 | @REM Licensed to the Apache Software Foundation (ASF) under one 3 | @REM or more contributor license agreements. See the NOTICE file 4 | @REM distributed with this work for additional information 5 | @REM regarding copyright ownership. The ASF licenses this file 6 | @REM to you under the Apache License, Version 2.0 (the 7 | @REM "License"); you may not use this file except in compliance 8 | @REM with the License. You may obtain a copy of the License at 9 | @REM 10 | @REM http://www.apache.org/licenses/LICENSE-2.0 11 | @REM 12 | @REM Unless required by applicable law or agreed to in writing, 13 | @REM software distributed under the License is distributed on an 14 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | @REM KIND, either express or implied. See the License for the 16 | @REM specific language governing permissions and limitations 17 | @REM under the License. 18 | @REM ---------------------------------------------------------------------------- 19 | 20 | @REM ---------------------------------------------------------------------------- 21 | @REM Maven2 Start Up Batch script 22 | @REM 23 | @REM Required ENV vars: 24 | @REM JAVA_HOME - location of a JDK home dir 25 | @REM 26 | @REM Optional ENV vars 27 | @REM M2_HOME - location of maven2's installed home dir 28 | @REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands 29 | @REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending 30 | @REM MAVEN_OPTS - parameters passed to the Java VM when running Maven 31 | @REM e.g. to debug Maven itself, use 32 | @REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 33 | @REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files 34 | @REM ---------------------------------------------------------------------------- 35 | 36 | @REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on' 37 | @echo off 38 | @REM enable echoing my setting MAVEN_BATCH_ECHO to 'on' 39 | @if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO% 40 | 41 | @REM set %HOME% to equivalent of $HOME 42 | if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%") 43 | 44 | @REM Execute a user defined script before this one 45 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre 46 | @REM check for pre script, once with legacy .bat ending and once with .cmd ending 47 | if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat" 48 | if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd" 49 | :skipRcPre 50 | 51 | @setlocal 52 | 53 | set ERROR_CODE=0 54 | 55 | @REM To isolate internal variables from possible post scripts, we use another setlocal 56 | @setlocal 57 | 58 | @REM ==== START VALIDATION ==== 59 | if not "%JAVA_HOME%" == "" goto OkJHome 60 | 61 | echo. 62 | echo Error: JAVA_HOME not found in your environment. >&2 63 | echo Please set the JAVA_HOME variable in your environment to match the >&2 64 | echo location of your Java installation. >&2 65 | echo. 66 | goto error 67 | 68 | :OkJHome 69 | if exist "%JAVA_HOME%\bin\java.exe" goto init 70 | 71 | echo. 72 | echo Error: JAVA_HOME is set to an invalid directory. >&2 73 | echo JAVA_HOME = "%JAVA_HOME%" >&2 74 | echo Please set the JAVA_HOME variable in your environment to match the >&2 75 | echo location of your Java installation. >&2 76 | echo. 77 | goto error 78 | 79 | @REM ==== END VALIDATION ==== 80 | 81 | :init 82 | 83 | @REM Find the project base dir, i.e. the directory that contains the folder ".mvn". 84 | @REM Fallback to current working directory if not found. 85 | 86 | set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR% 87 | IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir 88 | 89 | set EXEC_DIR=%CD% 90 | set WDIR=%EXEC_DIR% 91 | :findBaseDir 92 | IF EXIST "%WDIR%"\.mvn goto baseDirFound 93 | cd .. 94 | IF "%WDIR%"=="%CD%" goto baseDirNotFound 95 | set WDIR=%CD% 96 | goto findBaseDir 97 | 98 | :baseDirFound 99 | set MAVEN_PROJECTBASEDIR=%WDIR% 100 | cd "%EXEC_DIR%" 101 | goto endDetectBaseDir 102 | 103 | :baseDirNotFound 104 | set MAVEN_PROJECTBASEDIR=%EXEC_DIR% 105 | cd "%EXEC_DIR%" 106 | 107 | :endDetectBaseDir 108 | 109 | IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig 110 | 111 | @setlocal EnableExtensions EnableDelayedExpansion 112 | for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a 113 | @endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS% 114 | 115 | :endReadAdditionalConfig 116 | 117 | SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe" 118 | 119 | set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar" 120 | set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain 121 | 122 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* 123 | if ERRORLEVEL 1 goto error 124 | goto end 125 | 126 | :error 127 | set ERROR_CODE=1 128 | 129 | :end 130 | @endlocal & set ERROR_CODE=%ERROR_CODE% 131 | 132 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost 133 | @REM check for post script, once with legacy .bat ending and once with .cmd ending 134 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" 135 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" 136 | :skipRcPost 137 | 138 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' 139 | if "%MAVEN_BATCH_PAUSE%" == "on" pause 140 | 141 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% 142 | 143 | exit /B %ERROR_CODE% 144 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | com.cictec.stomp 7 | rabbitmq 8 | 0.0.1-SNAPSHOT 9 | jar 10 | 11 | rabbitmq 12 | Demo project for Spring Boot 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.6.RELEASE 18 | 19 | 20 | 21 | 22 | UTF-8 23 | UTF-8 24 | 1.8 25 | 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-web 31 | 32 | 33 | 34 | org.springframework.boot 35 | spring-boot-starter-test 36 | test 37 | 38 | 39 | org.springframework.boot 40 | spring-boot-starter-amqp 41 | 42 | 43 | 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-maven-plugin 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /src/main/java/com/cictec/stomp/RabbitmqApplication.java: -------------------------------------------------------------------------------- 1 | package com.cictec.stomp; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class RabbitmqApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(RabbitmqApplication.class, args); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/com/cictec/stomp/config/ProducerConfig.java: -------------------------------------------------------------------------------- 1 | //package com.cictec.stomp.config; 2 | // 3 | //import org.springframework.amqp.core.Binding; 4 | //import org.springframework.amqp.core.BindingBuilder; 5 | //import org.springframework.amqp.core.Queue; 6 | //import org.springframework.amqp.core.TopicExchange; 7 | //import org.springframework.beans.factory.annotation.Qualifier; 8 | //import org.springframework.context.annotation.Bean; 9 | //import org.springframework.context.annotation.Configuration; 10 | // 11 | ///** 12 | // * @author :zoboy 13 | // * @Description: 14 | // * @ Date: Created in 2018-10-25 09:43 15 | // */ 16 | //@Configuration 17 | //public class ProducerConfig { 18 | // 19 | // @Bean(name="message") 20 | // public Queue queueMessage() { 21 | // return new Queue("message"); 22 | // } 23 | // 24 | // @Bean 25 | // public TopicExchange exchange() { 26 | // return new TopicExchange("exchange"); 27 | // } 28 | // 29 | // @Bean 30 | // Binding bindingExchangeMessage(@Qualifier("message") Queue queueMessage, TopicExchange exchange) { 31 | // return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message"); 32 | // } 33 | //} 34 | -------------------------------------------------------------------------------- /src/main/java/com/cictec/stomp/controller/ProducerMessage.java: -------------------------------------------------------------------------------- 1 | package com.cictec.stomp.controller; 2 | 3 | import org.springframework.amqp.core.AmqpTemplate; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.web.bind.annotation.GetMapping; 6 | import org.springframework.web.bind.annotation.PathVariable; 7 | import org.springframework.web.bind.annotation.RestController; 8 | 9 | /** 10 | * @author :zoboy 11 | * @Description: 12 | * @ Date: Created in 2018-10-25 09:52 13 | */ 14 | @RestController 15 | public class ProducerMessage { 16 | 17 | 18 | @Autowired 19 | private AmqpTemplate template; 20 | 21 | @GetMapping("/send/{message}") 22 | public String send(@PathVariable String message){ 23 | template.convertAndSend("exchange","test",message); 24 | return "success"; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=7070 2 | 3 | spring.rabbitmq.host=192.168.10.182 4 | spring.rabbitmq.port=5672 5 | spring.rabbitmq.username=admin 6 | spring.rabbitmq.password=123456 -------------------------------------------------------------------------------- /src/main/resources/static/demo.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | WebSocket 4 | 5 | 6 | 7 |
8 |
9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 | 68 | -------------------------------------------------------------------------------- /src/main/resources/static/inner.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 |
6 |
7 | 8 | 9 | 10 | 11 | 12 | 13 | 63 | -------------------------------------------------------------------------------- /src/main/resources/static/js/stomp.js: -------------------------------------------------------------------------------- 1 | // Generated by CoffeeScript 1.7.1 2 | 3 | /* 4 | Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0 5 | 6 | Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/) 7 | Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com) 8 | */ 9 | 10 | (function() { 11 | var Byte, Client, Frame, Stomp, 12 | __hasProp = {}.hasOwnProperty, 13 | __slice = [].slice; 14 | 15 | Byte = { 16 | LF: '\x0A', 17 | NULL: '\x00' 18 | }; 19 | 20 | Frame = (function() { 21 | var unmarshallSingle; 22 | 23 | function Frame(command, headers, body) { 24 | this.command = command; 25 | this.headers = headers != null ? headers : {}; 26 | this.body = body != null ? body : ''; 27 | } 28 | 29 | Frame.prototype.toString = function() { 30 | var lines, name, skipContentLength, value, _ref; 31 | lines = [this.command]; 32 | skipContentLength = this.headers['content-length'] === false ? true : false; 33 | if (skipContentLength) { 34 | delete this.headers['content-length']; 35 | } 36 | _ref = this.headers; 37 | for (name in _ref) { 38 | if (!__hasProp.call(_ref, name)) continue; 39 | value = _ref[name]; 40 | lines.push("" + name + ":" + value); 41 | } 42 | if (this.body && !skipContentLength) { 43 | lines.push("content-length:" + (Frame.sizeOfUTF8(this.body))); 44 | } 45 | lines.push(Byte.LF + this.body); 46 | return lines.join(Byte.LF); 47 | }; 48 | 49 | Frame.sizeOfUTF8 = function(s) { 50 | if (s) { 51 | return encodeURI(s).match(/%..|./g).length; 52 | } else { 53 | return 0; 54 | } 55 | }; 56 | 57 | unmarshallSingle = function(data) { 58 | var body, chr, command, divider, headerLines, headers, i, idx, len, line, start, trim, _i, _j, _len, _ref, _ref1; 59 | divider = data.search(RegExp("" + Byte.LF + Byte.LF)); 60 | headerLines = data.substring(0, divider).split(Byte.LF); 61 | command = headerLines.shift(); 62 | headers = {}; 63 | trim = function(str) { 64 | return str.replace(/^\s+|\s+$/g, ''); 65 | }; 66 | _ref = headerLines.reverse(); 67 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 68 | line = _ref[_i]; 69 | idx = line.indexOf(':'); 70 | headers[trim(line.substring(0, idx))] = trim(line.substring(idx + 1)); 71 | } 72 | body = ''; 73 | start = divider + 2; 74 | if (headers['content-length']) { 75 | len = parseInt(headers['content-length']); 76 | body = ('' + data).substring(start, start + len); 77 | } else { 78 | chr = null; 79 | for (i = _j = start, _ref1 = data.length; start <= _ref1 ? _j < _ref1 : _j > _ref1; i = start <= _ref1 ? ++_j : --_j) { 80 | chr = data.charAt(i); 81 | if (chr === Byte.NULL) { 82 | break; 83 | } 84 | body += chr; 85 | } 86 | } 87 | return new Frame(command, headers, body); 88 | }; 89 | 90 | Frame.unmarshall = function(datas) { 91 | var frame, frames, last_frame, r; 92 | frames = datas.split(RegExp("" + Byte.NULL + Byte.LF + "*")); 93 | r = { 94 | frames: [], 95 | partial: '' 96 | }; 97 | r.frames = (function() { 98 | var _i, _len, _ref, _results; 99 | _ref = frames.slice(0, -1); 100 | _results = []; 101 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 102 | frame = _ref[_i]; 103 | _results.push(unmarshallSingle(frame)); 104 | } 105 | return _results; 106 | })(); 107 | last_frame = frames.slice(-1)[0]; 108 | if (last_frame === Byte.LF || (last_frame.search(RegExp("" + Byte.NULL + Byte.LF + "*$"))) !== -1) { 109 | r.frames.push(unmarshallSingle(last_frame)); 110 | } else { 111 | r.partial = last_frame; 112 | } 113 | return r; 114 | }; 115 | 116 | Frame.marshall = function(command, headers, body) { 117 | var frame; 118 | frame = new Frame(command, headers, body); 119 | return frame.toString() + Byte.NULL; 120 | }; 121 | 122 | return Frame; 123 | 124 | })(); 125 | 126 | Client = (function() { 127 | var now; 128 | 129 | function Client(ws) { 130 | this.ws = ws; 131 | this.ws.binaryType = "arraybuffer"; 132 | this.counter = 0; 133 | this.connected = false; 134 | this.heartbeat = { 135 | outgoing: 10000, 136 | incoming: 10000 137 | }; 138 | this.maxWebSocketFrameSize = 16 * 1024; 139 | this.subscriptions = {}; 140 | this.partialData = ''; 141 | } 142 | 143 | Client.prototype.debug = function(message) { 144 | var _ref; 145 | return typeof window !== "undefined" && window !== null ? (_ref = window.console) != null ? _ref.log(message) : void 0 : void 0; 146 | }; 147 | 148 | now = function() { 149 | if (Date.now) { 150 | return Date.now(); 151 | } else { 152 | return new Date().valueOf; 153 | } 154 | }; 155 | 156 | Client.prototype._transmit = function(command, headers, body) { 157 | var out; 158 | out = Frame.marshall(command, headers, body); 159 | if (typeof this.debug === "function") { 160 | this.debug(">>> " + out); 161 | } 162 | while (true) { 163 | if (out.length > this.maxWebSocketFrameSize) { 164 | this.ws.send(out.substring(0, this.maxWebSocketFrameSize)); 165 | out = out.substring(this.maxWebSocketFrameSize); 166 | if (typeof this.debug === "function") { 167 | this.debug("remaining = " + out.length); 168 | } 169 | } else { 170 | return this.ws.send(out); 171 | } 172 | } 173 | }; 174 | 175 | Client.prototype._setupHeartbeat = function(headers) { 176 | var serverIncoming, serverOutgoing, ttl, v, _ref, _ref1; 177 | if ((_ref = headers.version) !== Stomp.VERSIONS.V1_1 && _ref !== Stomp.VERSIONS.V1_2) { 178 | return; 179 | } 180 | _ref1 = (function() { 181 | var _i, _len, _ref1, _results; 182 | _ref1 = headers['heart-beat'].split(","); 183 | _results = []; 184 | for (_i = 0, _len = _ref1.length; _i < _len; _i++) { 185 | v = _ref1[_i]; 186 | _results.push(parseInt(v)); 187 | } 188 | return _results; 189 | })(), serverOutgoing = _ref1[0], serverIncoming = _ref1[1]; 190 | if (!(this.heartbeat.outgoing === 0 || serverIncoming === 0)) { 191 | ttl = Math.max(this.heartbeat.outgoing, serverIncoming); 192 | if (typeof this.debug === "function") { 193 | this.debug("send PING every " + ttl + "ms"); 194 | } 195 | this.pinger = Stomp.setInterval(ttl, (function(_this) { 196 | return function() { 197 | _this.ws.send(Byte.LF); 198 | return typeof _this.debug === "function" ? _this.debug(">>> PING") : void 0; 199 | }; 200 | })(this)); 201 | } 202 | if (!(this.heartbeat.incoming === 0 || serverOutgoing === 0)) { 203 | ttl = Math.max(this.heartbeat.incoming, serverOutgoing); 204 | if (typeof this.debug === "function") { 205 | this.debug("check PONG every " + ttl + "ms"); 206 | } 207 | return this.ponger = Stomp.setInterval(ttl, (function(_this) { 208 | return function() { 209 | var delta; 210 | delta = now() - _this.serverActivity; 211 | if (delta > ttl * 2) { 212 | if (typeof _this.debug === "function") { 213 | _this.debug("did not receive server activity for the last " + delta + "ms"); 214 | } 215 | return _this.ws.close(); 216 | } 217 | }; 218 | })(this)); 219 | } 220 | }; 221 | 222 | Client.prototype._parseConnect = function() { 223 | var args, connectCallback, errorCallback, headers; 224 | args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 225 | headers = {}; 226 | switch (args.length) { 227 | case 2: 228 | headers = args[0], connectCallback = args[1]; 229 | break; 230 | case 3: 231 | if (args[1] instanceof Function) { 232 | headers = args[0], connectCallback = args[1], errorCallback = args[2]; 233 | } else { 234 | headers.login = args[0], headers.passcode = args[1], connectCallback = args[2]; 235 | } 236 | break; 237 | case 4: 238 | headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3]; 239 | break; 240 | default: 241 | headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3], headers.host = args[4]; 242 | } 243 | return [headers, connectCallback, errorCallback]; 244 | }; 245 | 246 | Client.prototype.connect = function() { 247 | var args, errorCallback, headers, out; 248 | args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; 249 | out = this._parseConnect.apply(this, args); 250 | headers = out[0], this.connectCallback = out[1], errorCallback = out[2]; 251 | if (typeof this.debug === "function") { 252 | this.debug("Opening Web Socket..."); 253 | } 254 | this.ws.onmessage = (function(_this) { 255 | return function(evt) { 256 | var arr, c, client, data, frame, messageID, onreceive, subscription, unmarshalledData, _i, _len, _ref, _results; 257 | data = typeof ArrayBuffer !== 'undefined' && evt.data instanceof ArrayBuffer ? (arr = new Uint8Array(evt.data), typeof _this.debug === "function" ? _this.debug("--- got data length: " + arr.length) : void 0, ((function() { 258 | var _i, _len, _results; 259 | _results = []; 260 | for (_i = 0, _len = arr.length; _i < _len; _i++) { 261 | c = arr[_i]; 262 | _results.push(String.fromCharCode(c)); 263 | } 264 | return _results; 265 | })()).join('')) : evt.data; 266 | _this.serverActivity = now(); 267 | if (data === Byte.LF) { 268 | if (typeof _this.debug === "function") { 269 | _this.debug("<<< PONG"); 270 | } 271 | return; 272 | } 273 | if (typeof _this.debug === "function") { 274 | _this.debug("<<< " + data); 275 | } 276 | unmarshalledData = Frame.unmarshall(_this.partialData + data); 277 | _this.partialData = unmarshalledData.partial; 278 | _ref = unmarshalledData.frames; 279 | _results = []; 280 | for (_i = 0, _len = _ref.length; _i < _len; _i++) { 281 | frame = _ref[_i]; 282 | switch (frame.command) { 283 | case "CONNECTED": 284 | if (typeof _this.debug === "function") { 285 | _this.debug("connected to server " + frame.headers.server); 286 | } 287 | _this.connected = true; 288 | _this._setupHeartbeat(frame.headers); 289 | _results.push(typeof _this.connectCallback === "function" ? _this.connectCallback(frame) : void 0); 290 | break; 291 | case "MESSAGE": 292 | subscription = frame.headers.subscription; 293 | onreceive = _this.subscriptions[subscription] || _this.onreceive; 294 | if (onreceive) { 295 | client = _this; 296 | messageID = frame.headers["message-id"]; 297 | frame.ack = function(headers) { 298 | if (headers == null) { 299 | headers = {}; 300 | } 301 | return client.ack(messageID, subscription, headers); 302 | }; 303 | frame.nack = function(headers) { 304 | if (headers == null) { 305 | headers = {}; 306 | } 307 | return client.nack(messageID, subscription, headers); 308 | }; 309 | _results.push(onreceive(frame)); 310 | } else { 311 | _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled received MESSAGE: " + frame) : void 0); 312 | } 313 | break; 314 | case "RECEIPT": 315 | _results.push(typeof _this.onreceipt === "function" ? _this.onreceipt(frame) : void 0); 316 | break; 317 | case "ERROR": 318 | _results.push(typeof errorCallback === "function" ? errorCallback(frame) : void 0); 319 | break; 320 | default: 321 | _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled frame: " + frame) : void 0); 322 | } 323 | } 324 | return _results; 325 | }; 326 | })(this); 327 | this.ws.onclose = (function(_this) { 328 | return function() { 329 | var msg; 330 | msg = "Whoops! Lost connection to " + _this.ws.url; 331 | if (typeof _this.debug === "function") { 332 | _this.debug(msg); 333 | } 334 | _this._cleanUp(); 335 | return typeof errorCallback === "function" ? errorCallback(msg) : void 0; 336 | }; 337 | })(this); 338 | return this.ws.onopen = (function(_this) { 339 | return function() { 340 | if (typeof _this.debug === "function") { 341 | _this.debug('Web Socket Opened...'); 342 | } 343 | headers["accept-version"] = Stomp.VERSIONS.supportedVersions(); 344 | headers["heart-beat"] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(','); 345 | return _this._transmit("CONNECT", headers); 346 | }; 347 | })(this); 348 | }; 349 | 350 | Client.prototype.disconnect = function(disconnectCallback, headers) { 351 | if (headers == null) { 352 | headers = {}; 353 | } 354 | this._transmit("DISCONNECT", headers); 355 | this.ws.onclose = null; 356 | this.ws.close(); 357 | this._cleanUp(); 358 | return typeof disconnectCallback === "function" ? disconnectCallback() : void 0; 359 | }; 360 | 361 | Client.prototype._cleanUp = function() { 362 | this.connected = false; 363 | if (this.pinger) { 364 | Stomp.clearInterval(this.pinger); 365 | } 366 | if (this.ponger) { 367 | return Stomp.clearInterval(this.ponger); 368 | } 369 | }; 370 | 371 | Client.prototype.send = function(destination, headers, body) { 372 | if (headers == null) { 373 | headers = {}; 374 | } 375 | if (body == null) { 376 | body = ''; 377 | } 378 | headers.destination = destination; 379 | return this._transmit("SEND", headers, body); 380 | }; 381 | 382 | Client.prototype.subscribe = function(destination, callback, headers) { 383 | var client; 384 | if (headers == null) { 385 | headers = {}; 386 | } 387 | if (!headers.id) { 388 | headers.id = "sub-" + this.counter++; 389 | } 390 | headers.destination = destination; 391 | this.subscriptions[headers.id] = callback; 392 | this._transmit("SUBSCRIBE", headers); 393 | client = this; 394 | return { 395 | id: headers.id, 396 | unsubscribe: function() { 397 | return client.unsubscribe(headers.id); 398 | } 399 | }; 400 | }; 401 | 402 | Client.prototype.unsubscribe = function(id) { 403 | delete this.subscriptions[id]; 404 | return this._transmit("UNSUBSCRIBE", { 405 | id: id 406 | }); 407 | }; 408 | 409 | Client.prototype.begin = function(transaction) { 410 | var client, txid; 411 | txid = transaction || "tx-" + this.counter++; 412 | this._transmit("BEGIN", { 413 | transaction: txid 414 | }); 415 | client = this; 416 | return { 417 | id: txid, 418 | commit: function() { 419 | return client.commit(txid); 420 | }, 421 | abort: function() { 422 | return client.abort(txid); 423 | } 424 | }; 425 | }; 426 | 427 | Client.prototype.commit = function(transaction) { 428 | return this._transmit("COMMIT", { 429 | transaction: transaction 430 | }); 431 | }; 432 | 433 | Client.prototype.abort = function(transaction) { 434 | return this._transmit("ABORT", { 435 | transaction: transaction 436 | }); 437 | }; 438 | 439 | Client.prototype.ack = function(messageID, subscription, headers) { 440 | if (headers == null) { 441 | headers = {}; 442 | } 443 | headers["message-id"] = messageID; 444 | headers.subscription = subscription; 445 | return this._transmit("ACK", headers); 446 | }; 447 | 448 | Client.prototype.nack = function(messageID, subscription, headers) { 449 | if (headers == null) { 450 | headers = {}; 451 | } 452 | headers["message-id"] = messageID; 453 | headers.subscription = subscription; 454 | return this._transmit("NACK", headers); 455 | }; 456 | 457 | return Client; 458 | 459 | })(); 460 | 461 | Stomp = { 462 | VERSIONS: { 463 | V1_0: '1.0', 464 | V1_1: '1.1', 465 | V1_2: '1.2', 466 | supportedVersions: function() { 467 | return '1.1,1.0'; 468 | } 469 | }, 470 | client: function(url, protocols) { 471 | var klass, ws; 472 | if (protocols == null) { 473 | protocols = ['v10.stomp', 'v11.stomp']; 474 | } 475 | klass = Stomp.WebSocketClass || WebSocket; 476 | ws = new klass(url, protocols); 477 | return new Client(ws); 478 | }, 479 | over: function(ws) { 480 | return new Client(ws); 481 | }, 482 | Frame: Frame 483 | }; 484 | 485 | if (typeof exports !== "undefined" && exports !== null) { 486 | exports.Stomp = Stomp; 487 | } 488 | 489 | if (typeof window !== "undefined" && window !== null) { 490 | Stomp.setInterval = function(interval, f) { 491 | return window.setInterval(f, interval); 492 | }; 493 | Stomp.clearInterval = function(id) { 494 | return window.clearInterval(id); 495 | }; 496 | window.Stomp = Stomp; 497 | } else if (!exports) { 498 | self.Stomp = Stomp; 499 | } 500 | 501 | }).call(this); 502 | -------------------------------------------------------------------------------- /src/main/resources/static/test.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | WebSocket 4 | 5 | 6 | 7 |
8 | 9 | 10 | 18 | -------------------------------------------------------------------------------- /src/test/java/com/cictec/stomp/RabbitmqApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.cictec.stomp; 2 | 3 | import org.junit.Test; 4 | import org.junit.runner.RunWith; 5 | import org.springframework.boot.test.context.SpringBootTest; 6 | import org.springframework.test.context.junit4.SpringRunner; 7 | 8 | @RunWith(SpringRunner.class) 9 | @SpringBootTest 10 | public class RabbitmqApplicationTests { 11 | 12 | @Test 13 | public void contextLoads() { 14 | } 15 | 16 | } 17 | --------------------------------------------------------------------------------