spring boot花式注册三大组件

目录

    • 1.使用注解方式注册:
    • 2.使用xxxRegistrationBean方式注册三大组件
    • 3.动态注册三大组件
      • 3.1、利用`ServletContextInitializer` 的`onStartup`方法得到的`ServletContext`:
      • 3.2、`ServletContainerInitializer`的`onStartup`方法得到的`ServletContext`:

1.使用注解方式注册:

servlet

//拦截/hello请求
//loadOnStartup属性可以设置加载servlet的顺序
//		<Load-on-startup>标记容器是否应该在web应用程序启动的时候就加载这个servlet,即实例化并调用其init()方法。
//			它的值必须是一个整数,表示servlet被加载的先后顺序。
//			如果该元素的值为负数或者没有设置,则容器会当Servlet被请求时再加载。
//			如果值为正整数或者0时,表示容器在应用启动时就加载并初始化这个servlet,值越小,servlet的优先级越高,就越先被加载。值相同时,容器就会自己选择顺序来加载。
@WebServlet(
        name="helloServlet",
        urlPatterns="/hello",
        initParams={
                @WebInitParam(name = "charset", value = "utf-8")/*这里可以放一些初始化的参数*/
        }
)
public class HelloServlet extends HttpServlet {
//    @Override
//    public void init() throws ServletException {
//        System.out.println("HelloServlet初始化啦!!!");
//    }
    @Override
    public void init(ServletConfig config) throws ServletException {
        super.init(config);
        System.out.println("HelloServlet初始化啦!!!");
        String charset = config.getInitParameter("charset");
        String servletName = config.getServletName();
        System.out.println(charset);
        System.out.println(servletName);
    }
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello...");
    }
    @Override
    public void destroy() {
        System.out.println("HelloServlet销毁啦!!!");
    }
}

Filter过滤器:

//Filter称之为过滤器,是用来做一些拦截的任务, 在Servlet接受请求之前,
// 做一些事情,如果不满足限定,可以拒绝进入Servlet
@WebFilter(
        filterName="filter0_FilerDemo2",
        /*通配符(*)表示对所有的web资源进行拦截*/
        urlPatterns = "/*",
        initParams = {
                @WebInitParam(name = "charset", value = "utf-8")/*这里可以放一些初始化的参数*/})
public class Filter0_FilerDemo2 implements Filter {
    private String filterName;
    private String charset;:
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("======================");
        System.out.println("过滤器Filter0_FilerDemo2初始化啦!!");
        /*初始化方法  接收一个FilterConfig类型的参数 该参数是对Filter的一些配置*/
        filterName = filterConfig.getFilterName();
        charset = filterConfig.getInitParameter("charset");
        System.out.println("过滤器名称:" + filterName);
        System.out.println("字符集编码:" + charset);
        System.out.println("======================");    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("过滤器Filter0_FilerDemo2...");
        // 放行,如果不放行,那么被访问的资源将无法看见
        filterChain.doFilter(servletRequest, servletResponse);
    }
    @Override
    public void destroy() {
        System.out.println("过滤器Filter0_FilerDemo2销毁啦!!");
        }
}

Listener监听器:

@WebListener
public class MyServletContextListener implements ServletContextListener {
    //项目启动就初始化
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("MyServletContextListener初始化啦!!");
        ServletContext sc = servletContextEvent.getServletContext();
        sc.setAttribute("lzh", "liuzhihui");
    }
    //项目关闭调用
    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("MyServletContextListener销毁啦!!");
    }
}

注意:如果使用的是Spring Boot内嵌服务器,需要在配置类上面添加额外的 @ServletComponentScan 注解来开启 Servlet 组件扫描功能,如果使用的是独立的服务器,则不需要添加,会使用服务器内部的自动发现机制。

2.使用xxxRegistrationBean方式注册三大组件

  • 注册Servlet,使用ServletRegistrationBean
  • 注册Filter,使用FilterRegistrationBean
  • 注册ServletListener,使用ServletListenerRegistrationBean

注册过滤器:注册监听器和servlet类似

public class MyFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter start。。。。。");
        filterChain.doFilter(servletRequest,servletResponse);
    }
    @Override
    public void destroy() {
    }
}
@Configuration
public class MyFilterConfig {

    @Bean
    public FilterRegistrationBean myFilter(){
        FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean();
        filterRegistrationBean.setFilter(new MyFilter());
        filterRegistrationBean.setUrlPatterns(Arrays.asList("/hellofilter1","/hellofilter2"));
        return filterRegistrationBean;
    }
}

SpringBoot帮我们自动配置SpringMVC的时候,自动注册Springmvc的前端控制器(DispatcherServlet),就是使用的这种方式注册的DispatcherServlet
DispatcherServletAutoConfigurationDispatcherServletRegistrationBean 继承自ServletRegistrationBean

@Bean(name = DEFAULT_DISPATCHER_SERVLET_REGISTRATION_BEAN_NAME)
@ConditionalOnBean(value = DispatcherServlet.class, name = DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServletRegistrationBean dispatcherServletRegistration(DispatcherServlet dispatcherServlet,
		WebMvcProperties webMvcProperties, ObjectProvider<MultipartConfigElement> multipartConfig) {
	DispatcherServletRegistrationBean registration = new DispatcherServletRegistrationBean(dispatcherServlet,
			webMvcProperties.getServlet().getPath());
	//默认拦截: / 所有请求;包静态资源,但是不拦截jsp请求; /*会拦截jsp
	//可以通过spring.mvc.servlet.path=来修改SpringMVC前端控制器默认拦截的请求路径
	registration.setName(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME);
	registration.setLoadOnStartup(webMvcProperties.getServlet().getLoadOnStartup());
	multipartConfig.ifAvailable(registration::setMultipartConfig);
	return registration;
}

3.动态注册三大组件

如果我们导的第三方jar,它们里面有一些组件,比如:阿里巴巴的连接池里面的Filter,如果是用web.xml,可以直接配在配置文件中,但是使用注解版时,没有了web.xml,怎么注册这些组件到servlet容器中呢?

ServletContext 提供了几个动态注册的方法,如下所示:

spring boot花式注册三大组件_第1张图片
所以只要获取到ServletContext就能往servlet容器中注入三大组件。

3.1、利用ServletContextInitializeronStartup方法得到的ServletContext

@Component
public class ServletConfig implements ServletContextInitializer {
    @Override
    public void onStartup(ServletContext servletContext) {
        ServletRegistration initServlet = servletContext
                .addServlet("initServlet", InitServlet.class);
        initServlet.addMapping("/initServlet");
        initServlet.setInitParameter("name", "javastack");
        initServlet.setInitParameter("sex", "man");
    }
}

本质上,ServletRegistrationBeanFilterRegistrationBean以及ServletListenerRegistrationBean,都属于ServletContextInitializer
spring boot花式注册三大组件_第2张图片

3.2、ServletContainerInitializeronStartup方法得到的ServletContext

使用ServletContainerInitializer:使用外置的Tomcat启动web应用时,会扫描当前应用每一个jar里面META-INF/services/ javax.servlet.ServletContainerInitializer指定的实现类,启动并运行这个实现类的方法

//容器启动的时候会将@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, "/*");
		
	}
}

注意使用ServletContainerInitializer方式:还需做如下配置META-INF/services/ javax.servlet.ServletContainerInitializerMETA-INF放在Resource

com.example.springboot07mybaties.servlet3.MyServletContainerInitializer

此外还可以使用WebApplicationInitializer注册三大组件。
甚至还可以使用监听器来注册:

public class UserListener  implements ServletContextListener {
    //监听ServletContext启动初始化
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("UserListener...contextInitialized...");
        ServletContext servletContext = servletContextEvent.getServletContext();
    }
}

总之,只要能获取到ServletContext ,就能注册三大组件。

你可能感兴趣的:(spring,boot,spring,boot)