本篇将介绍如下几点java
Servlet是基于Java技术的web组件,容器托管的,用于生成动态内容。像其余基于Java的组件技术同样, Servlet也是基于平台无关的Java类格式,被编译为平台无关的字节码,能够被基于Java技术的webserver 动态加载并运行。容器(平时咱们所使用的tomcat就是其中一种servlet容器),有时候也叫作servlet引擎,是webserver为支持servlet功能扩展的部分。客户端 经过Servlet容器实现的请求/应答模型与Servlet交互。(引用自oracle官方servlet3.1规范文档)web
servlet按照一个严格定义的生命周期被管理,该生命周期包括:如何被加载?实例化?初始化?处理客户端请求?什么时候结束服务? 该生命周期能够经过Servlet接口中的API来表示:init、service、destroyspring
servlet容器负责加载和实例化servlet,加载和实例化能够发生在容器启动时,或者延迟初始化直到容器有请求须要处理时。(经过开发者配置来肯定)编程
servlet容器必须在处理客户端请求以前,对servlet实例进行初始化(即调用Servlet.init接口)。能够完成一些读取持久化配置数据、初始化资源等一次性的动做。tomcat
完成初始化以后,servlet容器可使用该servlet来处理客户端请求。(容器经过开发者的配置,即servlet-mapping来寻找适合当前请求的servlet)客户端请求由ServletRequest类型来封装表示、Servlet响应由ServletResponse类型来封装表示。这两个类型的对象都由容器进行实例化,在调用Servlet处理客户端请求时传递给Servlet的service方法。在Http请求的场景下,容器提供的实现对应为HttpServletRequest、HttpServletResponse。一个servlet实例应对多个客户端请求的状况,致使了咱们须要在处理请求时保证线程安全。安全
在servlet技术中,除了Servlet接口用于处理请求这个组件接口外,还存在Filter、Listener这两个重要的组件接口。 其中Filter是一种代码重用的技术,运行运行过程当中改变进入资源的请求和资源返回的响应中的有效负载和header信息。便可以在分发请求给servlet处理以前对请求进行拦截,以后再servlet完成处理,返回响应后对响应进行拦截。能够用于日志记录、验证等需求。 和servlet生命周期同样,应用一样存在生命周期。监听应用生命周期事件可让开发人员更好的控制ServletContext、HTTPSession和ServletRequest的生命周期,能够更好的进行代码分解。Servlet事件监听器支持在ServletContext、HTTPSession和ServletRequest状态改变时进行事件通知。oracle
实现本身的Filter能够经过实现接口javax.servlet.Filter来完成,以后经过web.xml或者注解配置到Servlet容器中,让容器在处理请求时应用此时配置的Filterapp
public class FirstFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println(getClass().getName() + " init()");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println(getClass().getName() + " doFilter()");
chain.doFilter(request, response);
}
@Override
public void destroy() {
}
}
复制代码
Listener的种类能够分为:框架
在收到客户端请求时,web容器肯定转发到哪一个web应用(获取servlet上下文路径),以后用于映射到servlet的路径是请求对象的请求URL减去上下文和路径参数部分,以后应用如下步骤来找出servlet来处理请求,短路原则,一旦找到匹配的servlet,以后的步骤直接跳过异步
经过@WebListener注解配置ServletContextListener实现类,在容器初始化servlet上下文时,调用ServletContext的API来注册
@WebListener
public class FirstServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
ServletContext servletContext = sce.getServletContext();
ServletRegistration.Dynamic dynamic = servletContext.addServlet("firstServlet", FirstServlet.class);
dynamic.addMapping("/first", "/first/*");
dynamic.setLoadOnStartup(1);
ServletRegistration.Dynamic dynamic2 = servletContext.addServlet("secondServlet", SecondServlet.class);
dynamic2.addMapping("/second", "/second/*");
dynamic2.setLoadOnStartup(1);
// 异步servlet
ServletRegistration.Dynamic firstAsyncServlet = servletContext.addServlet("firstAsyncServlet", FirstAsyncServlet.class);
firstAsyncServlet.setLoadOnStartup(1);
firstAsyncServlet.setAsyncSupported(true);
firstAsyncServlet.addMapping("/async/first", "/async/first/*");
// TODO Filter调用顺序???
FilterRegistration.Dynamic filterRegistration = servletContext.addFilter("secondFilter", SecondFilter.class);
filterRegistration.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD),
true, "/first");
FilterRegistration.Dynamic filterDynamic = servletContext.addFilter("firstFilter", FirstFilter.class);
filterDynamic.addMappingForUrlPatterns(
EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD), false, "/first");
// 非阻塞IO servlet
ServletRegistration.Dynamic firstNoBIOServlet = servletContext.addServlet("firstNoBIOServlet", FirstNoBlockIOServlet.class);
firstNoBIOServlet.setLoadOnStartup(1);
firstNoBIOServlet.setAsyncSupported(true);
firstNoBIOServlet.addMapping("/nobio/first", "/nobio/first/*");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
}
复制代码
在spring中利用基于SPI机制的ServletContainerInitializer来初始化容器,具体实现方式是:
public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// 指定ROOT ApplicationContext的配置类
return new Class[]{RootConfig.class};
}
@Override
protected Class<?>[] getServletConfigClasses() {
// 指定Web ApplicationContext的配置类
return new Class[]{WebConfig.class};
}
@Override
protected String[] getServletMappings() {
// 指定DispatcherServlet的servlet-mapping,此处指定为default servlet。任何未找到映射的请求都会由DispatcherServlet来处理请求
return new String[]{"/"};
}
@Override
protected Filter[] getServletFilters() {
// 配置Filter
return super.getServletFilters();
}
}
复制代码
这篇文章中梳理了Servlet中的经常使用技术,主要涉及Servlet、Filter、Listener的知识点和配置细节。以后引伸出springMVC是如何利用这些知识点来构建一个web框架的。servlet做为java web开发中的基石是每一个开发者都必须掌握的技能。关于springMVC中的更多原理细节将在后续文章整理发出,期待你的关注