Spring Boot 基于Servlet 的异步服务

Servlet 3.0中支持异步的HTTP请求,本章基于Spring Boot 搭建一个基于Servlet 3.0异步HTTP服务,如果你对异步和同步还有疑问或者概念不清晰,请自行上网查阅相关资料。

  1. 在pom.xml中引入配置
        
            org.springframework.boot
            spring-boot-starter-web
        
  1. 建立Service层接口
public interface PiceaService {
    //无返回参数方法
    void task() throws Exception;
    //有返回参数方法
    String task2() throws Exception;
}
  1. 建立Service层实现
    Service层接口与实现,跟其他正常同步请求一样,没有差别。
@Service
public class PiceaServiceImpl implements PiceaService {

    @Override
    public void task() throws Exception {
        System.out.println("------------------------在看貂蝉,不要打扰--------------");
        Thread.sleep(1000);
    }

    @Override
    public String task2 () throws Exception {
        int k = 1;
        System.out.println("------------------------在看鱼,不要打扰--------------");
        Thread.sleep(1000);
        return (String.valueOf(k));
    }
}
  1. 最重要的一步,建立Contoller层方法
    在Contoller层,主要是利用了Servlet 3.0为异步处理提供的监听器,使用AsyncListener接口表示。此接口负责管理异步事件,它可以监控如下四种事件:
    1). 异步线程开始时,调用AsyncListener的onStartAsync(AsyncEvent event)方法;
    2). 异步线程出错时,调用AsyncListener的onError(AsyncEvent event)方法;
    3). 异步线程执行超时,则调用AsyncListener的onTimeout(AsyncEvent event)方法;
    4). 异步执行完毕时,调用AsyncListener的onComplete(AsyncEvent event)方法;
@RestController
public class PiceaServletContoller {

    @Autowired
    private PiceaService piceaService;

    @RequestMapping("/task")
    public void task(HttpServletRequest request,
                     HttpServletResponse response) throws Exception {
        piceaService.task();
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().println("这个是无返回的处理方法");
    }

    @RequestMapping("/asyncTask")
    public void asyncTask(HttpServletRequest request,
                            HttpServletResponse response) throws Exception {
        System.out.println("控制层线程:" + Thread.currentThread().getName());
        AsyncContext asyncContext = request.startAsync();
        asyncContext.addListener(new AsyncListener() {
            @Override
            public void onComplete(AsyncEvent asyncEvent) throws IOException {
                // 异步执行完毕时
                System.out.println("异步执行完毕");
            }

            @Override
            public void onTimeout(AsyncEvent asyncEvent) throws IOException {
                //异步线程执行超时
                System.out.println("异步线程执行超时");
            }

            @Override
            public void onError(AsyncEvent asyncEvent) throws IOException {
                //异步线程出错时
                System.out.println("异步线程出错");
            }

            @Override
            public void onStartAsync(AsyncEvent asyncEvent) throws IOException {
                //异步线程开始时
                System.out.println("异步线程开始");
            }
        });
        asyncContext.setTimeout(3000);
        asyncContext.start(new Runnable() {
            @Override
            public void run() {
                try {
                    System.out.println("异步执行线程:" + Thread.currentThread().getName());
                    String str = piceaService.task2();
                    Thread.sleep(1000);
                    asyncContext.getResponse().setCharacterEncoding("UTF-8");
                    asyncContext.getResponse().setContentType("text/html;charset=UTF-8");
                    asyncContext.getResponse().getWriter().println("这是【异步】的请求返回: " +str);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }catch (Exception e) {
                    e.printStackTrace();
                }
                //异步请求完成通知,所有任务完成了,才执行
                asyncContext.complete();
            }
        });
    }
}
  1. 测试结果及方法
    浏览器中分别访问http://localhost:2001/task和http://localhost:2001/asyncTask测试结果。
    在异步时,明显可以看到执行线程是不一样的。
    Spring-boot-async-servlet.png

老板,欢迎下次再来!

其它注意

本文章样例:
工程名:spring-boot-async-servlet
GitHub:https://github.com/zzyjb/SpringBootLearning

你可能感兴趣的:(Spring Boot 基于Servlet 的异步服务)