【左京淳的JAVA WEB学习笔记】第八章 服务器异步设定

在特定时间开放抢票的网站,常常会有流量爆炸的问题。这时候可以透过服务器的异步处理来解决。
让买票处理使用主线程,而需要等待的出票处理使用异步线程。
要使用异步线程,需在Servlet前注解支持异步处理。然後利用request物件叫出AsyncContext物件。
这时response回应就会等到AsyncContext.complete()结束时才被送出。关键程序码如下:

@WebServlet(urlPatterns="/AsynSvl",asyncSupported=true)
AsyncContext ac = request.startAsync();
ServletResponse res = ac.getResponse();

新建一个测试案例

  1. asynTest.jsp
"<body>
  <input type=""button"" value=""测试"" onclick=""submit()""><br>
  <span id=""info"" style=""color:red;font-size:12px""></span>
</body>"
"<%
  String path = request.getContextPath();
  String basePath = request.getScheme() + ""://"" + request.getServerName()  
  + "":"" + request.getServerPort() + path + ""/"";
%><script src=""http://ajax.microsoft.com/ajax/jQuery/jquery-1.4.4.min.js""></script>
<script type=""text/javascript"">
  function submit(){
    var url = ""<%=basePath%>AsynSvl"";
    $.ajax({
        type:""get"",
        url:url,
        success:function(msg){
            document.getElementById(""info"").innerHTML=msg;
        }
    })
  }
</script>"
(余略…)
  1. AsynSvl
@WebServlet(urlPatterns="/AsynSvl",asyncSupported=true)
public class AsynSvl extends HttpServlet {
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    AsyncContext ac = request.startAsync();
    ServletResponse res = ac.getResponse();
    res.setCharacterEncoding("utf-8");
    PrintWriter out = res.getWriter();
    try {
      Thread.sleep(3000);
    }catch(Exception e){
    }
    out.println("异步处理OK");
    out.flush();
    out.close();
  }
(余略…)
}

如果异步处理的url有经过过滤器(Filter),则过滤器也要设定支持异步。

@WebFilter(urlPatterns = "/*",
  asyncSupported=true,
  initParams = {@WebInitParam(name = "encoding",value = "utf-8")})

直接拜访jsp网址,然後点选测试。
http://localhost:8080/Hello/main/asynTest.jsp

成功的话会看到"异步处理OK"字样

异步监听器

利用异步监听器可以检测异步处理的执行状况。监听器可能会收到以下几种结果,可以设定相应的处理:

  • onStartAsync //AsyncContext重新创建时触发此方法
  • onComplete //正常结束时触发此方法
  • onTimeout //超时的时候触发此方法,默认为30秒,也可利用setTimeout()自行设定。
  • onError //错误时触发此方法

修改刚才的AsynSvl,在里面添加一个MyListener类。

public class AsynSvl extends HttpServlet {
  class MyListener implements AsyncListeren{
    public void onComplete(AsyncEvent e) throws IOException{
      System.out.println(e.getAsyncContext().hashCode() + "onComplete");
    }
    public void onError(AsyncEvent e) throws IOException{
      System.out.println(e.getAsyncContext().hashCode() + "onError");
    }
    public void onStartAsync(AsyncEvent e) throws IOException{
      System.out.println(e.getAsyncContext().hashCode() + "onStartAsync");
    }
    public void onTimeout(AsyncEvent e) throws IOException{
      System.out.println(e.getAsyncContext().hashCode() + "onTimeout");
    }
  }
(中略…)
  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    AsyncContext ac = request.startAsync();
    ac.addListener(new MyListener());
    ServletResponse res = ac.getResponse();
    res.setCharacterEncoding("utf-8");
    PrintWriter out = res.getWriter();
    try {
      Thread.sleep(3000);
    }catch(Exception e){
    }
    out.println("异步处理OK");
    out.flush();
    out.close();
      ac.complete();
      //ac.setTimeout(5000);
  }
}

建立了MyListener类之後别忘了在doGet()里面添加这行ac.addListener(new MyListener());
不然待会儿测试的时候,脑海中就会响起五月天的听不到
当执行到ac.complete()时,监听器会在後台印出onComplete。
如果把这行注解掉,那麽预设等待30秒後,会得到onTimeout及onComplete。
如果注解掉ac.complete()後,再添加ac.setTimeout(5000),则五秒後会得到onTimeout及onComplete。


<<:  什麽是零信任(What is Zero Trust)?

>>:  .net framework 4.5.2 升级到 .net framework 4.6.2 笔记

CDN 与网站资讯安全服务简介

前言 当一个网站取得 Public IP 与 internet 连接时,也就表示网站正开始面对来自全...

用React刻自己的投资Dashboard Day8 - useState hook

tags: 2021铁人赛 React 在Card元件中有使用到useState,是React中一个...

Day4 如何安装Git的环境

大家好我是乌木白,今日要和大家分享如何安装Git的环境! 如何安装Git的环境 安装在 Windo...

第二天:什麽是 CI/CD?

虽然一讲到敏捷开发、DevOps 时就很常听到 CI/CD 这些词汇,不过到底什麽是 CI?又什麽是...