zoukankan      html  css  js  c++  java
  • Spring注解开发系列VII --- Servlet3.0

    Servlet3.0简介

    Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布。该版本在前一版本(Servlet 2.5)的基础上提供了若干新特性用于简化 Web 应用的开发和部署。其中有几项特性的引入让开发者感到非常兴奋,同时也获得了 Java 社区的一片赞誉之声:

    1.异步处理支持:有了该特性,Servlet 线程不再需要一直阻塞,直到业务处理完毕才能再输出响应,最后才结束该 Servlet 线程。在接收到请求之后,Servlet 线程可以将耗时的操作委派给另一个线程来完成,自己在不生成响应的情况下返回至容器。针对业务处理较耗时的情况,这将大大减少服务器资源的占用,并且提高并发处理速度。

    2.新增的注解支持:该版本新增了若干注解,用于简化 Servlet、过滤器(Filter)和监听器(Listener)的声明,这使得 web.xml 部署描述文件从该版本开始不再是必选的了。

    3.可插性支持:熟悉 Struts2 的开发者一定会对其通过插件的方式与包括 Spring 在内的各种常用框架的整合特性记忆犹新。将相应的插件封装成 JAR 包并放在类路径下,Struts2 运行时便能自动加载这些插件。现在 Servlet 3.0 提供了类似的特性,开发者可以通过插件的方式很方便的扩充已有 Web 应用的功能,而不需要修改原有的应用。

    也就是说我们完全可以通过注解来取代web.xml,这也就是注解版的web开发。

    一.@WebServlet("/hello")

    @WebServlet(name="Hello",urlPatterns={"/hello.view"},loadOnStartup=1)  
    public class Hello extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("hello,world");
        }
    }

    上面的@WebServlet告知容器,loadOnStartup,当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载。

    HelloServlet这个Servlet的名称是Hello,这是由name属性指定的,而如果客户端请求的URL是/hello.view,则由具Hello名称的Servlet来处理,这是由urlPatterns属性来指定的。在Java EE相关应用程序中使用标注时,可以记得的是,没有设置的属性通常会有默认值。例如,若没有设置@WebServlet的name属性,默认值会是Servlet的类完整名称。

    相类似的注解还有@WebFilter(),@WebListener() 分别可以使用类似注解注册Filter以及Listener

    二.ServletContainerInitializer

    如果是本地项目可以通过上述注解来注册组件,但是如果是第三方的插件,无法通过@WebServlet()等注解注册组件,在web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filtes等,servlet规范中通过ServletContainerInitializer实现此功能

    1.创建配置文件

    首先创建在src或java目录下创建一个META-INF目录,然后在该目录下创建services目录,services下再创建javax.servlet.ServletContainerInitializer文件

    2.创建MyServletContainerInitializer类该类必须实现ServletContainerInitializer

    //容器启动时,会将HandlesTypes指定类型下面的子类,实现类,子接口传递过来
    @HandlesTypes(value = {HelloService.class})
    public class MyServletContainerInitializer implements ServletContainerInitializer  {
        /**
         * 应用启动,会运行onStartup方法
         * ServletContext arg1:代表当前WEb应用的ServletContext,一个web应用相当于一个webContext
         *
         * @param set 所有HandlesTypes指定的类型以及子类
         * @param servletContext
         * @throws ServletException
         */
        @Override
        public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
            for (Class<?> cla:set){
                System.out.println("============================="+cla.getName());
            }
    
        }
    }

    3.配置文件内容

    在services目录下创建的文件里面内容为MyServletContainerInitializer的全类名:com.wang.servlet.MyServletContainerInitializer

    4.启动应用

    启动服务器,启动后会自动调用MyServletContainerInitializer的onStartup方法,其中@HandlesTypes类注解的作用是可以将感兴趣的类的子类(不包括该类)通过onStartup的第一个参数,以集合的形式传进来传进来。

    三.使用ServletContainerInitializer注册三大组件

    public class UserServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            resp.getWriter().write("wanggggggg");
        }
    }
    /**
     * 监听项目的启动和停止
     */
    public class UserListener implements ServletContextListener {
        //监听启动
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            System.out.println("UserListener contextInitialized.....");
        }
        //监听销毁
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("UserListener contextDestroyed.....");
        }
    }
    public class UserFilter implements Filter {
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("UserFilter init...");
        }
    
        @Override
        public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
            System.out.println("UserFilter doFilter...");
            filterChain.doFilter(servletRequest,servletResponse);
        }
    
        @Override
        public void destroy() {
            System.out.println("UserFilter destroy...");
        }
    }

     使用编码的方式给servlet注册组件。

      @Override
        public void onStartup(Set<Class<?>> set, ServletContext servletContext) throws ServletException {
            for (Class<?> cla:set){
                System.out.println("============================="+cla.getName());
            }
            //注册Servlet
            ServletRegistration.Dynamic userServlet = servletContext.addServlet("userServlet", new UserServlet());
            //配置Servlet映射信息
            userServlet.addMapping("/userServlet");
    
            //注册监听器
            servletContext.addListener(UserListener.class);
    
            //注册Filter
            FilterRegistration.Dynamic userFilter = servletContext.addFilter("userFilter", UserFilter.class);
            //配置Filter的映射信息
            userFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST),true,"/");
        }

    注意:必须在项目启动的时候添加组件,在项目运行时不允许注册组件,可以通过以下两种方式:

    1.使用ServletContainerInitializer机制来注册组件;

    2.利用ServletContextListener监听项目启动时注册组件。

  • 相关阅读:
    centos7.6 使用yum安装mysql5.7
    解决hadoop本地库问题
    docker-compose 启动警告
    docker 安装zabbix5.0 界面乱码问题解决
    docker 部署zabbix问题
    zookeeper 超时问题
    hbase regionserver异常宕机
    (转载)hadoop 滚动升级
    hadoop Requested data length 86483783 is longer than maximum configured RPC length
    zkfc 异常退出问题,报错Received stat error from Zookeeper. code:CONNECTIONLOSS
  • 原文地址:https://www.cnblogs.com/wangxiayun/p/10154633.html
Copyright © 2011-2022 走看看