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

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

  • 相关阅读:
    2017.5.2-afternoon
    2017.5.2-morning
    2017.4.27-afternoon
    2017.4.27-morning
    2017.4.26-morning
    2017.4.26-afternoon
    2017.4.24-4.25
    2017.4.21-afternoon
    Linux下进程间通信(二)----共享内存和信号量
    Linux下进程间通信(一)----概述和管道通信
  • 原文地址:https://www.cnblogs.com/binarylei/p/10204208.html
Copyright © 2020-2023  润新知