美文网首页自动化测试我爱编程
Springboot + DWR 实现消息推送

Springboot + DWR 实现消息推送

作者: 清风徐来水波不清 | 来源:发表于2018-06-27 19:51 被阅读153次

    SpringBoot 整合 dwr ,实现 js 直接调用后端 Service.

    前一段时间由于工作需要接触到了dwr,使用dwr将mq接收到的消息推送到前台,最近项目改用springboot,因此又去重新回炉了一下。
    1.新建springboot项目,添加下面dwr的依赖文件

           <!-- DWR -->
            <dependency>
                <groupId>org.directwebremoting</groupId>
                <artifactId>dwr</artifactId>
                <version>3.0.2-RELEASE</version>
            </dependency>
    

    2.添加spring.xml,配置dwr扫描
    spring.xml 内容:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.directwebremoting.org/schema/spring-dwr http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd">
    
        <dwr:annotation-config/>
    
        <dwr:annotation-scan scanRemoteProxy="false" base-package="com.hikvision.lcc.dwr"/>
    
        <dwr:configuration/>
    </beans>
    
    

    springboot 需要加载spring.xml,在启动类中做如下配置:

    @SpringBootApplication
    @ImportResource("classpath*:spring/spring.xml")
    public class Demo2Application {
        public static void main(String[] args) {
            SpringApplication.run(Demo2Application.class, args);
        }
    }
    
    1. 之前项目用到的是dwr.xml进行配置,在springboot中我们需要用Java代码进行配置,配置类如下:
    
    @Configuration
    public class DwrConfig {
    
        /**
         *  加入 DWR servlet,相当于在xml中配置
         * @return
         */
        @Bean
        public ServletRegistrationBean servletRegistrationBean() {
           DwrSpringServlet servlet = new DwrSpringServlet();
            ServletRegistrationBean registrationBean = new ServletRegistrationBean(servlet, "/dwr/*");
            //设置成true使DWR能够debug和进入测试页面。
            registrationBean.addInitParameter("debug", "true");
            //pollAndCometEnabled 设置成true能增加服务器的加载能力,尽管DWR有保护服务器过载的机制。
            registrationBean.addInitParameter("pollAndCometEnabled", "true");
            
            registrationBean.addInitParameter("activeReverseAjaxEnabled", "true");
            registrationBean.addInitParameter("maxWaitAfterWrite", "60");
            return registrationBean;
        }
    }
    
    

    4.基本配置结束,先写个小小的demo一下。新建一个service类

    @Service
    @RemoteProxy  // spring 的注解,相当于暴露服务
    public class DemoDwr {
        //TODO  这块可以注入服务
        @RemoteMethod
        public String hello(){
            return "hello  dada " ;
        }
        @RemoteMethod
        public String echo(String  string){
            return "hello   " + string ;
        }
    }
    

    接着写一个简单的html来个阶段性测试。
    demo.html

    <html>
    <head>
        <title></title>
        <script type='text/javascript' src='/dwr/engine.js'></script>
        <script type='text/javascript' src='/dwr/interface/DemoDwr.js'></script>
        
    </head>
    hello
    <script>
        DemoDwr.echo('叫我小司马', function (str) {
            alert(str);
        });
    </script>
    </html>
    

    运行项目,刷新一下页面就可以感受到自己的劳动成果了。



    *****************************************我是华丽的分割线******************************************
    你以为这就结束了,万里长征才走了几米远.... 接着我们进入进阶测试。


    5.接着我简单演示一下如何从后端推送到前端消息。
    先写一个DWR工具类DwrScriptSessionManagerUtil,可以直接拷贝,一般变化不大。
    public class DwrScriptSessionManagerUtil extends DwrServlet {
        private static final long serialVersionUID = -7504612622407420071L;
        public void init(final String key, final String value) throws ServletException {
            Container container = ServerContextFactory.get().getContainer();
            ScriptSessionManager manager = container.getBean(ScriptSessionManager.class);
            ScriptSessionListener listener = new ScriptSessionListener() {
                public void sessionCreated(ScriptSessionEvent ev) {
                    HttpSession session = WebContextFactory.get().getSession();
                    //String userId = ((User) session.getAttribute("userinfo")).getHumanid() + "";
                    System.out.println("a ScriptSession is created!");
                    ev.getSession().setAttribute(key, value);
                }
                public void sessionDestroyed(ScriptSessionEvent ev) {
                    System.out.println("a ScriptSession is distroyed");
                }
            };
            manager.addScriptSessionListener(listener);
    
        }
    
    }
    

    假如你已经有一个加收消息的类DemoConsumer,如果mq不熟悉的建议先补一补去,在这我就不细说了。我的消费者代码大概如下,牵扯到业务会自行略去。

    @Service
    @RemoteProxy
    public class Demo2Consumer extends AbstractSpringNotifyConsumer {
       //保存scriptSession , 这个方法需要在页面刚已加载的时候调用,为了前端和后端建立连接。
        @RemoteMethod
        public void onPageLoad(String tag) {
            //获取当前的ScriptSession
            try {
                ScriptSession scriptSession =  WebContextFactory.get().getScriptSession();
                if(scriptSession != null){
                    scriptSession.setAttribute("tag", tag);
                }
                DwrScriptSessionManagerUtil dwrScriptSessionManagerUtil = new DwrScriptSessionManagerUtil() ;
                dwrScriptSessionManagerUtil.init("tag",tag);
            } catch (Exception e) {
    
            }
            System.out.println("onPageLoad 被调用 :" + tag);
        }
    
      // mq接受到消息会触发这个方法
     @Override
        public void onMessage(TextNotifyMessage message) throws NotifyException {
    
            System.out.println(" 收到消息  " + message.getData());
            System.err.println(" 收到消息  " + message.getData());
            // 下面代码变化不大,主要是给前端推送
            Browser.withAllSessionsFiltered(new ScriptSessionFilter() {
    
                public boolean match(ScriptSession session) {
                    /* 这块判断是否合法 ,可以在这块验证用户的合法性,为了简单我直接返回true*/
                    return true;
                      /*  if (session.getAttribute("userId") == null) {
                            return false;
                        } else {
                            return (session.getAttribute("userId")).equals(userId);
                        }*/
                }
    
            }, new Runnable() {
                private ScriptBuffer script = new ScriptBuffer();
    
                public void run() {
                    //设定前台接收消息的方法和参数  在前台js里定义getmessage (data) 的方法,就会自动被调用
                    script.appendCall("getmessage", message.getData());
                    Collection<ScriptSession> sessions = Browser.getTargetSessions();
                    for (ScriptSession scriptSession : sessions) {
                        scriptSession.addScript(script);
                    }
                    System.out.println("dwrtool  showmessage 调用 ");
                }
            });
        }
    }
    
    1. 现在再来改改原来的html,
    <html>
    <head>
        <title></title>
        <script type='text/javascript' src='/dwr/engine.js'></script>
    
        <script type='text/javascript' src='/dwr/interface/Demo2Consumer.js'></script>
    
        <script>
            function onpage(){
                // 页面加载直接调用这个函数,我这块使用点击按钮
                Demo2Consumer.onPageLoad("123456");
            }
            // 后端会调用这个函数
            function getmessage(data){
                alert(data);
            }
        </script>
    </head>
    hello
    <input type="button" onclick="onpage()" value="onpage" >
    </html>
    

    效果展示:点击onpage 按钮后会一直对话框弹出,显示的就是mq接收到的消息。
    7.补充,和前端聊了聊以后,前端给建议不需要调用onpage记载,也可以调用dwr的js函数,这块我贴上供大家参考

    
    <script>
        //  激活ajax    
      dwr.engine.setActiveReverseAjax(true)
        // 页面未加载的时候是否发送通知
        dwr.engine.setNotifyServerOnPageUnload(true,true)
        // 出现错误后的处理方法
        dwr.engine.setErrorHandler(function(){})
    
        function getmessage(data){
            if (window.eventBus) {
                window.eventBus.$emit('getDwr',data);
            }
        }
    </script>
    
    

    相关文章

      网友评论

      • 我是小:engine.js等几个js404 是为啥啊 楼主
        清风徐来水波不清:spring.xml 配置有没有问题 都扫描到了吗?springboot的Java配置检查一下。另外我的js里面还缺一个dwr/util.js 的引用。

      本文标题:Springboot + DWR 实现消息推送

      本文链接:https://www.haomeiwen.com/subject/uaeiyftx.html