Servlet 3.0 规范(二)注解驱动和异步请求

Servlet 3.0 规范(二)注解驱动和异步请求

在 Servlet 3.0 时支持注解启动,不再需要 web.xml 配制文件。

一、Servlet 3.0 组件

Servlet 容器的组件大致可以分为以下几类:

Servlet 3.0 组件
  ├── 组件申明注解
  |    ├── @javax.servlet.annotation.WebServlet
  |    ├── @javax.servlet.annotation.WebFilter
  |    ├── @javax.servlet.annotation.WebListener
  |    ├── @javax.servlet.annotation.ServletSecurity
  |    ├── @javax.servlet.annotation.HttpMethodConstraint
  |    └── @javax.servlet.annotation.HttpConstraint
  |
  ├── 配置申明
  |    └── @javax.servlet.annotation.WebInitParam
  |
  ├── 上下文
  |    └── @javax.servlet.AsyncContext
  ├── 事件
  |    └── @javax.servlet.AsyncEvent
  ├── 监听器
  |    └── @javax.servlet.AsyncListener
  |
  ├── Servlet 组件注册
  |    ├── javax.servlet.ServletContext#addServlet()
  |    └── javax.servlet.ServletRegistration
  |
  ├── Filter 组件注册
  |    ├── javax.servlet.ServletContext#addFilter()
  |    └── javax.servlet.FilterRegistration
  |
  ├── 监听器注册
  |    ├── javax.servlet.ServletContext#addListener()
  |    └── javax.servlet.AsyncListener
  |
  └── 自动装配
       ├── javax.servlet.ServletContainerInitializer
       └── @javax.servlet.annotation.HandlesTypes

二、注解驱动

1.1 Servlet 3.0 注解

Servlet 3.0 常用注解: @WebServlet @WebFilter @WebInitParam @WebListener

@WebServlet("/hello")
public class HelloServert extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.getWriter().write("hello");
    }
}

Tomcat 7.x 以上的版本启动,访问 localhost:8080/hello。Tomcat 对 Servlet 的支持如下:

Tomcat 6.x 实现 Servert 2.5
Tomcat 7.x 实现 Servert 3.0
Tomcat 8.x 实现 Servert 3.1
Tomcat 9.x 实现 Servert 4.0

1.2 ServletContainerInitializer

  1. Servlet 容器启动会扫描当前应用的每一个 jar 包 ServletContainerInitializer 的实现。

  2. 通过每个 jar 包下的 META-INFO/services/javax.servlet.ServletContainerInitializer 文件:
    com.github.binarylei.MyServletContainerInitializer

javax.servlet.ServletContainerInitializer

@HandlesTypes(HelloServert.class)
public class MyServletContainerInitializer implements ServletContainerInitializer {

    /**
     * @param c                 @HandlesTypes 指定,HelloServert 子类
     * @param ServletContext    注册三大组件(Servlet Filter Listener)
     */
    @Override
    public void onStartup(Set<Class<?>> set, ServletContext ctx)
            throws ServletException {
        // 1. 处理感兴趣的类
        System.out.println(set);

        // 2.1. 注册 Servert
        ServletRegistration.Dynamic servlet = ctx.addServlet("myServlet", HelloServert.class);
        servlet.addMapping("/*");

        // 2.2. 注册 Listener
        ctx.addListener(MyServletContextListener.class);

        // 2.3. 注册 Filter
        FilterRegistration.Dynamic filter = ctx.addFilter("myFileter", MyFilter.class);
        filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),
                true, "/*");
    }
}

在 Servlet 3.0 时支持注解启动,其中 ServletContainerInitializer 和 HandlesTypes 都是 Servlet 3.0 的规范。

  • ServletContainerInitializer 只有一个方法 onStartup
  • HandlesTypes 感兴趣的类,启动时会通过 onStartup 传递给 clazzs 参数。HandlesTypes 会找到 HelloServert 所有的子类(不包括 HelloServert 自己)

三、异步请求

@WebServlet(value = "/async", asyncSupported = true)
public class AsyncServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        // 1. 支持异步处理 asyncSupported = true
        // 2. 开启异步处理模式
        AsyncContext asyncContext = req.startAsync();

        // 3. 子线程处理响应
        asyncContext.start(() -> {
            process();
            // 4. 处理结束
            asyncContext.complete();
            PrintWriter writer = asyncContext.getResponse().getWriter();
            writer.write("async");
        });
    }

    private void process() {
        TimeUnit.SECONDS.sleep(5);
    }
}

每天用心记录一点点。内容也许不重要,但习惯很重要!

posted on 2019-01-01 09:36  binarylei  阅读(842)  评论(0编辑  收藏  举报

导航