Javaweb之过滤器

Javaweb之过滤器

一、过滤器(Filter)

配置了过滤器之后,在访问目标资源前,会先经过过滤器处理,之后再由过滤器根据业务逻辑判断是否需要访问目标资源

二、过滤器使用步骤

1. 新建一个类,实现 javax.servlet.Filter 接口,该接口有三个方法

public interface Filter {
    // 初始化方法,web应用启动时执行一次该方法
    public default void init(FilterConfig filterConfig) throws ServletException {}

    // 执行过滤的方法,比如可以做表单校验之类的操作
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException;

    // Servlet容器在销毁过滤器实例前调用该方法,在该方法中释放Servlet过滤器占用的资源
    public default void destroy() {}
}

涉及到的几个对象:

  • FilterConfig:可以通过它的 getServletContext() 方法获取到ServletContext对象。
  • FilterChain:调用它的 doFilter(ServletRequest request, ServletResponse response) 方法,表示当前过滤器执行完,交给过滤器链中下个过滤器操作,如果本过滤器已经是最后一个,则直接访问目标资源。

2. 在 web.xml 文件中配置,配置方法类似 Servlet

<?xml version="1.0" encoding="UTF-8"?>  
<web-app>
    <filter>
        <filter-name>XxxFilter</filter-name>
        <filter-class>全类名</filter-class>
        <init-param>
            <param-name>参数名称</param-name>
            <param-value>参数值</param-value>
        </init-param>
        <dispatcher>REQUEST</dispatcher>
    </filter>
    <filter-mapping>
        <filter-name>XxxFilter</filter-name>
        <!-- 过滤路径 -->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
</web-app>

其中,dispatcher 标签有四个值可选:REQUEST/FORWARD/INCLUDE/ERROR

  • REQUEST:当用户直接访问页面时,才会调用该过滤器
  • FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用
  • INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用
  • ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用

    如果没做任何配置,默认是 REQUEST,也可以同时配置多个 dispatcher。
    另外,如果多个过滤器对同一个资源都进行了配置,其执行顺序取决于各个过滤器的 <filter-mapping> 标签在 xml 中的顺序,在执行过程中,若某一过滤器在 doFilter() 方法中未执行 chain.doFilter() 方法,后续过滤器便不会执行。

3. 也可以通过注解的方式来配置 Filter

@WebFilter(urlPatterns = { "/xxx" })
也可以配置各项参数,功能与 xml 配置类似, 不再赘述。

三、过滤器的应用之全站乱码问题

1,需求

处理请求的参数时,若参数带有中文,即会出现乱码。出现乱码的原因根据请求方式的不同有两种原因:

  • get:浏览器发起 get 请求,中文按照 jsp 的 pageEncoding 编码将字符串转化为字节数组发送给服务器,因为是 get 方式,服务器以 ISO-8859-1 的方式将字节数组转化为该编码的字符串,在处理的时候把取得的字符串按照 ISO-8859-1 的编码还原成字节数组,最后用正确编码创建字符串,即得到传递的信息,也就有了如下经典代码:
response.setContentType("text/hmtl;charset=utf-8");
String param = request.getPrameter("name");
String realParam = new String(param.getBytes("ISO-8859-1"), "UTF-8")
response.getWriter().println(realParam);

实际上,高版本 tomcat 严格按照 RFC 3986 规范进行访问解析,而 RFC 3986 规范定义了Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符,RFC 3986 中指定了以下字符为保留字符:! * ’ ( ) ; : @ & = + $ , / ? # [ ] 。所以通常不建议在 get 请求中直接传递中文参数,如有需求可以客户端先用 Base64 对中文编码,服务器端再解码。

  • post:浏览器发起 post 请求,获取参数时默认采用 ISO-8859-1 编码,因此获取到的中文参数乱码,post 请求的乱码问题解决非常简单,将请求编码和响应编码设置成一致并且支持中文的编码即可,代码如下:
response.setContentType("text/hmtl;charset=utf-8");
request.setCharacterEncoding("UTF-8");
String param = request.getPrameter("name");
response.getWriter().println(param);

以上即为传统解决乱码问题的方案,这样做的一个问题就是,在每一个 Servlet 中都需要编写这段代码,代码重用率不高。在这种情况下,就可以使用 Filter,将所有请求过滤,并解决编码问题,就无需在每个 Servlet 中重复代码了。

2,步骤

  • 以 post 为例,新建一个类实现 Filter 接口,将上述代码放到 doFilter 方法中即可,这里使用注解注册过滤器
@WebFilter(urlPatterns = { "/*" })
public class CodeFilter implements Filter {

    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                         throws IOException, ServletException {
        response.setContentType("text/html;charset=utf-8");
        request.setCharacterEncoding("utf-8");
        chain.doFilter(request, response);
    }

    public void init(FilterConfig fConfig) throws ServletException {
    }
}
  • 之后所有的 Servlet 中都无需再重复写上述代码,直接获取参数即可
String name = request.getParameter("name");
response.getWriter().println(name);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值