在 Servlet 3.0 時支持註解啓動,再也不須要 web.xml 配製文件。java
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
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 6.x 實現 Servert 2.5 Tomcat 7.x 實現 Servert 3.0 Tomcat 8.x 實現 Servert 3.1 Tomcat 9.x 實現 Servert 4.0
Servlet 容器啓動會掃描當前應用的每個 jar 包 ServletContainerInitializer 的實現。app
經過每一個 jar 包下的 META-INFO/services/javax.servlet.ServletContainerInitializer 文件:
com.github.binarylei.MyServletContainerInitializer異步
@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
只有一個方法 onStartupHandlesTypes
感興趣的類,啓動時會經過 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); } }
天天用心記錄一點點。內容也許不重要,但習慣很重要!ide