前言
这几章都比较枯燥哈,要耐心一点,配置这些也很重要&有必要(相比于业务处理)。
万一出了什么幺蛾子,同时你知道了是配置、初始化的问题,就可以从学的这些入手来Debug了。
Servlet 中的 Listener(监听器)
基础知识
在设计模式——观察者模式设计中,最容易理解和体现的恐怕就属Listener了(监听器),Tomcat服务器中这个概念用的很广泛。(某些憨憨别把Listener当接口或者类来看了)
Servlet中的 Listener ,能够让Servlet很方便地从另一个角度,去控制程序和数据。
在Tomcat服务器中,具体设计的Listener有:
- Listener:
- EventListeners(有关事件)
- ServletContextAttributeListener
- ServletRequestAttributeListener
- ServletRequestListener
- HttpSessionAttributeListener
- LifecycleListeners(有关生命周期)
- ServletContextListener
- HttpSessionListener
- EventListeners(有关事件)
具体区别嘛,来人,上图:
具体有哪些接口和接口的说明,请在需要的时候自行查表。(就不浪费篇幅了,重在理解)
这些 Listener 的实现类可以配置在 web.xml 中的 标签中。
(当然也可以在应用程序中自己动态地添加 Listener,一般都这样做了)
需要注意的是 ServletContextListener(第二类第二个) 在容器启动之后就不能再添加新的,因为它所监听的事件已经不会再出现。
事例
如同在Spring框架中,ContextLoaderListener (org.springframework.web.context.ContextLoaderListener) 就实现了一个ServletContextListener。
当启动容器,进行加载时,ContextLoaderListener 类就会在contextInitialized()方法中初始化Spring容器 :
public void contextInitialized(ServletContextEvent event){
this.contextLoader = createContextLoader();
if(this.contextLoader == null){
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
Spring加载容器有两种(我知道的):
- 通过web.xml的标签中配置的applicationContext.xml的路径找到该文件。
- /WEB_INF/路径下查找默认的applicationContext.xml文件。
Servlet 中的 Filter(过滤器)
Filter用起来是最爽的了,可以通过和组合来使用。
其实啊,Filter可以完成和Servlet同样的工作(可以看做Servlet的变种),而且更灵活——它比Servlet多提供了一个FilterChain对象,来帮我们控制请求(xxxresponse)的流转(也就是一种预处理)。
总体性地说,Filterd的作用:对用户请求进行预处理,接着将请求交给Servlet进行处理并生成响应,最后Filter再对服务器响应进行后处理。
基础知识
-
Filter用处:
-
在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest。
-
根据需要检查HttpServletRequest,也可以修改HttpServletRequest头和数据。(HttpServletResponse同理)
-
-
Filter种类:
- 用户授权的Filter:Filter负责检查用户请求,根据请求过滤用户非法请求。
- 日志Filter:详细记录某些特殊的用户请求。
- 负责解码的Filter:包括对非标准编码的请求解码
另外,一个Filter可拦截多个请求或响应;一个请求或响应也可被多个拦截
-
Filter的实现类
FilterConfig和FilterChain的具体实现类是ApplicationFilterConfig 和 ApplicationFilterChain。
但是,Filter的实现类是由用户自定义的,实现接口就行。(其中ApplicationFilterChain类将多个Filter串联起来,组成一个链)
Filter中重要的三个接口方法:
-
init(FilterConfig):
初始化的时候调用该方法,可以写一些环境变量配置等的获取操作
-
doFilter(ServletRequest, ServletResponse, FilterChain):
核心功能,正如上面的**“总结”**所言,就不多说了,提一点:
- 调用FilterChain.doFilter()传递请求,到下一个Filter中去处理
- 不调用的话,请求就直接返回了。
-
destroy():
销毁时调用,而且Web容器会再次嗲用doFilter()方法!
-
-
Filter执行流程:
Filter的核心实际上还是FilterChain对象,这个对象保存了最终的Servlet和所以Filter对象(保存在了filters[]数组中),下面是执行的时序图:
然后 = =,CSDN有点毒瘤,mermaid给我砍了,下面的类分别是 :- StandarWapperValue
- ApplicationFilterFactory
- ApplicationFilterChain
- Filter
- Servlet
事例
这是一个用来解决全站中文乱码问题的过滤器【开发过程中写的,不是框架自带的】:(具体编解码知识请到3.x学习)
public class CharacterEncodingFilter implements Filter {
private FilterConfig filterConfig = null;
//设置默认的字符编码
private String defaultCharset = "UTF-8";
public void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String charset = filterConfig.getInitParameter("charset");
if(charset==null){
charset = defaultCharset;
}
request.setCharacterEncoding(charset);
response.setCharacterEncoding(charset);
response.setContentType("text/html;charset="+charset);
MyCharacterEncodingRequest requestWrapper = new MyCharacterEncodingRequest(request);
chain.doFilter(requestWrapper, response);
}
public void init(FilterConfig filterConfig) throws ServletException {
//得到过滤器的初始化配置信息
this.filterConfig = filterConfig;
}
public void destroy() {
}
}
章节总结
第九章从:
- Servlet容器的启动
- Servlet初始化细节
- Servlet体系结构
来描绘一个粗略的结构图,方面后面的讲解和理解。