过滤器

本文介绍了Servlet过滤器的基本概念、特点、作用和工作原理。过滤器作为服务器与客户端请求和响应的中间层,用于拦截和修改请求或响应。文中详细讲解了过滤器的创建过程,包括实现Filter接口和配置web.xml,以及多个过滤器的使用顺序。同时,讨论了过滤器的生命周期,包括初始化、过滤操作和销毁阶段。最后,通过代码示例展示了如何使用过滤器控制用户必须登录才能访问用户信息。

1.基本概念

过滤器(Filter)是服务器与客户端请求与响应的中间层组件,在实际项目开发中过滤器主要用于对浏览器的请求进行过滤处理,将过滤后的的请求再转给下一个资源。与其他web应用程序组件不同的是,过滤器采用了“”的方式进行处理。当需要限制用户访问某些资源或者在处理请求时提前处理某些资源的时候,就可以使用过滤器完成。

2.特点
  • Servlet过滤器可能检查和修改ServletRequest和ServletResponse对象
  • 可以指定Servlet过滤器和特定的URL关联,只有当客户请求访问此URL时,才会触发该过滤器工作
  • 多个Servlet过滤器可以被串联起来,形成管道效应,协同修改请求和响应对象
  • 所有支持Java Servlet规范2.3的Servlet容器,都支持Servlet过滤器
3.作用

(1)在HttpServletRequest 到达Servlet 之前,拦截客户的HttpServletRequest ;根据需要检查HttpServletRequest ,也可以修改HttpServletRequest 头和数据。

(2) 在HttpServletResponse 到达客户端之前,拦截HttpServletResponse ;根据需要检查HttpServletResponse ,可以修改HttpServletResponse 头和数据。

4.工作原理

过滤器是一个可插入的自由组件,也就是说客户端和服务器之间可以插入过滤器的个数是可选的,当插入多个过滤器时,就形成过滤链。客户端浏览器在访问web服务器的某个具体资源的时候,请求经过过滤器1,过滤器1将code1代码块进行相关处理之后,再将请求传递给过滤链中的下一个过滤器2,(过滤器的执行顺序以配置文件中配置的顺序为准)过滤器2处理完之后,request就传递的Servlet完成相应的逻辑。这个请求在通过过滤链并被服务器处理之后,一个响应将以相反的顺序通过该链发送回去。这样,请求和响应都得到了处理。

在这里插入图片描述

5.过滤器的创建过程
  • 实现javax.servlet.Filter接口
  • 实现init方法,读取过滤器的初始化参数
  • 实现doFilter方法,完成对请求或响应的过滤
  • 调用FilterChain接口对象的doFilter方法,向后续的过滤器传递请求或响应

过滤器的默认代码如下:

package com.dlj.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.annotation.WebFilter;

/**
 * Servlet Filter implementation class DemoFilter
 */
@WebFilter("/DemoFilter")
public class DemoFilter implements Filter {

    /**
     * Default constructor. 
     */
    public DemoFilter() {//构造方法
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {//过滤器销毁
		// TODO Auto-generated method stub
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {//执行过滤操作
		// TODO Auto-generated method stub
		// place your code here

		// pass the request along the filter chain
		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {//过滤器初始化
		// TODO Auto-generated method stub
	}

}

过滤器的配置:(两种方式二选一即可)
(1) 直接通过注解的方式

@WebFilter(filterName="DemoFilter")//使用filterName属性声明过滤器的名称(可选)

@WebFilter(filterName="DemoFilter",urlPatterns="/*")
@WebFilter(filterName="DemoFilter",value="/*")//使用urlPatterns或value属性指定要过滤 的URL模式(必选)

(2)通过web.xml文件配置(WEB-INF—>>web.xml)

<filter>
    <filter-name>DemoFilter</filter-name><!--用于为过滤器指定一个名字,该元素的内容不能为空-->
    <filter-class>com.dlj.filter.DemoFilter</filter-class><!--用于指定当前过滤器的路径,包名+类名-->
    <init-param><!--用于为过滤器指定初始化参数-->
        <param-name>charset</param-name><!--指定参数的名字-->
        <param-value>utf-8</param-value><!--指定参数的值-->
    </init-param>
</filter>
<filter-mapping><!--用于设置一个 Filter 所负责拦截的资源,一个Filter拦截的资源可通过两种方式来指定:Servlet 名称和资源访问的请求路径-->
    <filter-name>DemoFilter</filter-name><!--设置filter的注册名称,该值必须是在<filter>元素中声明过的过滤器的名字-->
    <url-pattern>/*</url-pattern><!--设置 filter 所拦截的请求路径-->
</filter-mapping>
6.多个过滤器的使用顺序

web.xml 中的 filter-mapping 元素的顺序决定了 Web 容器应用过滤器到 Servlet 的顺序。若要反转过滤器的顺序,您只需要在 web.xml 文件中反转 filter-mapping 元素即可。

<filter-mapping>
   <filter-name>过滤器1</filter-name>
   <url-pattern>过滤器1的拦截路径</url-pattern>
</filter-mapping>

<filter-mapping>
   <filter-name>过滤器2</filter-name>
   <url-pattern>过滤器2的拦截路径</url-pattern>
</filter-mapping>
7.过滤器的生命周期

初始化: void init(FilterConfig fConfig) 这个方法在服务器启动时被创建,在过滤器创建后立马执行,并且只会调用一次,通过 FilterConfig来读取web.xml文件中Servlet过滤器的初始化参数。

过滤:void doFilter(ServletRequest request, ServletResponse response, FilterChain chain),完成实际的过滤操作的方法,当客户请求访问与过滤器关联的目标资源时,先调用该方法。FilterChain参数用来访问后续的过滤器doFilter()方法。

销毁:void destroy()在服务器关闭的时候执行,释放过滤器占用的资源,只会执行一次。

8.代码举例——控制用户必须登录才能访问所有用户信息
package com.dlj.filter;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;

/**
 * Servlet Filter implementation class CheckLoginFilter
 */
@WebFilter(value = "/*", filterName = "aa")
public class CheckLoginFilter implements Filter {

	/**
	 * Default constructor.
	 */
	public CheckLoginFilter() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * @see Filter#destroy()
	 */
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println("CheckLoginFilter.destroy......");
	}

	/**
	 * @see Filter#doFilter(ServletRequest, ServletResponse, FilterChain)
	 */
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		// place your code here
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		HttpServletResponse httpServletResponse = (HttpServletResponse) response;
		String uri = httpServletRequest.getRequestURI();//获取请求的URI
		System.out.println("CheckLoginFilter...." + uri);
		
		//无需参与过滤的内容
		if (StringUtils.equals(uri, "/blog/signin.jsp")) {
			chain.doFilter(request, response);
			return;
		}

		if (StringUtils.equals(uri, "/blog/SigninServlet")) {
			chain.doFilter(request, response);
			return;
		}

		if (StringUtils.contains(uri, "/static/")) {
			chain.doFilter(request, response);
			return;
		}
		if (StringUtils.equals(uri, "/blog/signup.jsp")) {
			chain.doFilter(request, response);
			return;
		}
		if (StringUtils.equals(uri, "/blog/SignupServlet")) {
			chain.doFilter(request, response);
			return;
		}
		//判断用户是否登录
		String username = (String) httpServletRequest.getSession().getAttribute("username");
		if (StringUtils.isEmpty(username)) {
			httpServletResponse.sendRedirect("/blog/signin.jsp");
			return;
		}
		// pass the request along the filter chain
		//输出登录用户的用户名 及当前访问页面的URI
		System.out.println("用户已登录,用户名:" + username + ",URI=" + uri);

		chain.doFilter(request, response);
	}

	/**
	 * @see Filter#init(FilterConfig)
	 */
	public void init(FilterConfig fConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("CheckLoginFilter.init......");
	}

}

http://localhost:8080/blog/showUsers访问成功,控制台显示:
在这里插入图片描述
点击“退出”之后,再次访问,仍然会跳转到登录界面

退出操作:

package com.dlj.servlet;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class QuiteServlet
 */
@WebServlet("/quit")
public class QuitServlet extends HttpServlet {
	private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public QuitServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

	/**
	 * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		request.getSession().invalidate();//将请求中的session设置为失效
		response.sendRedirect("/blog/signin.jsp");
//		response.getWriter().append("Served at: ").append(request.getContextPath());
	}

	/**
	 * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
	 */
	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		// TODO Auto-generated method stub
		doGet(request, response);
	}

}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值