• Spring注解驱动开发(七)-----servlet3.0、springmvc


    ServletContainerInitializer

    Shared libraries(共享库) / runtimes pluggability(运行时插件能力)

    ServletContainerInitializer初始化web容器:

    在web容器启动时为提供给第三方组件机会做一些初始化的工作,例如注册servlet或者filters等,servlet规范(JSR356)中通过ServletContainerInitializer实现此功能。

    每个框架要使用ServletContainerInitializer就必须在对应的jar包的META-INF/services 目录创建一个名为javax.servlet.ServletContainerInitializer的文件,文件内容指定具体的ServletContainerInitializer实现类,那么,当web容器启动时就会运行这个初始化器做一些组件内的初始化工作。

    示例

    1、MyServletContainerInitializer

    package com.atguigu.servlet;
    
    import java.util.EnumSet;
    import java.util.Set;
    
    import javax.servlet.DispatcherType;
    import javax.servlet.FilterRegistration;
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRegistration;
    import javax.servlet.annotation.HandlesTypes;
    
    import com.atguigu.service.HelloService;
    
    //容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来;
    //传入感兴趣的类型;
    @HandlesTypes(value={HelloService.class})
    public class MyServletContainerInitializer implements ServletContainerInitializer {
    
        /**
         * 应用启动的时候,会运行onStartup方法;
         * 
         * Set<Class<?>> arg0:感兴趣的类型的所有子类型;
         * ServletContext arg1:代表当前Web应用的ServletContext;一个Web应用一个ServletContext;
         */
        @Override
        public void onStartup(Set<Class<?>> arg0, ServletContext sc) throws ServletException {
            // TODO Auto-generated method stub
            System.out.println("感兴趣的类型:");
            for (Class<?> claz : arg0) {
                System.out.println(claz);
            }
        }
    
    }

    2、配置

    需要新建META-INF/services文件夹,并且文件名为javax.servlet.ServletContainerInitializer,文件内容就为MyServletContainerInitializer的包路径

    这样应用启动的时候,会运行onStartup方法,会将所有的HelloService(所有子类或其实现类)拿到。

    3、额外添加servlet、filter以及listener组件

    修改MyServletContainerInitializer:

    package com.atguigu.servlet;
    
    import java.util.EnumSet;
    import java.util.Set;
    
    import javax.servlet.DispatcherType;
    import javax.servlet.FilterRegistration;
    import javax.servlet.ServletContainerInitializer;
    import javax.servlet.ServletContext;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRegistration;
    import javax.servlet.annotation.HandlesTypes;
    
    import com.atguigu.service.HelloService;
    
    //容器启动的时候会将@HandlesTypes指定的这个类型下面的子类(实现类,子接口等)传递过来;
    //传入感兴趣的类型;
    @HandlesTypes(value={HelloService.class})
    public class MyServletContainerInitializer implements ServletContainerInitializer {
    
        /**
         * 应用启动的时候,会运行onStartup方法;
         * 
         * Set<Class<?>> arg0:感兴趣的类型的所有子类型;
         * ServletContext arg1:代表当前Web应用的ServletContext;一个Web应用一个ServletContext;
         * 
         * 1)、使用ServletContext注册Web组件(Servlet、Filter、Listener)
         * 2)、使用编码的方式,在项目启动的时候给ServletContext里面添加组件;
         *         必须在项目启动的时候来添加;
         *         1)、ServletContainerInitializer得到的ServletContext;
         *         2)、ServletContextListener得到的ServletContext;
         */
        @Override
        public void onStartup(Set<Class<?>> arg0, ServletContext sc) throws ServletException {
            // TODO Auto-generated method stub
            System.out.println("感兴趣的类型:");
            for (Class<?> claz : arg0) {
                System.out.println(claz);
            }
            
            //注册组件  ServletRegistration  
            ServletRegistration.Dynamic servlet = sc.addServlet("userServlet", new UserServlet());
            //配置servlet的映射信息
            servlet.addMapping("/user");
            
            
            //注册Listener
            sc.addListener(UserListener.class);
            
            //注册Filter  FilterRegistration
            FilterRegistration.Dynamic filter = sc.addFilter("userFilter", UserFilter.class);
            //配置Filter的映射信息
            filter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
            
        }
    
    }

    4、UserServlet

    package com.atguigu.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    public class UserServlet extends HttpServlet {
        
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // TODO Auto-generated method stub
            resp.getWriter().write("tomcat...");
        }
    
    }

    5、UserFilter

    package com.atguigu.servlet;
    
    import java.io.IOException;
    
    import javax.servlet.Filter;
    import javax.servlet.FilterChain;
    import javax.servlet.FilterConfig;
    import javax.servlet.ServletException;
    import javax.servlet.ServletRequest;
    import javax.servlet.ServletResponse;
    
    public class UserFilter implements Filter {
    
        @Override
        public void destroy() {
            // TODO Auto-generated method stub
            
        }
    
        @Override
        public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
                throws IOException, ServletException {
            // 过滤请求
            System.out.println("UserFilter...doFilter...");
            //放行
            arg2.doFilter(arg0, arg1);
            
        }
    
        @Override
        public void init(FilterConfig arg0) throws ServletException {
            // TODO Auto-generated method stub
            
        }
    
    }

    6、UserListener

    package com.atguigu.servlet;
    
    import javax.servlet.ServletContext;
    import javax.servlet.ServletContextEvent;
    import javax.servlet.ServletContextListener;
    
    /**
     * 监听项目的启动和停止
     * @author lfy
     *
     */
    public class UserListener implements ServletContextListener {
    
        
        //监听ServletContext销毁
        @Override
        public void contextDestroyed(ServletContextEvent arg0) {
            // TODO Auto-generated method stub
            System.out.println("UserListener...contextDestroyed...");
        }
    
        //监听ServletContext启动初始化
        @Override
        public void contextInitialized(ServletContextEvent arg0) {
            // TODO Auto-generated method stub
            ServletContext servletContext = arg0.getServletContext();
            System.out.println("UserListener...contextInitialized...");
        }
    
    }

    Servlet3.0整合springMVC

    接入分析

    1、web容器在启动的时候,会扫描每个jar包下的META-INF/services/javax.servlet.ServletContainerInitializer
    2、加载这个文件指定的类SpringServletContainerInitializer
    3、spring的应用一启动会加载感兴趣的WebApplicationInitializer接口的下的所有组件;
    4、并且为WebApplicationInitializer组件创建对象(组件不是接口,不是抽象类)
      1)、AbstractContextLoaderInitializer:创建根容器;createRootApplicationContext();
      2)、AbstractDispatcherServletInitializer:
          创建一个web的ioc容器;createServletApplicationContext();
          创建了DispatcherServlet;createDispatcherServlet();
          将创建的DispatcherServlet添加到ServletContext中;
          getServletMappings();
      3)、AbstractAnnotationConfigDispatcherServletInitializer:注解方式配置的DispatcherServlet初始化器
          创建根容器:createRootApplicationContext()
          getRootConfigClasses();传入一个配置类
          创建web的ioc容器: createServletApplicationContext();
          获取配置类;getServletConfigClasses();

    总结:
    以注解方式来启动SpringMVC;继承AbstractAnnotationConfigDispatcherServletInitializer;实现抽象方法指定DispatcherServlet的配置信息;-----通过看源码,得出这个逻辑

    ===========================
    定制SpringMVC;
    1)、@EnableWebMvc:开启SpringMVC定制配置功能;
    <mvc:annotation-driven/>;

    2)、配置组件(视图解析器、视图映射、静态资源映射、拦截器。。。)
    extends WebMvcConfigurerAdapter

    整合 

    1、MyWebAppInitializer

    package com.atguigu;
    
    import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
    
    import com.atguigu.config.AppConfig;
    import com.atguigu.config.RootConfig;
    
    //web容器启动的时候创建对象;调用方法来初始化容器以前前端控制器
    public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    
        //获取根容器的配置类;(Spring的配置文件)   父容器;
        @Override
        protected Class<?>[] getRootConfigClasses() {
            // TODO Auto-generated method stub
            return new Class<?>[]{RootConfig.class};
        }
    
        //获取web容器的配置类(SpringMVC配置文件)  子容器;
        @Override
        protected Class<?>[] getServletConfigClasses() {
            // TODO Auto-generated method stub
            return new Class<?>[]{AppConfig.class};
        }
    
        //获取DispatcherServlet的映射信息
        //  /:拦截所有请求(包括静态资源(xx.js,xx.png)),但是不包括*.jsp;
        //  /*:拦截所有请求;连*.jsp页面都拦截;jsp页面是tomcat的jsp引擎解析的;
        @Override
        protected String[] getServletMappings() {
            // TODO Auto-generated method stub
            return new String[]{"/"};
        }
    
    }

    2、RootConfig-----spring容器配置类

    package com.atguigu.config;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.stereotype.Controller;
    
    //Spring的容器不扫描controller;父容器
    @ComponentScan(value="com.atguigu",excludeFilters={
            @Filter(type=FilterType.ANNOTATION,classes={Controller.class})
    })
    public class RootConfig {
    
    }

    3、AppConfig-----springmvc容器配置类

    package com.atguigu.config;
    
    
    import java.util.List;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.format.FormatterRegistry;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.stereotype.Controller;
    import org.springframework.validation.MessageCodesResolver;
    import org.springframework.validation.Validator;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
    import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    import com.atguigu.controller.MyFirstInterceptor;
    
    //SpringMVC只扫描Controller;子容器
    //useDefaultFilters=false 禁用默认的过滤规则;
    @ComponentScan(value="com.atguigu",includeFilters={
            @Filter(type=FilterType.ANNOTATION,classes={Controller.class})
    },useDefaultFilters=false)
    @EnableWebMvc
    public class AppConfig  extends WebMvcConfigurerAdapter  {
    
    }

    还记得之前在使用xml方式的这些配置吗?

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:mvc="http://www.springframework.org/schema/mvc"
        xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    
        <!--将SpringMVC处理不了的请求交给tomcat;静态资源 就可以访问 -->
        <mvc:default-servlet-handler/>
        <!-- SpringMVC的高级功能开启 -->
        <mvc:annotation-driven />
        
        <!-- <mvc:interceptors>
        
        </mvc:interceptors>
        <mvc:view-controller path=""/> -->
    
    </beans>

    通过注解也可以实现:

    定制SpringMVC;
    1)、@EnableWebMvc:开启SpringMVC定制配置功能;
    <mvc:annotation-driven/>;

    2)、配置组件(视图解析器、视图映射、静态资源映射、拦截器。。。)
    extends WebMvcConfigurerAdapter

    修改AppConfig

    package com.atguigu.config;
    
    
    import java.util.List;
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.ComponentScan.Filter;
    import org.springframework.context.annotation.FilterType;
    import org.springframework.format.FormatterRegistry;
    import org.springframework.http.converter.HttpMessageConverter;
    import org.springframework.stereotype.Controller;
    import org.springframework.validation.MessageCodesResolver;
    import org.springframework.validation.Validator;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
    import org.springframework.web.servlet.HandlerExceptionResolver;
    import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
    import org.springframework.web.servlet.config.annotation.ContentNegotiationConfigurer;
    import org.springframework.web.servlet.config.annotation.CorsRegistry;
    import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
    import org.springframework.web.servlet.config.annotation.EnableWebMvc;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.PathMatchConfigurer;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
    import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    import com.atguigu.controller.MyFirstInterceptor;
    
    //SpringMVC只扫描Controller;子容器
    //useDefaultFilters=false 禁用默认的过滤规则;
    @ComponentScan(value="com.atguigu",includeFilters={
            @Filter(type=FilterType.ANNOTATION,classes={Controller.class})
    },useDefaultFilters=false)
    @EnableWebMvc
    public class AppConfig  extends WebMvcConfigurerAdapter  {
    
        //定制
        
        //视图解析器
        @Override
        public void configureViewResolvers(ViewResolverRegistry registry) {
            // TODO Auto-generated method stub
            //默认所有的页面都从 /WEB-INF/ xxx .jsp
            //registry.jsp();
            registry.jsp("/WEB-INF/views/", ".jsp");
        }
        
        //静态资源访问
        @Override
        public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
            // TODO Auto-generated method stub
            configurer.enable();//-----相当于<mvc:default-servlet-handler/>,把处理不了的请求交给tomcat
        }
        
        //拦截器
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            // TODO Auto-generated method stub
            //super.addInterceptors(registry);
            registry.addInterceptor(new MyFirstInterceptor()).addPathPatterns("/**");
        }
    
    }

    MyFirstInterceptor:

    package com.atguigu.controller;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    public class MyFirstInterceptor implements HandlerInterceptor {
    
        //目标方法运行之前执行
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
                throws Exception {
            // TODO Auto-generated method stub
            System.out.println("preHandle..."+request.getRequestURI());
            return true;
        }
    
        //目标方法执行正确以后执行
        @Override
        public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
                ModelAndView modelAndView) throws Exception {
            // TODO Auto-generated method stub
            System.out.println("postHandle...");
    
        }
    
        //页面响应以后执行
        @Override
        public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
                throws Exception {
            // TODO Auto-generated method stub
            System.out.println("afterCompletion...");
        }
    
    }

     

  • 相关阅读:
    从程序员到项目经理(5):程序员加油站 不是人人都懂的学习要点
    从程序员到项目经理(14):项目经理必须懂一点“章法”
    从程序员到项目经理(17):你不是一个人在战斗思维一换天地宽
    从程序员到项目经理(19):想改变任何人都是徒劳的
    tp5时间戳转换日期格式
    win10让人愤怒的磁盘占用100%问题
    uniapp将时间日期格式化的组件unidateformat的用法
    Asp.Net大型项目实践系列第二季(一)哥欲善其事,必先利其器...
    Asp.Net大型项目实践(9)ExtJs实现系统框架页(非iframe,附源码,在线demo)
    Asp.Net大型项目实践(10)基于MVC Action粒度的权限管理(在线demo,全部源码)
  • 原文地址:https://www.cnblogs.com/alimayun/p/11129904.html
Copyright © 2020-2023  润新知