繁体   English   中英

使用SseEmitter进行Spring休息服务

[英]Spring rest service with SseEmitter

当我在服务器上调用控制器时,我正在尝试通知一个简单的html页面。 我有一个Android应用程序调用我的控制器,当这完成后,我想通知我的网页控制器被调用。

这是我的一些代码:

    @RequestMapping("/user") 
public class UserController {

    /**
     * Returns user by id.
     * 
     * @param user IMEI
     * @return
     */
    @RequestMapping(value = "/{imei}", method = RequestMethod.GET)
    public User getUser(@PathVariable String imei) {

        User myUser = null;
        try {
            myUser = DbConnector.getUserWithImei(imei);
        } catch (Exception e) {
            System.out.println("Couldn't get user from database");
            e.printStackTrace();
        }
        SseEmitter emitter = new SseEmitter();
        try {
            emitter.send("Hallokes");
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        emitter.complete();
        return myUser;
    }
}

我看到的所有教程,控制器返回SseEmitter但我必须返回一个User。 我必须使用另一个映射创建另一个控制器并侦听该URL吗? 如何在现有控制器中调用该控制器方法? 我的EventSource必须监听哪个URL?

在此先感谢您的帮助!

亲切的问候。

我想你几乎就在那里,Allinone51。

您对SseEmitter.send()的调用可能应该在getUser方法中。 一般模式是,当您创建SseEmitter时,您需要将其“存储”在某处以便其他代码获取它。 您正确地从getSseEmitter方法返回SseEmitter,您只是忘记将其存储为另一种方法,以便能够在其上调用“send”。

调整上面的示例,它可能是这样的:

//...
private SseEmitter emitter;

@RequestMapping(value = "/{imei}", method = RequestMethod.GET)
public User getUser(@PathVariable String imei) { 
    User myUser = null;

    // .. do resolving of myUser (e.g. database etc).

    // Send message to "connected" web page:
    if (emitter != null) {
        emitter.send(myUser.toString()); // Or format otherwise, e.g. JSON.
    }

    // This return value goes back as a response to your android device
    // i.e. the caller of the getUser rest service.
    return myUser;
}

@RequestMapping(value = "/sse")
public SseEmitter getSseEmitter() {
    emitter = new SseEmitter();
    return emitter;
}

当然,上面的代码只适用于一个连接/发射器。 有更智能的存储发射器的方法。 例如,在我的在线游戏应用程序中,我将发射器挂钩到每个Player对象中。 这样,只要我的服务器上的玩家对象有东西告诉玩家设备,它就可以访问自己内部的正确发射器。

我设法使SseEmitter工作。 我将解释我是如何做到的,也许它会帮助别人。

我发现的第一件事是EventSource(“url”)实际上只是“调用”那个url(如果我错了,请纠正我)。 因此,在Restcontroller的情况下,它只会一遍又一遍地调用该控制器。 现在,当您使用SseEmitter.send时,会触发EventSource的onMessage()方法。 所以我所做的是添加另一个带有映射“/ sse”的控制器方法,让我的eventSource调用该方法。 现在当我调用返回用户的原始控制器方法时,我只是将一个全局变量设置为true,如果该变量为true,我发送一条消息。 代码将更好地解释这个:

在我的Android应用程序中调用的方法遵循SSE的控制器方法:

@RequestMapping(value = "/{imei}", method = RequestMethod.GET)
    public User getUser(@PathVariable String imei) { // @PathVariable for
                                                        // passing variables
                                                        // in uri.
                                                        // (<root-url>/service/greeting/myVariable)
        User myUser = null;
        try {
            myUser = DbConnector.getUserWithImei(imei);
        } catch (Exception e) {
            System.out.println("Couldn't get user from database");
            e.printStackTrace();
        }
        if (myUser != null) {
            if (myUser.getAccess() == 1) {
                calledImei = true;
            }
        }
        return myUser;
    }

    @RequestMapping(value = "/sse")
    public SseEmitter getSseEmitter() {
        SseEmitter sseEmitter = new SseEmitter();
        if(calledImei) {
            try {
                sseEmitter.send("Message 1");
                calledImei = false;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        sseEmitter.complete();
        return sseEmitter;
    }
}

现在是带有EventSource的HTML页面:

<body>
    <script>
            var source = new EventSource("rest/user/sse");
            source.onmessage = function(event) {
                 //Do what you need to do when message received.
            }
    </script>
</body>

希望这会对其他人有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM