欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

javaweb——过滤器

程序员文章站 2022-05-23 10:11:28
...

过滤器

作用

​ 实现对web资源请求的拦截,完成特殊的操作,尤其是对请求的预处理。

应用场景

  • Web资源权限访问控制
  • 字符集编码处理
  • 内容敏感字符词汇过滤
  • 响应信息压缩

工作流程
javaweb——过滤器

过滤器的生命周期

  • 过滤器的创建和销毁由web服务器负责
  1. web应用程序启动时,web服务器创建Filter的实例对象 ,以及对象的初始化。(调用init()方法,这个方法只在tomcat服务器启动的时候调用一次)
  2. 当请求访问与过滤器关联的web资源时(某个URL),过滤器拦截请求,完成指定功能(完成后交给下一个过滤器或者servlet进行处理)。(调用doFilter()方法,web程序运行期间可多次调用)
  3. Filter对象创建后会一直驻留在内存中,在web应用移除或服务器停止时才销毁。(调用destory()方法)

过滤器链

  • 在一个web应用中,多个过滤器组合起来称之为一个过滤器链。(比如说有的请求不止需要被一个过滤器拦截进行处理[先是字符集编码的处理的过滤器,再是判断是否登录的过滤器],这时就需要编写多个过滤器类来分别处理)

  • 过滤器请求预处理的调用顺序取决于过滤器在web.xml文件中的注册顺序,而过滤器响应后处理的调用顺序取决于过滤器注册顺序的逆序。

    (web.xml的顺序决定的是执行doFilter()的顺序 并不决定init()的顺序)

过滤器的实现步骤

编写java类实现Filter接口

package 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;

//要实现javax.servlet.Filter接口,重写下面三个方法
public class CharacterEncodingFilter implements Filter {

	@Override
	public void destroy() {
		//在过滤器销毁的时候做一些清理工作
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		//完成过滤器的功能
        //request是请求预处理
        //reponse是响应后处理
        
        //不要忘记调用这个方法,意思是交给下一个过滤器或者servlet(请求本来要到达的地方)进行后续的操作处理
        chain.doFilter(request,response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
		//在过滤器对象创建的时候做一些初始化操作
        
        //参数中FilterConfig是过滤器配置类,在配置Filter的时候会设置一些初始化参数(设置初始化参数都是在web.xml文件中或者注解中完成),把这些配置封装成配置类对象传入进来
      
        /*在web.xml中
        <filter>
        	.....注册filter
        	<init-param>
        		<param-name>version</param-name>
        		<param-value>2.0</param-value>
        	</init-param>
        </filter>
        */
       
        /*
        	在init()函数中
        	通过 config.getInitParameter("version");能获取version的值
        */
	}
}

在web.xml文件中对filter类进行注册,并设置所拦截的资源

<!-- 注册过滤器,让web服务器识别到这个过滤器要对一些web请求做拦截处理-->
	<filter>
		<filter-name>TestFilter</filter-name>
		<filter-class>com.lxc.TestFilter</filter-class>
		
		<!--设置过滤器配置类的初始化参数  -->
		<init-param>
			<param-name>charset</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	
	<!--拦截映射的配置,指定过滤器对哪些请求做拦截处理  -->
	<!-- /*代表所有的请求都会被这个过滤器拦截  -->
	<filter-mapping>
		<filter-name>TestFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

配置要拦截的资源

  1. 以指定资源匹配。例如"/index.jsp"

  2. 以目录匹配。例如"/servlet/*"

  3. 以后缀名匹配,例如"*.jsp"

  4. 通配符,拦截所有web资源。"/*"

  5. 拦截多个页面

    <filter>  
        <filter-name>authority</filter-name>  
        <filter-class>com.util.AuthorityFilter</filter-class>  
    </filter>  
    <filter-mapping>  
        <filter-name>authority</filter-name>  
        <url-pattern>/pages/genbill/*</url-pattern>  
    </filter-mapping>  
    <filter-mapping>  
        <filter-name>authority</filter-name>  
        <url-pattern>/pages/cmm/*</url-pattern>  
    </filter-mapping>  
    

filter-mapping的子元素dispather

必须写在filter-mapping的最后。dispatcher的前提条件当然是要先满足url-pattern,然后是dispatcher属性。

<filter-mapping>
	<filter-name>testFilter</filter-name>
	<url-pattern>/test2.jsp</url-pattern>
	<dispatcher>REQUEST</dispatcher>
</filter-mapping>

如果不写dispatcher这个子属性,那么默认是REQUEST

dispatcher有四种可能的属性:
1、REQUEST
只要发起的操作是一次HTTP请求,比如请求某个URL、发起了一个GET请求、表单提交方式为POST的POST请求、表单提交方式为GET的GET请求。一次重定向则前后相当于发起了两次请求,这些情况下有几次请求就会走几次指定过滤器。
2、FOWARD
只有当当前页面是通过请求转发转发过来的情形时,才会走指定的过滤器 (但该过滤器必须指定了<dispatcher>FORWARD</dispatcher>
3、INCLUDE
只要是通过<jsp:include page="xxx.jsp" />,嵌入进来的页面,每嵌入的一个页面,都会走一次指定的过滤器。
4、ERROR
假如web.xml里面配置了<error-page></error-page>

<error-page>
 <error-code>400</error-code>
 <location>/filter/error.jsp</location>
</error-page>

<error-page>
 <error-code>404</error-code>
 <location>/filter/error.jsp</location>
</error-page>

不管这个请求是从哪里发过来的(jsp还是过滤器),发送方是什么方式就按什么方式匹配。

也可以把四种可能都写上,四种情况都会拦截

	<filter-mapping>
		<filter-name>testFilter</filter-name>
		<url-pattern>/test2.jsp</url-pattern>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>

使用注解配置Filter

javaweb——过滤器

@WebFilter(filterName = "CharsetFilter",
        urlPatterns = { "/AddServlet","/qiantai/order.jsp","/RemoveServlet", "/UserOrderingServlet" },
        dispatcherTypes = {DispatcherType.ASYNC,DispatcherType.ERROR},/*枚举类型*/
        initParams = {
                @WebInitParam(name = "charset", value = "utf-8"),/*这里可以放一些初始化的参数*/				@WebInitParam(name = "contenttype", value = "text/html;charset=utf-8")
        })

使用注解配置的话,filter的执行顺序(过滤器类doFilter()方法的执行顺序)跟过滤器类的类名的字母顺序有关,例如AFilter.java会比BFilter.java先执行

请求和响应字符集编码处理

package 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;

public class CharacterEncodingFilter implements Filter {

	//接收过滤配置类对象
	private FilterConfig config;

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {

		//不直接设置为UTF-8,而是把编码的信息放在web.xml文件中,以后直接修改web.xml中的初始化参数就行,避免了java代码的重新编译等操作
		// 根据过滤器配置字符集,设置请求字符集编码
		request.setCharacterEncoding(config.getInitParameter("charset"));
		response.setContentType(config.getInitParameter("responsecharset"));
		chain.doFilter(request, response);
	}

	@Override
	public void init(FilterConfig config) throws ServletException {
		this.config = config;
	}
}

web.xml文件

	<!-- 字符集编码过滤器配置 -->
	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>charset</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
        <init-param>
          <param-name>responsecharset</param-name>
          <param-value>text/html;charset=utf-8</param-value>
    	</init-param>
	</filter>

	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

登录验证

使用注解配置过滤器,拦截的时候不能拦截全部页面,不然会出现很多后续的麻烦


@WebFilter(filterName = "LoginFilter", urlPatterns = "*.jsp", dispatcherTypes = {})
public class SessionFilter implements Filter {

	@Override
	public void destroy() {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		HttpServletRequest hrequest = (HttpServletRequest)request;
		HttpServletResponse hresponse = (HttpServletResponse)response;
		
		String loginUser = (String)hrequest.getSession().getAttribute("loginUser");//从session对象中获取登录用户名
		
		if(loginUser==null){//登录用户名不存在,用户未登录,强制重定向至登陆页面
			hresponse.sendRedirect(hrequest.getContextPath()+"/index.jsp?flag=1");
			return;
			
		}else{
			chain.doFilter(request, response);//已登录,转入相应的请求处理
			return;
		}

	}

	@Override
	public void init(FilterConfig arg0) throws ServletException {

	}

}

相关标签: 过滤器 javaweb