在 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