Filter过滤器与Listener监听器的使用(全站中文乱码处理)

目录

 

一、Filter过滤器的使用

【1】Filter技术概述

【2】Filter访问机制

【3】Filter的生命周期

【4】使用过滤器处理中文乱码问题

二、Listener监听器的使用

【1】监听器技术概述

【2】监听器的种类


一、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.csdn.net/c17315377559/article/details/100044843

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章