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
组件扫描功能,如果使用的是独立的服务器,则不需要添加,会使用服务器内部的自动发现机制。
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
。
DispatcherServletAutoConfiguration
:DispatcherServletRegistrationBean
继承自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;
}
如果我们导的第三方jar
,它们里面有一些组件,比如:阿里巴巴的连接池里面的Filter
,如果是用web.xml
,可以直接配在配置文件中,但是使用注解版时,没有了web.xml
,怎么注册这些组件到servlet
容器中呢?
ServletContext
提供了几个动态注册的方法,如下所示:
所以只要获取到ServletContext
就能往servlet
容器中注入三大组件。
ServletContextInitializer
的onStartup
方法得到的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");
}
}
本质上,ServletRegistrationBean
、FilterRegistrationBean
以及ServletListenerRegistrationBean
,都属于ServletContextInitializer
ServletContainerInitializer
的onStartup
方法得到的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.ServletContainerInitializer
:META-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
,就能注册三大组件。