Tomcat 7上的Servlet 3异步任务 [英] Servlet 3 Async task on Tomcat 7

查看:151
本文介绍了Tomcat 7上的Servlet 3异步任务的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用基于其异步支持的Servlet 3.0和Comet模式实现简单聊天。

I'm trying to implement Simple chat using Servlet 3.0 and Comet pattern based on its async support.

我的灵感来自于这篇文章:
http://www.javaworld.com /javaworld/jw-02-2009/jw-02-servlet3.html?page=3

I'm inspired by this article: http://www.javaworld.com/javaworld/jw-02-2009/jw-02-servlet3.html?page=3

我的servlet看起来像这样。

My servlet looks like this.

@WebServlet(name="chatServlet", urlPatterns={"/ChatServlet"}, asyncSupported=true)
public class ChatServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
         AsyncContext aCtx = request.startAsync(request, response); 
         ServletContext appScope = request.getServletContext();    
         List<AsyncContext> watchers = (List<AsyncContext>) appScope.getAttribute("watchers");
         watchers.add(aCtx); //register the watcher
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
          AsyncContext aCtx = request.startAsync(request, response); 
          ServletContext appScope = request.getServletContext(); 
          Queue<String> messages = (Queue<String>)appScope.getAttribute("messages");
          messages.add(someMessage);
    }
} 

现在我的听众看起来像这样:

now my Listener looks like this:

@WebListener
public class ChatPushService implements ServletContextListener {

        @Override
        public void contextInitialized(ServletContextEvent sce) {
              final List<AsyncContext> watchers = new  ArrayList<AsyncContext>();
             sce.getServletContext().setAttribute("watchers", watchers);
              // store new messages not published yet
             Queue<String> messages = new ConcurrentLinkedQueue<String>();
             sce.getServletContext().setAttribute("messages", messages);
             Executor messageExecutor = Executors.newCachedThreadPool(); 
             final Executor watcherExecutor = Executors.newCachedThreadPool();
             while(true)
              {      

                 if(!messages.isEmpty()) 
                 {
                     System.out.println("notEmpty");
                    String message =  messages.poll(); 
                    messageExecutor.execute(new Runnable(){

                        @Override
                        public void run() {
                             for(final AsyncContext aCtx : watchers){
                                 watcherExecutor.execute(new Runnable(){

                                     @Override
                                        public void run() {
                                           try {
                                            aCtx.getResponse().getWriter().print("brrrrr");
                                        } catch (IOException e) {
                                            // TODO Auto-generated catch block
                                            e.printStackTrace();
                                        }
                                     }
                                 });
                             }
                        }
                 });
              }
        }

    }
    }

当我开始时,它在容器启动期间冻结。

When I'm starting my it's freezing during container initiation.

Nov 1, 2011 1:12:09 AM org.apache.catalina.core.AprLifecycleListener init
INFO: The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: /usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-6-openjdk/jre/lib/amd64:/usr/lib/jvm/java-6-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib/jni:/lib:/usr/lib
Nov 1, 2011 1:12:09 AM org.apache.tomcat.util.digester.SetPropertiesRule begin
WARNING: [SetPropertiesRule]{Server/Service/Engine/Host/Context} Setting property 'source' to 'org.eclipse.jst.jee.server:Servlet3Comet' did not find a matching property.
Nov 1, 2011 1:12:09 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["http-bio-8080"]
Nov 1, 2011 1:12:09 AM org.apache.coyote.AbstractProtocol init
INFO: Initializing ProtocolHandler ["ajp-bio-8009"]
Nov 1, 2011 1:12:09 AM org.apache.catalina.startup.Catalina load
INFO: Initialization processed in 624 ms
Nov 1, 2011 1:12:09 AM org.apache.catalina.core.StandardService startInternal
INFO: Starting service Catalina
Nov 1, 2011 1:12:09 AM org.apache.catalina.core.StandardEngine startInternal
INFO: Starting Servlet Engine: Apache Tomcat/7.0.22

看起来像 public void contextInitialized 函数没有在后台异步运行,并且阻止了进一步的容器初始化。

It looks like public void contextInitialized function is not running asynchronously on background and is blocking further container initialization.

为什么?

有人可以帮我解决这个问题吗?

can anybody help me on this issue?

推荐答案

您正在 contextInitialized() 方法中运行while循环是错的。 Servlet容器作为应用程序启动的一部分调用 contextInitialized() ,while循环将阻止您的应用程序启动。

You are running while loop inside contextInitialized() method which is wrong. contextInitialized() is invoked by Servlet Container as part of the application startup, having while loop there will block your app start.

修改代码,使ContextListener启动一个守护程序线程,将监控程序发布给观察者

Modified the code such the ContextListener will start one daemon thread which publishes the messages to the watchers

@WebListener
public class ChatPushService implements ServletContextListener {

    @Override
    public void contextInitialized(ServletContextEvent sce) {
          final List<AsyncContext> watchers = new  ArrayList<AsyncContext>();
         sce.getServletContext().setAttribute("watchers", watchers);
          // store new messages not published yet
         Queue<String> messages = new ConcurrentLinkedQueue<String>();
         sce.getServletContext().setAttribute("messages", messages);
         new chatManager(sce.getServletContext()).start(); //START DAEMON

      }
}
public class ChatManager implements Runnable
{
ServletContext servletCtx;
public ChatManager(ServletContext ctx)
{
     this.servletCtx = ctx;
}
public void run()
{
         List<AsyncContext> watchers = (List<AsyncContext>) servletCtx.getAttribute("watchers");
     Queue<String> messages = (Queue<String>)appScope.getAttribute("messages");
     Executor messageExecutor = Executors.newCachedThreadPool(); 
         final Executor watcherExecutor = Executors.newCachedThreadPool();
         while(true)
          {      

             if(!messages.isEmpty()) 
             {
                 System.out.println("notEmpty");
                String message =  messages.poll(); 
                messageExecutor.execute(new Runnable(){

                    @Override
                    public void run() {
                         for(final AsyncContext aCtx : watchers){
                             watcherExecutor.execute(new Runnable(){

                                 @Override
                                    public void run() {
                                       try {
                                        aCtx.getResponse().getWriter().print("brrrrr");
                                    } catch (IOException e) {
                                        // TODO Auto-generated catch block
                                        e.printStackTrace();
                                    }
                                 }
                             });
                         }
                    }
             });
          }
    }

}

}

这篇关于Tomcat 7上的Servlet 3异步任务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆