javaweb——过滤器

过滤器

作用

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

应用场景

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

工作流程
在这里插入图片描述

过滤器的生命周期

  • 过滤器的创建和销毁由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

在这里插入图片描述

@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 {

	}

}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章