本文引自:https://www.cnblogs.com/dudududu/p/8505177.html

参考博客:http://www.cnblogs.com/coderland/p/5902878.html

https://www.cnblogs.com/HigginCui/p/5772514.html

基本概念在参考博客中,已经讲的很清楚了。这里,简单总结一下,并贴一个完整实例。

总结:

1)Filter称为过滤器。它是一个服务器端的组件。通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊的功能。例如实现URL级别的权限访问控制、过滤敏感词汇、压缩响应信息等一些高级功能。

2)Filter技术主要进行对用户请求的预处理,也可以对服务器响应进行后处理。

这两种情况都属于直接访问页面(也包括直接访问Servlet),故在配置<filter-mapping>时,可以不写<dispatcher>,使用默认的REQUEST。(也可以写出来直接指定为REQUEST)

一般地,客户端提交请求信息通过HttpServletRequest到达Servlet,然后Servlet进行处理并产生响应,响应通过HttpServletResponse传递到客户端。

Filter在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest,根据需要检查HttpServletRequest,或者修改HttpServletRequest 头和数据,称为对用户请求的预处理。

Filer在HttpServletResponse从Servlet到达客户端之前,拦截HttpServletResponse ,根据需要检查HttpServletResponse,或者修改HttpServletResponse头和数据,称为对服务器响应进行后处理。

3)Filer的生命周期:

实例化(web.xml)——>初始化(init()方法)——>过滤(doFilter()方法)——>销毁(destroy()方法)

    public void init(FilterConfig filterConfig) throws ServletException;//初始化
//filter对象只会创建一次,init方法也只会执行一次
和我们编写的Servlet程序一样,Filter的创建和销毁由WEB容器负责。 web 应用程序启动时,web 容器读取web.xml配置文件,
将创建Filter 的实例对象,并调用其init方法(这个init方法中可以读取web.xml文件中过滤器的参数)完成对象的初始化功能,
从而为后续的用户请求作好拦截的准备工作。开发人员可以通过init方法的参数FilterConfig对象,获得当前filter配置信息。 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;//拦截请求
//可执行n次
这个方法完成实际的过滤操作。当客户请求访问与过滤器关联的URL的时候执行该方法。FilterChain参数的doFilter方法用于访问后续过滤器或者调用目标资源。 public void destroy();//销毁
//该方法在Filter的生命周期中仅执行一次。
Filter对象创建后会驻留在内存,当web应用移除或服务器停止时才销毁。在Web容器卸载 Filter 对象之前被调用。在这个方法中,可以释放过滤器使用的资源。

4)Filter开发步骤:

  (1)编写java类实现javax.servlet.Filter接口,并实现其doFilter方法;

  (2)在web.xml文件中对编写的filter类进行注册,并设置它所能拦截的资源。

5)Filter链:

  在一个web应用中,可以开发编写多个Filter,这些Filter组合起来称之为一个Filter链。

  web服务器根据Filter在web.xml文件中的注册顺序,决定先调用哪个Filter,当第一个Filter的doFilter方法被调用时,web服务器会创建一个代表Filter链的FilterChain对象传递给该方法。在doFilter方法中,开发人员如果调用了FilterChain对象的doFilter方法,则web服务器会检查FilterChain对象中是否还有filter,如果有,则调用第2个filter,如果没有,则调用目标资源。

6)FilterConfig接口:

用户在配置filter时,可以使用为filter配置一些初始化参数(<init-param>),当web容器实例化Filter对象,调用其init方法时,会把封装了filter初始化参数的filterConfig对象传递进来。因此开发人员在编写filter时,通过filterConfig对象的方法获取相关初始化信息。

7)在检查URI路径中的是否含有某个初始值,对于servlet来说,是指配置servlet时指定的url-pattern的值,而不是servlet类名。

8)在实现Filter的类中的doFilter()方法中,需要将传进来的ServletRequest转换为HttpServletRequest,将传进来的ServletResponse转换为HttpServletResponse,才能进行相关方法的调用。

9)过滤器的分类: 

  (1)REQUEST:当用户直接访问页面(包括用户请求的预处理和对服务器响应进行后处理)时,Web容器将会调用过滤器。如果目标资源是通过RequestDispatcher的include()或forward()方法访问时,那么该过滤器就不会被调用。 
  (2)INCLUDE:如果目标资源是通过RequestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
  (3)FORWARD:如果目标资源是通过RequestDispatcher的forward()方法访问时,那么该过滤器将被调用,除此之外,该过滤器不会被调用。
  (4)ERROR:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。

贴个例子,实现两个过滤器一个判断用户是否登录然后跳转指定页面,一个用来处理乱码问题:

login.jsp:

<form action="doLogin" method="post">
用户名:<input type="text" name="userName"/><br/>
密码:<input type="password" name="password"/><br/>
<input type="submit" value="登录"/>
<input type="reset" value="重置"/>
</form>

创建一个success.jsp用于展示跳转成功。

创建登录跳转Servlet:

package com.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; @SuppressWarnings("serial")
public class DoLoginServlet extends HttpServlet { @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
this.doPost(req, resp);
} @Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String userName=req.getParameter("userName");
String password=req.getParameter("password");
System.out.println(userName);
if("张三".equals(userName)&&"123".equals(password)){
//校验通过
HttpSession session = req.getSession();
session.setAttribute("userName", userName);
       //这里必须使用重定向,不能使用请求转发
       //请求转发:request.getRequestDispatcher().forward()是属于FORWARD类型的过滤器,需要在配置过滤器时,写明FORWARD类型的<dispatcher>
resp.sendRedirect("success.jsp");
}else
{
resp.sendRedirect("login.jsp");
} }
}

注意:

请求转发:即request.getRequestDispatcher().forward(),是一种服务器的行为,客户端只有一次请求,服务器端转发后会将请求对象保存,地址栏中的URL地址不会改变,得到响应后服务器端再将响应发给客户端;

请求重定向:即response.sendRedirect(),是一种客户端行文,从本质上讲等同于两次请求,前一次请求对象不会保存,地址栏的URL地址会改变。

请求转发与请求重定向的区别,参考博客:http://blog.csdn.net/u012877472/article/details/50804568

创建第一个过滤器(解决乱码):

package com.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest; public class SetEconding implements Filter { @Override
public void destroy() {
// TODO Auto-generated method stub } @Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException { HttpServletRequest req=(HttpServletRequest)arg0;
//解决乱码问题
req.setCharacterEncoding("UTF-8"); //别忘了放行
arg2.doFilter(arg0, arg1); } @Override
public void init(FilterConfig arg0) throws ServletException {
// TODO Auto-generated method stub } }

创建第二个过滤器(是否登录):

package com.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession; public class LoginFilter implements Filter {

  //定义一个FilterConfig,用于传递出初始化方法init()中的FilterConfig对象
private FilterConfig config=null;
@Override
public void destroy() {
// TODO Auto-generated method stub } @Override
public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
throws IOException, ServletException {
HttpServletRequest req=(HttpServletRequest)arg0;
HttpServletResponse resp=(HttpServletResponse)arg1;
HttpSession session=req.getSession(); //获取配置文件中配置的初始化参数,在这里是获取不过滤页面名单
String initParam=config.getInitParameter("NotFilter");
String[] notFilterPages=initParam.split(";");

     //不过滤的页面直接调用FilterChain的doFilter()方法跳转到下个过滤器或者目标资源
if(notFilterPages!=null){
for(int i=0;i<notFilterPages.length;++i){
//跳过字段为空和空字符串的情况
if(notFilterPages[i]==null||"".equals(notFilterPages[i]))continue;
//注意这里是URI路径中的是否含有某个初始值,对于servlet来说,是指配置servlet时指定的url-pattern的值,而不是servlet类名
if(req.getRequestURI().indexOf(notFilterPages[i])!=-1){
arg2.doFilter(arg0, arg1);
return;
} } }

     //当登录成功(即session中存在“userName”的值),则跳转到下一个过滤器或者目标资源
//只要未登录成功,所有的页面跳转请求(免除过滤的页面和servlet处理类除外)都将跳转到登录页面
if(session.getAttribute("userName")!=null){
arg2.doFilter(arg0, arg1);
return;
}else{
resp.sendRedirect("login.jsp");
return;
} } @Override
public void init(FilterConfig arg0) throws ServletException {
config=arg0; } }

web.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>javaEE_filter</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list> <!-- 第1个过滤器 -->
<!-- 配置解决乱码过滤器 -->
<filter>
<filter-name>SetEcondingFilter</filter-name>
<filter-class>com.filter.SetEconding</filter-class>
</filter> <!-- 配置解决乱码过滤器映射 -->
<filter-mapping>
<filter-name>SetEcondingFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 第2个过滤器 -->
<!-- 配置登录过滤器 -->
<filter>
<filter-name>LoginFilter</filter-name>
<filter-class>com.filter.LoginFilter</filter-class>
<init-param>
<param-name>NotFilter</param-name>
<param-value>login;doLogin</param-value>
</init-param>
</filter> <!-- 配置登录过滤器映射 -->
<filter-mapping>
<filter-name>LoginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> <!-- 配置处理登录的Servlet -->
<servlet>
<servlet-name>LoginServlet</servlet-name>
<servlet-class>com.servlet.DoLoginServlet</servlet-class>
</servlet> <!-- 配置处理登录Servlet的映射 -->
<servlet-mapping>
<servlet-name>LoginServlet</servlet-name>
<url-pattern>/doLogin</url-pattern>
</servlet-mapping>
</web-app>

乱码问题的解决方案:


乱码问题的解决代码主要有两种即使用request对象的setCharacterEncoding()方法和String的构造器方法。

例:

req.setCharacterEncoding("UTF-8");
userName=new String(userName.getBytes("ISO-8859-1"),"UTF-8");

1)使用过滤器:

在本例中,为了说明过滤器的执行顺序,而定义了两个过滤器并在配置时将处理乱码的过滤器放在了靠前的位置,但是对于处理乱码的过滤器完全可以将代码

req.setCharacterEncoding("UTF-8");

放在判断是否登录的过滤器的doFilter方法体中(最好放在方法体靠前位置,以保证过滤时先进行代码乱码的过滤)。而无需创建第二个过滤器。

2)当然,也可以使用javaBean的方式解决代码乱码问题

Java web--过滤器的更多相关文章

  1. Java Web——过滤器

    <Java Web开发技术应用——过滤器> 过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上.过滤器可附加到一个或多个servlet或JSP页面上,并且可以检查进 ...

  2. java web 过滤器跟拦截器的区别和使用

    注:文章整理自知乎大牛以及百度网友(电脑网络分类达人 吕明),特此感谢! 一.过滤器 1.什么是过滤器? 过滤器是一个程序,它先于与之相关的servlet或JSP页面运行在服务器上.过滤器可附加到一个 ...

  3. java web过滤器实际应用(解决中文乱码 html标签转义功能 敏感字符过滤功能)

    转载地址:http://www.cnblogs.com/xdp-gacl/p/3952405.html 在filter中可以得到代表用户请求和响应的request.response对象,因此在编程中可 ...

  4. java web过滤器防止未登录进入界面

    import java.io.IOException; import javax.servlet.Filter; import javax.servlet.FilterChain; import ja ...

  5. JAVA WEB 过滤器(Filter)中向容器 Spring 注入 bean

    如果直接使用 @Autoware 获取 bean 会直接使该 bean 为 null,这是因为这种配置过滤器的方法无法在过滤器中使用 Spring bean,因为 Filter 比 bean 先加载, ...

  6. java Web 过滤器Filter详解

    简介 Filter也称之为过滤器,Web开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Servlet, 静态图片文件或静态 html 文件等进行拦截,从而实现一些特殊 ...

  7. Java Web 中 过滤器与拦截器的区别

    过滤器,是在java web中,你传入的request,response提前过滤掉一些信息,或者提前设置一些参数,然后再传入servlet或者struts的 action进行业务逻辑,比如过滤掉非法u ...

  8. 初学Java Web(8)——过滤器和监听器

    什么是过滤器 过滤器就是 Servlet 的高级特性之一,就是一个具有拦截/过滤功能的一个东西,在生活中过滤器可以是香烟滤嘴,滤纸,净水器,空气净化器等,在 Web 中仅仅是一个实现了 Filter ...

  9. JAVA WEB 三器之过滤器(Filter)

    过滤器(Filter) 1. 简介 过滤器可以动态地拦截请求和响应,以变换或使用包含在请求或响应中的信息,它是 Servlet 技术中最实用的技术,属于系统级别,主要是利用函数的回调实现.对 Jsp, ...

  10. SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。

    熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...

随机推荐

  1. Win2D 官方文章系列翻译 - 与 Direct2D 互操作

    本文为个人博客备份文章,原文地址: http://validvoid.net/win2d-interop-with-direct2d/ Win2D 作为 Direct2D 的上层实现,支持与其进行双向 ...

  2. 语文,数学,ps

    数学教2课以集合为主. 集合:是指具有某种特定性质的具体的或抽象的对象汇总成的集体,这些对象称为该集合的元素. 特点:确定性给定一个集合,哪些对象是这个集合元素,不允有模棱两可的情况.互用性任何两个元 ...

  3. 选择、循环与函数结构:MATLAB VS Python

    选择.循环与函数结构:MATLAB VS Python 整理基本的程序控制结构,主要是选择 和 循环. 1.MATLAB选择结构 (1)单分支if语句格式: if 条件 语句组 end (2)双分支i ...

  4. Java Programming Guidelines

    This appendix contains suggestions to help guide you in performing low-level program design and in w ...

  5. JSON:json_encode函数不能获取属性原因及解决方案

    json_encode()是个解析json数据的函数,但是这个函数可以有两个参数 形式: json_decode ( string  $json,  ture || false )   第一个参数传字 ...

  6. 智能开关:orange pi one(arm linux)控制继电器

    大家都知道,继电器是用小电流去控制大电流运作的一种“自动开关”,在我们生活.工作中随处可见.现在的“智能家居”概念,有很多功能模块其实就是“智能开关”,远程开关.定时开关.条件触发开关等等. 下面介绍 ...

  7. SQL:获取语句执行时间

    项目中查看数据库查询语句执行时间,脚本如下: --清除缓存 CHECKPOINT; DBCC DROPCLEANBUFFERS; DBCC FREEPROCCACHE; DBCC FREESYSTEM ...

  8. IOS NSOperationQueue(线程 封装操作)

    #import "HMViewController.h" @interface HMViewController () @end @implementation HMViewCon ...

  9. select_related()函数

    Django获取数据实体的时候,返回的对象一个实体或多个实体,也就是QuerySet,它是Django专有的东西,具体的理解,它是类似Python的字典的东西,但它并不实现字典的所有方法.今天讲解的是 ...

  10. POJ-3020 Antenna Placement---二分图匹配&最小路径覆盖&建图

    题目链接: https://vjudge.net/problem/POJ-3020 题目大意: 一个n*m的方阵 一个雷达可覆盖两个*,一个*可与四周的一个*被覆盖,一个*可被多个雷达覆盖问至少需要多 ...