복붙노트

[SPRING] 서버 측에서 스프링 프레임 워크로 안드로이드에 Stomp 클라이언트 설정

SPRING

서버 측에서 스프링 프레임 워크로 안드로이드에 Stomp 클라이언트 설정

나는 봄에 구성된 돌풍 서버와 데이터를 교환하는 안드로이드 애플리케이션을 개발 중이다. 보다 역동적 인 안드로이드 응용 프로그램을 얻으려면 Stomp 메시지와 함께 WebSocket 프로토콜을 사용하려고합니다.

이 물건을 실현하기 위해 나는 봄에 웹 소켓 메시지 브로커를 설정했다.

@Configuration
//@EnableScheduling
@ComponentScan(
        basePackages="project.web",
        excludeFilters = @ComponentScan.Filter(type= FilterType.ANNOTATION, value = Configuration.class)
)
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/message");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/client");
    }
}

Spring 컨트롤러의 SimpMessageSendingOperations를 사용하여 서버에서 클라이언트로 메시지 보내기 :

@Controller
public class MessageAddController {
    private final Log log = LogFactory.getLog(MessageAddController.class);

    private SimpMessageSendingOperations messagingTemplate;

    private UserManager userManager;

    private MessageManager messageManager;

    @Autowired
    public MessageAddController(SimpMessageSendingOperations messagingTemplate, 
            UserManager userManager, MessageManager messageManager){
        this.messagingTemplate = messagingTemplate;
        this.userManager = userManager;
        this.messageManager = messageManager;
    }

    @RequestMapping("/Message/Add")
    @ResponseBody
    public SimpleMessage addFriendship(
            @RequestParam String content,
            @RequestParam Long otherUser_id
    ){
        if(log.isInfoEnabled())
            log.info("Execute MessageAdd action");
        SimpleMessage simpleMessage;

        try{
            User curentUser = userManager.getCurrentUser();
            User otherUser = userManager.findUser(otherUser_id);

            Message message = new Message();
            message.setContent(content);
            message.setUserSender(curentUser);
            message.setUserReceiver(otherUser);

            messageManager.createMessage(message);          
            Message newMessage = messageManager.findLastMessageCreated();

            messagingTemplate.convertAndSend( 
                    "/message/add", newMessage);//send message through websocket

            simpleMessage = new SimpleMessage(null, newMessage);
        } catch (Exception e) {
            if(log.isErrorEnabled())
                log.error("A problem of type : " + e.getClass() 
                        + " has occured, with message : " + e.getMessage());
            simpleMessage = new SimpleMessage(
                            new SimpleException(e.getClass(), e.getMessage()), null);
        }
        return simpleMessage;
    }
}

stomp.js가있는 웹 브라우저에서이 구성을 테스트 할 때 어떤 문제도 없습니다. 웹 브라우저와 Jetty 서버간에 메시지가 완벽하게 교환됩니다. 웹 브라우저 테스트 용 JavaScript 코드 :

    var stompClient = null;

    function setConnected(connected) {
        document.getElementById('connect').disabled = connected;
        document.getElementById('disconnect').disabled = !connected;
        document.getElementById('conversationDiv').style.visibility = connected ? 'visible' : 'hidden';
        document.getElementById('response').innerHTML = '';
    }

    function connect() {
        stompClient = Stomp.client("ws://YOUR_IP/client");         
        stompClient.connect({}, function(frame) {
            setConnected(true);
            stompClient.subscribe('/message/add', function(message){
                showMessage(JSON.parse(message.body).content);
            });
        });
    }

    function disconnect() {
        stompClient.disconnect();
        setConnected(false);
        console.log("Disconnected");
    }


    function showMessage(message) {
        var response = document.getElementById('response');
        var p = document.createElement('p');
        p.style.wordWrap = 'break-word';
        p.appendChild(document.createTextNode(message));
        response.appendChild(p);
    }

문제는 gozirra, activemq-stomp 또는 다른 라이브러리와 같이 Android에서 stomp를 사용하려고 할 때 발생합니다. 대부분의 경우 서버와의 연결이 작동하지 않습니다. 내 앱이 실행을 멈추고 잠시 후 logcat에 다음 메시지가 표시됩니다. java.net.UnknownHostException : 호스트 "ws : //192.168.1.39/client"를 확인할 수 없습니다 : 호스트 이름과 연결된 주소가 없습니다. 이유를 이해하지 못한다. 내 안드로이드 활동에서 stomp 호소력을 관리하는 Gozzira 라이브러리를 사용한 코드 :

private void stomp_test() {
    String ip = "ws://192.172.6.39/client";
    int port = 8080;

    String channel = "/message/add";
    Client c;

    try {
        c = new Client( ip, port, "", "" );
        Log.i("Stomp", "Connection established");
        c.subscribe( channel, new Listener() {
            public void message( Map header, String message ) {
                Log.i("Stomp", "Message received!!!");
              }
        });

    } catch (IOException ex) {
        Log.e("Stomp", ex.getMessage());
        ex.printStackTrace();

    } catch (LoginException ex) {
        Log.e("Stomp", ex.getMessage());
        ex.printStackTrace();
    } catch (Exception ex) {
        Log.e("Stomp", ex.getMessage());
        ex.printStackTrace();
    }

}

몇 가지 조사를 한 후에, 나는 자바 클라이언트와 함께 웹 소켓을 통해 스톰프를 사용하려는 대부분의 사람들이이 사이트 에서처럼 ActiveMQ 서버를 사용함을 발견했다. 그러나 봄 도구는 사용하기가 매우 쉽고 내 서버 계층을 그대로 유지하면 멋지게 될 것입니다. 누군가가 서버 측에서 스프링 구성을 사용하여 클라이언트 측에서 stomp java (Android)를 사용하는 방법을 알고 있습니까?

해결법

  1. ==============================

    1.RxJava https://github.com/NaikSoftware/StompProtocolAndroid와 함께 안드로이드 (또는 일반 자바)에 대한 STOMP 프로토콜 구현. SpringBoot가 설치된 STOMP 서버에서 테스트되었습니다. 간단한 예제 (retrolambda 포함) :

    RxJava https://github.com/NaikSoftware/StompProtocolAndroid와 함께 안드로이드 (또는 일반 자바)에 대한 STOMP 프로토콜 구현. SpringBoot가 설치된 STOMP 서버에서 테스트되었습니다. 간단한 예제 (retrolambda 포함) :

    private StompClient mStompClient;
    
     // ...
    
     mStompClient = Stomp.over(WebSocket.class, "ws://localhost:8080/app/hello/websocket");
     mStompClient.connect();
    
     mStompClient.topic("/topic/greetings").subscribe(topicMessage -> {
         Log.d(TAG, topicMessage.getPayload());
     });
    
     mStompClient.send("/app/hello", "My first STOMP message!");
    
     // ...
    
     mStompClient.disconnect();
    

    프로젝트에 다음 클래스 경로를 추가하십시오.

      classpath 'me.tatarka:gradle-retrolambda:3.2.0'
    

    앱 build.gradle에 다음을 추가하십시오.

    apply plugin: 'me.tatarka.retrolambda'
    
    android {
           .............
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
    
    
      dependencies {
          ............................
        compile 'org.java-websocket:Java-WebSocket:1.3.0'
        compile 'com.github.NaikSoftware:StompProtocolAndroid:1.1.5'
    }
    

    모두 비동기 적으로 작동합니다! subscribe () 및 send () 후에 connect ()를 호출하면 메시지가 대기열로 푸시됩니다.

    추가 기능 :

    예 :

    public class MainActivity extends AppCompatActivity {
        private StompClient mStompClient;
        public static  final String TAG="StompClient";
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Button view = (Button) findViewById(R.id.button);
            view.setOnClickListener(e->  new LongOperation().execute(""));
    
    
        }
    
    
            private class LongOperation extends AsyncTask<String, Void, String> {
            private StompClient mStompClient;
            String TAG="LongOperation";
            @Override
            protected String doInBackground(String... params) {
    
                mStompClient = Stomp.over(WebSocket.class, "ws://localhost:8080/app/hello/websocket");
                mStompClient.connect();
    
                mStompClient.topic("/topic/greetings").subscribe(topicMessage -> {
                    Log.d(TAG, topicMessage.getPayload());
                });
    
                mStompClient.send("/app/hello", "My first STOMP message!").subscribe();
    
    
                mStompClient.lifecycle().subscribe(lifecycleEvent -> {
                    switch (lifecycleEvent.getType()) {
    
                        case OPENED:
                            Log.d(TAG, "Stomp connection opened");
                            break;
    
                        case ERROR:
                            Log.e(TAG, "Error", lifecycleEvent.getException());
                            break;
    
                        case CLOSED:
                            Log.d(TAG, "Stomp connection closed");
                            break;
                    }
                });
                return "Executed";
            }
    
            @Override
            protected void onPostExecute(String result) {
    
            }
    
        }
    }
    

    manifest.xml에 인터넷 권한 추가

    <uses-permission android:name="android.permission.INTERNET" />
    
  2. ==============================

    2.나는 안드로이드와 스프링 서버로 웹 소켓을 통해 스톰프를 사용하는 것을 성취한다.

    나는 안드로이드와 스프링 서버로 웹 소켓을 통해 스톰프를 사용하는 것을 성취한다.

    그런 일을하기 위해 나는 웹 소켓 라이브러리 werbench (이 링크를 따라 가며 다운로드)를 사용했다. 설치하려면 maven 명령 mvn install을 사용했고 로컬 저장소에 jar 파일을 다시 가져 왔습니다. 그런 다음 기본 웹 소켓 하나에 스톰프 레이어를 추가해야하지만 웹 소켓에서 스톰프를 관리 할 수있는 자바에서 스톰프 라이브러리를 찾을 수 없습니다 (gozzira를 포기해야 함). 그래서 저는 제 자신을 만듭니다 (모델과 같은 stomp.js로). 당신이 그것을보고 싶어하는지 나에게 묻는 것을 주저하지 마라. 그러나 나는 그것을 매우 빨리 실현했다. 그래서 그것은 stomp.js만큼 많이 관리 할 수 ​​없다. 그럼, 내 스프링 서버와 인증을 실현해야합니다. 그것을 성취하기 위해 나는이 사이트의 표시를 따랐다. 내가 JSESSIONID 쿠키를 다시 얻었을 때, 나는 단지 stomp "라이브러리"에있는 werbench 웹 소켓의 인스턴스에이 쿠키가있는 헤더를 선언해야했습니다.

    편집하다 : 이 라이브러리의 주요 클래스는 웹 소켓 연결을 통해 스톰프를 관리하는 클래스입니다.

    import java.io.IOException;
    import java.net.URI;
    import java.net.URISyntaxException;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    import android.util.Log;
    import de.roderick.weberknecht.WebSocket;
    import de.roderick.weberknecht.WebSocketEventHandler;
    import de.roderick.weberknecht.WebSocketMessage;
    
    public class Stomp {
    
        private static final String TAG = Stomp.class.getSimpleName();
    
        public static final int CONNECTED = 1;//Connection completely established
        public static final int NOT_AGAIN_CONNECTED = 2;//Connection process is ongoing
        public static final int DECONNECTED_FROM_OTHER = 3;//Error, no more internet connection, etc.
        public static final int DECONNECTED_FROM_APP = 4;//application explicitely ask for shut down the connection 
    
        private static final String PREFIX_ID_SUBSCIPTION = "sub-";
        private static final String ACCEPT_VERSION_NAME = "accept-version";
        private static final String ACCEPT_VERSION = "1.1,1.0";
        private static final String COMMAND_CONNECT = "CONNECT";
        private static final String COMMAND_CONNECTED = "CONNECTED";
        private static final String COMMAND_MESSAGE = "MESSAGE";
        private static final String COMMAND_RECEIPT = "RECEIPT";
        private static final String COMMAND_ERROR = "ERROR";
        private static final String COMMAND_DISCONNECT = "DISCONNECT";
        private static final String COMMAND_SEND = "SEND";
        private static final String COMMAND_SUBSCRIBE = "SUBSCRIBE";
        private static final String COMMAND_UNSUBSCRIBE = "UNSUBSCRIBE";
        private static final String SUBSCRIPTION_ID = "id";
        private static final String SUBSCRIPTION_DESTINATION = "destination";
        private static final String SUBSCRIPTION_SUBSCRIPTION = "subscription";
    
    
        private static final Set<String> VERSIONS = new HashSet<String>();
        static {
            VERSIONS.add("V1.0");
            VERSIONS.add("V1.1");
            VERSIONS.add("V1.2");
        }
    
        private WebSocket websocket;
    
        private int counter;
    
        private int connection;
    
        private Map<String, String> headers;
    
        private int maxWebSocketFrameSize;
    
        private Map<String, Subscription> subscriptions;
    
        private ListenerWSNetwork networkListener;
    
        /**
         * Constructor of a stomp object. Only url used to set up a connection with a server can be instantiate
         * 
         * @param url
         *      the url of the server to connect with
         */
        public Stomp(String url, Map<String,String> headersSetup, ListenerWSNetwork stompStates){       
            try {
                this.websocket = new WebSocket(new URI(url), null, headersSetup);
                this.counter = 0;
    
                this.headers = new HashMap<String, String>();
                this.maxWebSocketFrameSize = 16 * 1024;
                this.connection = NOT_AGAIN_CONNECTED;
                this.networkListener = stompStates;
                this.networkListener.onState(NOT_AGAIN_CONNECTED);
                this.subscriptions = new HashMap<String, Subscription>();
    
                this.websocket.setEventHandler(new WebSocketEventHandler() {        
                    @Override
                    public void onOpen(){
                        if(Stomp.this.headers != null){                                         
                            Stomp.this.headers.put(ACCEPT_VERSION_NAME, ACCEPT_VERSION);
    
                            transmit(COMMAND_CONNECT, Stomp.this.headers, null);
    
                            Log.d(TAG, "...Web Socket Openned");
                        }
                    }
    
                    @Override
                    public void onMessage(WebSocketMessage message) {
                        Log.d(TAG, "<<< " + message.getText());
                        Frame frame = Frame.fromString(message.getText());
                        boolean isMessageConnected = false;
    
                        if(frame.getCommand().equals(COMMAND_CONNECTED)){
                            Stomp.this.connection = CONNECTED;
                            Stomp.this.networkListener.onState(CONNECTED);
    
                            Log.d(TAG, "connected to server : " + frame.getHeaders().get("server"));
                            isMessageConnected = true;
    
                        } else if(frame.getCommand().equals(COMMAND_MESSAGE)){
                            String subscription = frame.getHeaders().get(SUBSCRIPTION_SUBSCRIPTION);
                            ListenerSubscription onReceive = Stomp.this.subscriptions.get(subscription).getCallback();
    
                            if(onReceive != null){
                                onReceive.onMessage(frame.getHeaders(), frame.getBody());
                            } else{
                                Log.e(TAG, "Error : Subscription with id = " + subscription + " had not been subscribed");
                                //ACTION TO DETERMINE TO MANAGE SUBCRIPTION ERROR
                            }
    
                        } else if(frame.getCommand().equals(COMMAND_RECEIPT)){
                            //I DON'T KNOW WHAT A RECEIPT STOMP MESSAGE IS
    
                        } else if(frame.getCommand().equals(COMMAND_ERROR)){
                            Log.e(TAG, "Error : Headers = " + frame.getHeaders() + ", Body = " + frame.getBody());
                            //ACTION TO DETERMINE TO MANAGE ERROR MESSAGE
    
                        } else {
    
                        }
    
                        if(isMessageConnected)
                            Stomp.this.subscribe();
                    }
    
                    @Override
                    public void onClose(){
                        if(connection == DECONNECTED_FROM_APP){
                            Log.d(TAG, "Web Socket disconnected");
                            disconnectFromApp();
                        } else{
                            Log.w(TAG, "Problem : Web Socket disconnected whereas Stomp disconnect method has never "
                                    + "been called.");
                            disconnectFromServer();
                        }
                    }
    
                    @Override
                    public void onPing() {
    
                    }
    
                    @Override
                    public void onPong() {
    
                    }
    
                    @Override
                    public void onError(IOException e) {
                        Log.e(TAG, "Error : " + e.getMessage());                
                    }
                });
            } catch (URISyntaxException e) {
                e.printStackTrace();
            }
        }
    
        /**
         * Send a message to server thanks to websocket
         * 
         * @param command
         *      one of a frame property, see {@link Frame} for more details
         * @param headers
         *      one of a frame property, see {@link Frame} for more details
         * @param body
         *      one of a frame property, see {@link Frame} for more details
         */
        private void transmit(String command, Map<String, String> headers, String body){
            String out = Frame.marshall(command, headers, body);
            Log.d(TAG, ">>> " + out);
            while (true) {
                if (out.length() > this.maxWebSocketFrameSize) {
                    this.websocket.send(out.substring(0, this.maxWebSocketFrameSize));
                    out = out.substring(this.maxWebSocketFrameSize);
                } else {
                    this.websocket.send(out);
                    break;
                }
            }
        }
    
        /**
         * Set up a web socket connection with a server
         */
        public void connect(){
            if(this.connection != CONNECTED){
                Log.d(TAG, "Opening Web Socket...");
                try{
                    this.websocket.connect();
                } catch (Exception e){
                    Log.w(TAG, "Impossible to establish a connection : " + e.getClass() + ":" + e.getMessage());
                }
            }
        }
    
        /**
         * disconnection come from the server, without any intervention of client side. Operations order is very important
         */
        private void disconnectFromServer(){
            if(this.connection == CONNECTED){
                this.connection = DECONNECTED_FROM_OTHER;
                this.websocket.close();
                this.networkListener.onState(this.connection);
            }
        }
    
        /**
         * disconnection come from the app, because the public method disconnect was called
         */
        private void disconnectFromApp(){
            if(this.connection == DECONNECTED_FROM_APP){
                this.websocket.close();
                this.networkListener.onState(this.connection);
            }
        }
    
        /**
         * Close the web socket connection with the server. Operations order is very important
         */
        public void disconnect(){
            if(this.connection == CONNECTED){
                this.connection = DECONNECTED_FROM_APP;
                transmit(COMMAND_DISCONNECT, null, null);
            }
        }
    
        /**
         * Send a simple message to the server thanks to the body parameter
         * 
         * 
         * @param destination
         *      The destination through a Stomp message will be send to the server
         * @param headers
         *      headers of the message
         * @param body
         *      body of a message
         */
        public void send(String destination, Map<String,String> headers, String body){
            if(this.connection == CONNECTED){
                if(headers == null)
                    headers = new HashMap<String, String>();
    
                if(body == null)
                    body = "";
    
                headers.put(SUBSCRIPTION_DESTINATION, destination);
    
                transmit(COMMAND_SEND, headers, body);
            }
        }
    
        /**
         * Allow a client to send a subscription message to the server independently of the initialization of the web socket.
         * If connection have not been already done, just save the subscription
         * 
         * @param subscription
         *      a subscription object
         */
        public void subscribe(Subscription subscription){
            subscription.setId(PREFIX_ID_SUBSCIPTION + this.counter++);
            this.subscriptions.put(subscription.getId(), subscription);
    
            if(this.connection == CONNECTED){   
                Map<String, String> headers = new HashMap<String, String>();            
                headers.put(SUBSCRIPTION_ID, subscription.getId());
                headers.put(SUBSCRIPTION_DESTINATION, subscription.getDestination());
    
                subscribe(headers);
            }
        }
    
        /**
         * Subscribe to a Stomp channel, through messages will be send and received. A message send from a determine channel
         * can not be receive in an another.
         *
         */
        private void subscribe(){
            if(this.connection == CONNECTED){
                for(Subscription subscription : this.subscriptions.values()){
                    Map<String, String> headers = new HashMap<String, String>();            
                    headers.put(SUBSCRIPTION_ID, subscription.getId());
                    headers.put(SUBSCRIPTION_DESTINATION, subscription.getDestination());
    
                    subscribe(headers);
                }
            }
        }
    
        /**
         * Send the subscribe to the server with an header
         * @param headers
         *      header of a subscribe STOMP message
         */
        private void subscribe(Map<String, String> headers){
            transmit(COMMAND_SUBSCRIBE, headers, null);
        }
    
        /**
         * Destroy a subscription with its id
         * 
         * @param id
         *      the id of the subscription. This id is automatically setting up in the subscribe method
         */
        public void unsubscribe(String id){
            if(this.connection == CONNECTED){
                Map<String, String> headers = new HashMap<String, String>();
                headers.put(SUBSCRIPTION_ID, id);
    
                this.subscriptions.remove(id);
                this.transmit(COMMAND_UNSUBSCRIBE, headers, null);
            }
        }
    }
    

    이것은 Stomp 메시지의 프레임입니다.

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class Frame {
    //  private final static String CONTENT_LENGTH = "content-length";
    
        private String command;
        private Map<String, String> headers;
        private String body;
    
        /**
         * Constructor of a Frame object. All parameters of a frame can be instantiate
         * 
         * @param command
         * @param headers
         * @param body
         */
        public Frame(String command, Map<String, String> headers, String body){
            this.command = command;     
            this.headers = headers != null ? headers : new HashMap<String, String>();
            this.body = body != null ? body : "";
        }
    
        public String getCommand(){
            return command;
        }
    
        public Map<String, String> getHeaders(){
            return headers;
        }
    
        public String getBody(){
            return body;
        }
    
        /**
         * Transform a frame object into a String. This method is copied on the objective C one, in the MMPReactiveStompClient
         * library
         * @return a frame object convert in a String
         */
        private String toStringg(){
            String strLines = this.command;
            strLines += Byte.LF;
            for(String key : this.headers.keySet()){
                strLines += key + ":" + this.headers.get(key);
                strLines += Byte.LF;
            }
            strLines += Byte.LF;
            strLines += this.body;
            strLines += Byte.NULL;
    
            return strLines;
        }
    
        /**
         * Create a frame from a received message. This method is copied on the objective C one, in the MMPReactiveStompClient
         * library
         * 
         * @param data
         *  a part of the message received from network, which represented a frame
         * @return
         *  An object frame
         */
        public static Frame fromString(String data){
            List<String> contents = new ArrayList<String>(Arrays.asList(data.split(Byte.LF)));
    
            while(contents.size() > 0 && contents.get(0).equals("")){
                contents.remove(0);
            }
    
            String command = contents.get(0);
            Map<String, String> headers = new HashMap<String, String>();
            String body = "";
    
            contents.remove(0);
            boolean hasHeaders = false;
            for(String line : contents){
                if(hasHeaders){
                    for(int i=0; i < line.length(); i++){
                        Character c = line.charAt(i);
                        if(!c.equals('\0'))
                            body += c;
                    }
                } else{
                    if(line.equals("")){
                        hasHeaders = true;
                    } else {
                        String[] header = line.split(":");
                        headers.put(header[0], header[1]);
                    }
                }
            }
            return new Frame(command, headers, body);   
        }
    
    //    No need this method, a single frame will be always be send because body of the message will never be excessive
    //    /**
    //     * Transform a message received from server in a Set of objects, named frame, manageable by java
    //     * 
    //     * @param datas
    //     *        message received from network
    //     * @return
    //     *        a Set of Frame
    //     */
    //    public static Set<Frame> unmarshall(String datas){
    //      String data;
    //      String[] ref = datas.split(Byte.NULL + Byte.LF + "*");//NEED TO VERIFY THIS PARAMETER
    //      Set<Frame> results = new HashSet<Frame>();
    //      
    //      for (int i = 0, len = ref.length; i < len; i++) {
    //            data = ref[i];
    //            
    //            if ((data != null ? data.length() : 0) > 0){
    //              results.add(unmarshallSingle(data));//"unmarshallSingle" is the old name method for "fromString"
    //            }
    //        }         
    //      return results;
    //    }
    
        /**
         * Create a frame with based fame component and convert them into a string
         * 
         * @param command
         * @param headers
         * @param body
         * @return  a frame object convert in a String, thanks to <code>toStringg()</code> method
         */
        public static String marshall(String command, Map<String, String> headers, String body){
            Frame frame = new Frame(command, headers, body);
            return frame.toStringg();
        }
    
        private class Byte {
            public static final String LF = "\n";
            public static final String NULL = "\0";
        }
    }
    

    이것은 stomp 프로토콜을 통해 가입을 설정하는 데 사용되는 객체입니다.

    public class Subscription {
    
        private String id;
    
        private String destination;
    
        private ListenerSubscription callback;
    
        public Subscription(String destination, ListenerSubscription callback){
            this.destination = destination;
            this.callback = callback;
        }
    
        public String getId() {
            return id;
        }
        public void setId(String id) {
            this.id = id;
        }
    
        public String getDestination() {
            return destination;
        }
    
        public ListenerSubscription getCallback() {
            return callback;
        }
    }
    

    적어도, "Run"Java 클래스로 사용되는 두 개의 인터페이스가 웹 소켓 네트워크와 주어진 구독 채널을 수신 대기합니다.

    public interface ListenerWSNetwork {
        public void onState(int state);
    }
    
    import java.util.Map;
    public interface ListenerSubscription {
        public void onMessage(Map<String, String> headers, String body);
    }
    

    자세한 내용은 주저하지 말고 문의하십시오.

  3. ==============================

    3.완벽한 솔루션에 페린은 고맙습니다. 예 : 전체 솔루션을 채우고 싶습니다. 귀하의 활동 / 서비스 단계에서 전화 연결 방법은 물론 MainThread에 없습니다.

    완벽한 솔루션에 페린은 고맙습니다. 예 : 전체 솔루션을 채우고 싶습니다. 귀하의 활동 / 서비스 단계에서 전화 연결 방법은 물론 MainThread에 없습니다.

    private void connection() {
            Map<String,String> headersSetup = new HashMap<String,String>();
            Stomp stomp = new Stomp(hostUrl, headersSetup, new ListenerWSNetwork() {
                @Override
                public void onState(int state) {
                }
            });
            stomp.connect();
            stomp.subscribe(new Subscription(testUrl, new ListenerSubscription() {
                @Override
                public void onMessage(Map<String, String> headers, String body) {
                }
            }));
        }
    

    그리고 webSocket weberknecht 라이브러리에서주의해야합니다. verifyServerHandshakeHeaders 메소드의 WebSocketHandshake 클래스의 버그입니다. (! headers.get ( "Connection"). equals ( "Upgrade"))와 서버가 업그레이드 대신 업그레이드를 보내는 경우에만 체크됩니다 당신은 오류 연결을 얻지 못했습니다 : 서버 핸드 셰이크의 헤더 필드가 누락되었습니다 : 연결을 해제해야합니다 (! headers.get ( "Connection"). equalsIgnoreCase ( "Upgrade"))

  4. from https://stackoverflow.com/questions/24346068/set-up-a-stomp-client-in-android-with-spring-framework-in-server-side by cc-by-sa and MIT license