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监听项目启动时注册组件。

  • 相关阅读:
    Access Token 机制详解
    Authorization Code 授权原理和实现方法
    Access Token 与 Refresh Token
    简单介绍 Oauth2.0 原理
    进行web开发时应该考虑的架构性因素
    查看linux服务器CPU数量
    Centos7 修改主机名
    Centos6 编译安装Python3.6
    Linux编译安装软件常见问题及排查
    问题列表
  • 原文地址:https://www.cnblogs.com/wangxiayun/p/10154633.html
Copyright © 2011-2022 走看看