Java之过滤器

一.基本定义:
过滤器实际上就是对web资源进行拦截,做一些处理后再交给下一个过滤器或servlet处理
通常都是用来拦截request进行处理的,也可以对返回的response进行拦截处理
在这里插入图片描述
二.新建一个Filter:
可以直接new一个Filter类.输入过滤器名称,跟创建Servlet一样,这里我们直接使用**@WebFilter**注解,不再去web,xml中进行配置了。创建完成后默认代码,可以看到,CharsetFilter实现了Filter接口,实现了3个方法。3个方法的作用已经在注释中写清楚了。
在这里插入图片描述

package com.fym.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
@WebFilter(filterName = "CharSetFilter")
public class CharSetFilter implements Filter {
    // 销毁时调用
    public void destroy() {
    }

    //过滤方法(真正做事的方法) 主要是对request和response进行一些处理,然后交给下一个过滤器或Servlet处理
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //doFilter()之前是,对请求的过滤
        chain.doFilter(req, resp);//放行操作,交给下一个过滤器或者是servlet处理
        //doFilter()之后是,对响应的过滤
    }

    //初始化方法  接收一个FilterConfig类型的参数 该参数是对Filter的一些配置
    public void init(FilterConfig config) throws ServletException {
    }
}

三.Filter的相关配置(@webFilter):
可配置的属性和常用的配置项:
在这里插入图片描述
①urlPatterns
配置要拦截的资源
以指定资源匹配。例如"/index.jsp"
以目录匹配。例如"/servlet/"
以后缀名匹配,例如"
.jsp"
通配符,拦截所有web资源。"/*"

②initParams
配置初始化参数,跟Servlet配置一样

③.dispatcherTypes (枚举类型)
配置拦截的类型,可配置多个。默认为DispatcherType.REQUEST**
例如
在这里插入图片描述
下面是一个最简单的字符编码的过滤器

package com.fym.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import java.io.IOException;
@WebFilter(filterName = "CharSetFilter", urlPatterns = "/*",//通配符(*)表示对所有的web资源进行拦截
        initParams = {
                @WebInitParam(name = "charset", value = "utf-8")//这里可以放一些初始化的参数,例如设置编码
        })
public class CharSetFilter implements Filter {
    private String filterName;
    private String charset;

    // 销毁时调用
    public void destroy() {
        System.out.println(filterName + "销毁");
    }

    //过滤方法(真正做事的方法) 主要是对request和response进行一些处理,然后交给下一个过滤器或Servlet处理
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        System.out.println(filterName + "doFilter()");
        //doFilter()之前是,对请求的过滤
        req.setCharacterEncoding(charset);
        chain.doFilter(req, resp);//放行操作,交给下一个过滤器或者是servlet处理
        //doFilter()之后是,对响应的过滤
        resp.setCharacterEncoding(charset);
    }

    //初始化方法  接收一个FilterConfig类型的参数 该参数是对Filter的一些配置
    public void init(FilterConfig config) throws ServletException {
        filterName = config.getFilterName();
        charset = config.getInitParameter("charset");
        System.out.println("过滤器名称:" + filterName);
        System.out.println("字符集编码:" + charset);
    }
}

启动服务器是,执行init()方法
在这里插入图片描述
需要注意的是
过滤器是在服务器启动时就会创建的,只会创建一个实例,常驻内存,也就是说服务器一启动就会执行Filter的init(FilterConfig config)方法.
当Filter被移除或服务器正常关闭时,会执行destroy方法
在这里插入图片描述

四.多个Filter的执行顺序:
在我们的请求到达Servle之间是可以经过多个Filter的,一般来说,建议Filter之间不要有关联,各自处理各自的逻辑即可。这样,我们也无需关心执行顺序问题。
如果一定要确保执行顺序,就要对配置进行修改了,执行顺序如下

①在web.xml中,filter执行顺序跟的顺序有关,先声明的先执行
②使用注解配置的话,filter的执行顺序跟
名称的字母顺序有关,例如AFilter会比BFilter先执行
③如果既有在web.xml中声明的Filter,也有通过注解配置的Filter,那么会优先执行web.xml中配置的Filter

五.设计一个登录校验的过滤器:
①注册过滤器,并设置不需要过滤的资源

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">
   <filter>
      <filter-name>CheckLoginFilter</filter-name>
      <filter-class>com.fym.filter.CheckLoginFilter</filter-class>
      <!-- 设置不需要过滤的资源 -->
      <init-param>
         <param-name>UnCheckURI</param-name>
         <param-value>/login,/login.jsp</param-value>
      </init-param>
   </filter>
   <filter-mapping>
      <filter-name>CheckLoginFilter</filter-name>
      <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

②.servlet,做一个简单的页面跳转,并把登录信息保存到session中

package com.fym.filter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class CheckLoginServlet extends HttpServlet{
	private static final long serialVersionUID = 1L;
	protected void service(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		//获取请求参数
		String username = req.getParameter("username");
		String password = req.getParameter("password");
		//这里是直接写死的,实际应用中应该是与数据库中的数据作比较
		if("admin".equals(username)&&"123".equals(password)){
			//将用户信息添加到session中
			req.getSession().setAttribute("USER_IN_SESSION", username);
		}
		//跳转到welcome.jsp页面中
		req.getRequestDispatcher("/welcome.jsp").forward(req, resp);
	}
}

③过滤器代码,判断是否登录

package com.fym.filter;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;

public class CheckLoginFilter implements Filter{
	//定义一个list,用来存放那些不需要过滤的资源
	private List<String> list ;
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		//得到初始化参数,并存放到list集合中
		String unCheckURI = arg0.getInitParameter("UnCheckURI");
		list =  Arrays.asList(unCheckURI.split(","));
	}

	@Override
	public void doFilter(ServletRequest requset, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		//servletRequest里没有获取请求资源的方法(该方法存在于它的子类中,所以需要进行强转)
		HttpServletRequest req = (HttpServletRequest) requset;
		HttpServletResponse resp = (HttpServletResponse) response;
		// 获取当前客户的发出请求的资源
		String requestURI = req.getRequestURI();
		//判断是否有和不需要过滤的资源相等的资源(取反,就是需要进行检查登录的资源)
		if (!list.contains(requestURI)) {
			// 登录检查过滤器(先获取session对象,再获取session中的数据)
			Object obj = req.getSession().getAttribute("USER_IN_SESSION");
			if (obj == null) {
				resp.sendRedirect("/login.jsp");
				return;
			}
		}
		// 放行(这一步是是必须要做的,但是往往会忽略这个,需要牢记)
		chain.doFilter(req, resp);
	}
	@Override
	public void destroy() {
	}
}

④.效果:访问/login.jsp和/login资源时,过滤器不做拦截,访问其他资源时,先判断是否登录,登录即可访问,没有登录,即跳转到登录页面.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值