Servlet 3.0 規範(二)註解驅動和異步請求

Servlet 3.0 規範(二)註解驅動和異步請求

在 Servlet 3.0 時支持註解啓動,再也不須要 web.xml 配製文件。java

1、Servlet 3.0 組件

Servlet 容器的組件大體能夠分爲如下幾類:git

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

2、註解驅動

1.1 Servlet 3.0 註解

Servlet 3.0 經常使用註解: @WebServlet @WebFilter @WebInitParam @WebListenergithub

@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 以上的版本啓動,訪問 。Tomcat 對 Servlet 的支持以下: web

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 的實現。app

  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 的規範。async

  • ServletContainerInitializer 只有一個方法 onStartup
  • HandlesTypes 感興趣的類,啓動時會經過 onStartup 傳遞給 clazzs 參數。HandlesTypes 會找到 HelloServert 全部的子類(不包括 HelloServert 本身)

3、異步請求

@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);
    }
}

天天用心記錄一點點。內容也許不重要,但習慣很重要!ide

相關文章
相關標籤/搜索