Spring Boot原生异步请求API说明

Laughing
2019-07-28 / 0 评论 / 1,306 阅读 / 正在检测是否收录...
温馨提示:
本文最后更新于2024年05月31日,已超过268天没有更新,若内容或图片失效,请留言反馈。

异步请求api调用说明

在编写实际代码之前,我们来了解下一些关于异步请求的api的调用说明。

获取AsyncContext:根据HttpServletRequest对象获取

AsyncContext asyncContext = request.startAsync();  

设置监听器:可设置其开始、完成、异常、超时等事件的回调处理

public interface AsyncListener extends EventListener {  
    void onComplete(AsyncEvent event) throws IOException;  
    void onTimeout(AsyncEvent event) throws IOException;  
    void onError(AsyncEvent event) throws IOException;  
    void onStartAsync(AsyncEvent event) throws IOException;  
}

说明

  1. onStartAsync:异步线程开始时调用
  2. onError:异步线程出错时调用
  3. onTimeout:异步线程执行超时调用
  4. onComplete:异步执行完毕时调用
    一般上,我们在超时或者异常时,会返回给前端相应的提示,比如说超时了,请再次请求等等,根据各业务进行自定义返回。同时,在异步调用完成时,一般需要执行一些清理工作或者其他相关操作。

需要注意的是只有在调用request.startAsync前将监听器添加到AsyncContext,监听器的onStartAsync方法才会起作用,而调用startAsyncAsyncContext还不存在,所以第一次调用startAsync是不会被监听器中的onStartAsync方法捕获的,只有在超时后又重新开始的情况下onStartAsync方法才会起作用。

设置超时:通过setTimeout方法设置,单位:毫秒。

一定要设置超时时间,不能无限等待下去,不然和正常的请求就一样了。

Servlet方式实现异步请求

面已经提到,可通过HttpServletRequest对象中获得一个AsyncContext对象,该对象构成了异步处理的上下文。所以,我们来实际操作下。

编写一个简单控制层

package Net.XiangCaoWuYu.Controllers;  

import io.swagger.annotations.Api;  
import io.swagger.annotations.ApiOperation;  
import org.slf4j.Logger;  
import org.slf4j.LoggerFactory;  
import org.springframework.web.bind.annotation.*;  
import javax.servlet.AsyncContext;  
import javax.servlet.AsyncEvent;  
import javax.servlet.AsyncListener;  
import javax.servlet.http.HttpServletRequest;  
import javax.servlet.http.HttpServletResponse;  
import java.io.IOException;  

/** 
 * ClassName: AsyncController <br/> 
 * Description: <br/> 
 * date: 2019/7/28 16:06<br/> 
 * 
 * @author lisen01<br /> 
 * @since JDK 1.8 
 */  
@RestController  
@Api(tags = "测试异步请求")  
@ResponseBody  
@RequestMapping(value = "/AsyncTest")  
public class ServletAsyncController {  
  
    private final static Logger logger = LoggerFactory.getLogger(ServletAsyncController.class);  
  
    @PostMapping(value = "test")  
    @ApiOperation(value = "测试异步请求")  
    public void test(HttpServletRequest request, HttpServletResponse response) {  
        AsyncContext context = request.startAsync();  
        context.addListener(new AsyncListener() {  
            @Override  
            public void onComplete(AsyncEvent asyncEvent) throws IOException {  
                logger.info("执行完成");  
            }  
  
            @Override  
            public void onTimeout(AsyncEvent asyncEvent) throws IOException {  
                logger.info("执行超时:");  
            }  
        
            @Override  
            public void onError(AsyncEvent asyncEvent) throws IOException {  
                logger.info("发生错误:" + asyncEvent.getThrowable());  
            }  
        
            @Override  
            public void onStartAsync(AsyncEvent asyncEvent) throws IOException {  
                logger.info("开始执行:");  
            }  
        });  
        
        //设置超时  
        context.setTimeout(2000);  
        
        //开启线程  
        context.start(new Runnable() {  
            @Override  
            public void run() {  
                try{  
                    Thread.sleep(100);  
                    logger.info("内部线程:"+Thread.currentThread().getName());  
                    context.getResponse().setCharacterEncoding("UTF-8");  
                    context.getResponse().setContentType("text/html;charset=utf-8");  
                    context.getResponse().getWriter().println("这是内部线程");  
                    //异步请求完成通知  
                    //此时整个请求才完成  
                    //其实可以利用此特性 进行多条消息的推送 把连接挂起。。  
                    context.complete();  
                } catch (InterruptedException e) {  
                    e.printStackTrace();  
                } catch (IOException e) {  
                    e.printStackTrace();  
                }  
            }  
        });  
        
        //此时之类 request的线程连接已经释放了  
        logger.info("线程:" + Thread.currentThread().getName());  
    }  
}

注意:异步请求时,可以利用ThreadPoolExecutor自定义个线程池

使用过滤器时,需要加入asyncSupported为true配置,开启异步请求支持

@WebServlet(urlPatterns = "/okong", asyncSupported = true )     
public  class AsyncServlet extends HttpServlet ...  
0

评论 (0)

取消
  1. 头像
    青云
    Windows 10 · Google Chrome

    画图

    回复
  2. 头像
    test
    Windows 10 · Google Chrome

    太好了。

    回复