目录
一、Filter过滤器的使用
【1】Filter技术概述
Filter技术,即过滤器技术,是Servlet三大核心技术之一,主要用于拦截请求进行过滤操作,是实现例如权限控制、全站乱码解决、压缩响应等功能的基础,是web开发中最实用的技术之一。
【2】Filter访问机制
过滤器可以配置多个,多个过滤器之前采用责任链模式,依次进行拦截。只有所有过滤器都通过,才可以访问到最终的资源。
如果是在web.xml中进行配置,通过<filter>和<filter-mapping>标签实现配置。<filter-mapping>用来设置此外过滤器的虚拟路径,只有符合过滤的虚拟路径,才会被过滤器拦截。不符合将不会被拦截,此外拦截的顺序是通过标签<filter-mapping>的上下顺序进行过滤。
如果是通过WebFilter()注解方式进行配置,可以使用filterName属性来指定filter的名称,可以使用value属性或者urlPatterns属性来指定Filter过滤的虚拟路径。只有符合过滤的虚拟路径,才会被过滤器拦截。不符合将不会被拦截,此外拦截的规则是通过属性filterName的字母顺序进行过滤。
【3】Filter的生命周期
在tomcat服务器启动后加载当前web应用时,filter会创建一个对象驻留在内存当中,在创建对象之后,立刻调用init方法完成初始化的操作。每次过滤器拦截请求或响应,都会导致它身上的doFilter方法执行,在doFilter方法中可以选择是否放行,如果放行在放行代码前后可以添加额外操作。当tomcat服务器关闭,在服务器关闭之前,filter对象销毁,对象销毁之前会自动调用destroy方法完成善后的操作。
补充:
【1】关于doFilter方法,每次过滤器拦截请求和响应之后,都会执行,请求过来时,会执行chain.doFilter(req, resp);语句前面的内容,响应回来之后,会执行chain.doFilter(req, resp);语句后面的内容。这点有点像请求转发执行的过程。
【2】关于责任链,在一个web应用中可以配置多个过滤器,只有请求响应都通过这些过滤器,才可以到达对应的资源身上,这些过滤器组成的链称为过滤器链。这些过滤器链称之为过滤器的责任链模式。
【4】使用过滤器处理中文乱码问题
使用服务器(tomcat7)及其以下版本,默认使用的是iso8859-1字符集,因为iso8859-1编码没有中文,所以会产生乱码。
如果页面使用的是POST请求提交方式,我们可以使用request.setCharacterEncoding("utf-8");设置编码字符集为utf-8。
如果页面使用的是GET请求提交方式,我们可以使用new String(request.getParameter("username").getBytes("iso8859-1"),"utf-8");方式处理乱码。
如果我们使用的处理POST处理方式则不能处理GET请求方式的乱码,但如果我们使用GET请求方式,却可以处理POST请求方式。所以使用GET请求方式进行处理。但如果使用GET请求方式,则不容易获取,需要处理的参数。所以,我们可以对getParameters()之类的方法进行增强,通过装饰者模式进行增强方法。
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
class MyHttpServletRequest extends HttpServletRequestWrapper {
private String encode;
public MyHttpServletRequest(HttpServletRequest request, String encode) {
super(request);
this.encode = encode;
}
//重写的方法
/**
* 返回一个经过乱码处理后的map对象
* @return
*/
@Override
public Map<String, String[]> getParameterMap() {
//获取原有的map值,依次作出乱码处理,处理后将值放入到新map中,并返回
Map<String, String[]> map = super.getParameterMap();
//创建新的map,用于存放处理好的map参数
Map<String, String[]> rmap = new HashMap<String, String[]>();
try {
//遍历map
for (Map.Entry<String, String[]> entry: map.entrySet()) {
String key = entry.getKey();
String[] values = entry.getValue();
String[] rvalues = new String[values.length];
for (int i = 0; i < values.length; i++) {
rvalues[i] = new String(values[i].getBytes("iso8859-1"),encode);
}
//将乱码处理后的数组放入到新map中
rmap.put(key,rvalues);
}
return rmap;
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public String[] getParameterValues(String name) {
Map<String, String[]> map = getParameterMap();
return map.get(name);
}
@Override
public String getParameter(String name) {
String[] values = getParameterValues(name);
//如果数组为null,则返回null,否则将数组中的第一个元素作为方法返回值使用
return values==null?null:values[0];
}
}
书写一个自定义类,继承HttpServletRequestWrapper 实现类,增强getParameterMap、getParameterValues、getParameter方法。
之所以继承HttpServletRequestWrapper 类,是因为HttpServletRequestWrapper 帮我们实现了ServletRequest与HttpServletRequest接口的方法。HttpServletRequest继承ServletRequest接口,HttpServletRequestWrapper 实现HttpServletRequest接口。
在Filter类上配置注解为@WebFilter(filterName = "EncodingFilter",value="/*")
在过滤器doFilter中书写以下内容便可以对中文进行过滤。
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//请求乱码处理
HttpServletRequest request = new MyHttpServletRequest((HttpServletRequest) req);
//响应乱码处理
resp.setContentType("text/html;charset="+encode);
chain.doFilter(request, resp);
}
二、Listener监听器的使用
【1】监听器技术概述
Listener是Servlet三大技术之一。Servlet三大技术包含Filter、Listener、Servlet。
如果希望自己的网站收集一些必要的数据,可以通过Listener监听器去监听获取。在某一个事件触发监听器之后,监听器会执行对应的操作。
【2】监听器的种类
1、监听三大作用域创建和销毁的监听器
ServletContextListener | 监听ServletContext域的创建销毁 |
HttpSessionListener | 监听Session域的创建销毁 |
ServletRequestListener | 监听request域的创建销毁 |
2、监听三大作用域中属性变化的监听器(创建、更新、销毁)
ServletContextAttributeListener | 监听ServletContext域中属性的变化 |
HttpSessionAttributeListener | 监听Session域中属性的变化 |
ServletRequestAttributeListener | 监听request域中属性的变化 |
实现以上三个接口,可以获得到三个域对象,从而获取用户的信息,参数,譬如响应头,请求头,url地址等等。
3、监听JavaBean在Session域中状态变化的监听器
HttpSessionBindingListener | 监听javabean在session域中添加和销毁事件 |
HttpSessionActivationListener | 让javabean自己感知到自己随着session被钝化和活化。 |
Javabean实现HttpSessionBindingListener和HttpSessionActivationListener接口,会重写这两个接口中的方法,HttpSessionBindingListener用于感知javabean在session域的变化。
HttpSessionActivationListener让javabean自己感知到自己随着session被钝化和活化。
钝化是指当服务器正常关闭时,还存活着的session 会随着服务器的关闭被以文件(“SESSIONS.ser”)的形式存储在tomcat 的work 目录下。
活化是指当服务器再次正常开启时,服务器会找到之前的“SESSIONS.ser” 文件,从中恢复之前保存起来的Session 对象。此时SESSIONS.ser这个文件会被消除。
想要随着Session 被钝化、活化的对象它的类必须实现Serializable 接口。关于序列化的问题,可参考https://blog.youkuaiyun.com/c17315377559/article/details/100044843