javaWeb 学习日记(14)------ Filter 学习

Filter(过滤器)简介:

  • Filter的基本功能是对Servlet容器调用Servlet的过程进行拦截,从而在Servlet 进行响应处理的前后实现一些特殊的功能。
  • 在 Servlet API 中定义了三个接口类来开供开发人员编写Filter程序: Filter, FilterChain, FilterConfig
  • Filter程序是-个实现了Filter接口的Java类,与Servlet程序相似,它由Servlet容器进行调用和执行
  • Filter程序需要在web.xml文件中进行注册和设置它所能拦截的资源: Filter 程序可以拦截Jsp, Servlet,静态图片文件和静态html文件

在这里插入图片描述



Filter 基本工作原理

  • 当在 web.xml 中注册了一个 Filter 来对某个 Servlet 程序进行拦截处理时,这个 Filter 就成了 Servlet 容器与该 Servlet 程序的通信线路上的一道关卡,该 Filter 可以对 Servlet 容器发送给 Servlet 程序的请求和 Servlet程序回送给 Servle t容器的相应进行拦截,可以决定是否将请求继续传递给 Servlet 程序,以及对请求和相应信息是否进行修改

  • 在一个web应用程序中可以注册多个Filter 程序,每个 Filter 程序都可以对一个或一组 Servlet 程序进行拦截。

  • 若有多个Filter程序对某个Servlet程序的访问过程进行拦截,当针对该Servlet 的访问请求到达时,web 容器将把这多个 Filter 程序组合成一个Filter链(过滤器链)。Filter 链中各个Filter的拦截顺序与它们在应用程序的web.xml中映射的顺序一致


Filter 接口

  • Web 容器创建Filter对象实例后,将立即调用该 Filter 对象的 init 方法。Init 方法在 Filter 生命周期中仅执行一次,web 容器在调用 init 方法时,会传递一个包含 Filter 的配置和运行环境的 FilterConfig 对象 (FilterConfig 的用法和 ServletConfig 类似)。利用 FilterConfig 对 象可以得到ServletContext 对象,以及部署描述符中配置的过滤器的初始化参数。在这个方法中,可以抛出 ServletException 异常,通知容器该过滤器不能正常工作。

  • destroy() :在Web容器卸载Filter对象之前被调用。该方法在Filter的生命周期中仅执行一次。在这个方法中,可以释放过滤器使用的资源

  • 与开发Servlet不同的是,Filter接口并没有相应的实现类可供继承,要开发过滤器,只能直接实现 Filter 接口。



FilterConfig接口

  • javax.servlet. FilterConfig 接口 :该接口类似于 ServletConfig 接口,由容器实现。Servlet 规范将代表 ServletContext 对象和 Filter 的配置参数信息都封装在该对象中。Servlet 容器将其作为参数传入过滤器对象的 init() 方法中。
  • String getFilterName() :得到描述符中指定的过滤器的名字。
  • String getlnitParameter(String name) :返回在部署描述中指定的名字为name的初始化参数的值。如果不存在返回 null.
  • Enumeration getlnitParameterNames() :返回过滤器的所有初始化参数的名字的枚举集合。
  • public ServletContext getServletContext() :返回 Servlet 上下文对象的引用。



Filter 是什么

  1. JavaWEB的一一个重要组件,可以对发送到Servlet的请求进行拦截,并对响应也进行拦截.
  2. Filter是实现了Filter 接口的Java类.
  3. Filter 需要在web.xml文件中进行配置和映射.



创建一个 Filter

  1. 创建一个 Filter 类,实现接口: Filter
    第一个Filter 过滤不正确的用户名
public class FilterLogIn implements Filter {
	//得到一个 filterConfig 
	FilterConfig filterConfig = null;
	@Override
	 public void init(FilterConfig filterConfig) throws ServletException {
  		this.filterConfig = filterConfig;
 	}
 	
@Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
   throws IOException, ServletException {
   	//得到 配置文件中的初始化 用户名
 	 String initUser = filterConfig.getInitParameter("userName");
 	 //得到请求参数中的用户名
  	String userName = request.getParameter("userName");
  	
  	//判断是否相等
  	if (!initUser.equals(userName)) {
  		request.setAttribute("message", "用户名不正确");
  		//用户名不相等返回登陆界面
   		request.getRequestDispatcher("/login.jsp").forward(request, response);
   		return ;
  	}
  	//用户名正确 放行
  	chain.doFilter(request, response);
 }
	

第二个 Filter 过滤不正确的密码(原理同上)

public class FilterLogInPass implements Filter {
 FilterConfig filterConfig = null;
 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  	this.filterConfig = filterConfig;
 }
 
 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
   throws IOException, ServletException {

	String initPassword = filterConfig.getInitParameter("password");
   	String password = request.getParameter("password");
 
   	if (!initPassword.equals(password)) {
    		request.setAttribute("message", "密码不正确");
    		request.getRequestDispatcher("/login.jsp").forward(request, response);
    	return ;
   	}
   	chain.doFilter(request, response);
    }
    
 @Override
 public void destroy() {
 }
}
  1. 注册 Filter(web.xml)
<!-- 配置的登陆的 filter -->
 <!-- 检查账号 -->
 <filter>
  	<filter-name>logFilter</filter-name>
  	<filter-class>com.athome.filterLogIn.FilterLogIn</filter-class>
  	<init-param>
   		<param-name>userName</param-name>
   		<param-value>Tom</param-value>
  	</init-param>
 </filter>
 
  <filter-mapping>
  	<filter-name>logFilter</filter-name>
  	<url-pattern>/success.jsp</url-pattern>
 </filter-mapping>
 
<!-- 检查密码 -->
 <filter>
  	<filter-name>logFilterPass</filter-name>
  	<filter-class>com.athome.filterLogIn.FilterLogInPass</filter-class>
   	<init-param>
   		<param-name>password</param-name>
   		<param-value>root</param-value>
  	</init-param>
 </filter>
 
 <filter-mapping>
 	<filter-name>logFilterPass</filter-name>
 	<url-pattern>/success.jsp</url-pattern>
</filter-mapping>
  1. jsp 文件
    login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<!-- 回显 -->
 	<font color="red">${requestScope.message }</font>
 	<br><br>
 	
 	<form action="success.jsp" method="post">
  		UserName:<input tyep="text" name="userName" value="${param.userName }">
  		Password:<input type="password" name="password">
  		<input type="submit" value="Submit">
 	</form>
</body>
</html>

success.jsp中

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
 	<h4>Hello:${param.userName }</h4>
</body>
</html>



自实现 HttpFilter 类

目的:简洁
public abstract class HttpFilter implements Filter{

/**
  * 用于保存 FilterConfig 对象
  */
 FilterConfig filterConfig;

/**
  * 不建议子类直接覆盖,若直接覆盖,可能会导致 filterConfig 成员变量初始化失败
  */
 @Override
 public void init(FilterConfig filterConfig) throws ServletException {
  	this.filterConfig = filterConfig;
  	init();
 }
 
/**
  * 供子类继承的初始化方法,可以通过 getFilterConfig() 获取 FilterConfig 对象 
  */
 protected void init() {}
 
 /**
  * 直接返回 init(FilterConfig) 的 filterConfig 对象
  * @return
  */
 public FilterConfig getFilterConfig() {
  return filterConfig;
 }

/**
  * 原生的 doFilter 方法,在方法内部把ServletRequest 和 ServletResponse
  * 转化成立HttpServletRequest 和 HttpServletResponse,并调用了 
  * doFilter(HttpServletRequest request,HttpServletResponse response,FilterChain chain)
  * 不建议直接继承该方法
  */
 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
   throws IOException, ServletException {

	HttpServletRequest request2 = (HttpServletRequest) request;
  	HttpServletResponse response2 = (HttpServletResponse) response;

doFilter(request2,response2,chain);

}

/**
  * 抽象方法,为Http 请求定制,必须实现的方法
  * @param request
  * @param response
  * @param chain
  * @throws IOException
  * @throws ServletException
  */
 abstract public void doFilter(HttpServletRequest request,HttpServletResponse response,
   FilterChain chain)throws IOException, ServletException ;

/*
  * 空的destroy() 方法
  */
 @Override
 public void destroy() { }
}



练习1

在这里插入图片描述
fiilter 中:

/**
 * Servlet Filter implementation class CacheFilter
 */
@WebFilter("/cache/*")
public class CacheFilter extends HttpFilter {
 @Override
 public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
   throws IOException, ServletException {
   
  //去除页面缓存
  response.setDateHeader("Expires", -1);
  response.setHeader("Cache-Control", "no-cache");
  response.setHeader("Pragma", "no-cache");
  
  //放行
  chain.doFilter(request, response);
 }
}

jsp中:
A.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
 	<a href="B.jsp">Goto PageB</a>
 	<br><br>
 	
 	<img alt="" src="timg.jpg">
</body>
</html>

B.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<a href="A.jsp">GoTo PageA</a>
</body>
</html>



练习2

在这里插入图片描述
解决方案一: 在每个 调用前加上 request.setCharacterEncoding(“utf-8”);

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
 <%
  	//第一种方式
  	request.setCharacterEncoding("utf-8"); 
 %>
</body>
</html>

第二种方式:使用过滤器
filter 中

@WebFilter("/encode/*")
public class EncodingFilter extends HttpFilter {
 private String encode;
 @Override
 protected void init() {
 
  //得到编码值
  encode = getFilterConfig().getServletContext().getInitParameter("encoding");
  System.out.println(encode);
 }
 
 @Override
 public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
   throws IOException, ServletException {
   
  //设置编码方式
  request.setCharacterEncoding(encode);
  
  //放行
  chain.doFilter(request, response);
 }
}

在 web.xml 中 设置web 应用的初始化参数

<context-param>
 	<param-name>encoding</param-name>
 	<param-value>utf-8</param-value>
</context-param>

jsp 中:
logIn.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
 	<form action="secc.jsp" method="post">
  		UserName:<input type="text" name="username">
  		<input type="submit" value="Submit">
 	</form>
</body>
</html>

succ.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	Hello: ${param.username }
</body>
</html>



补充 dispatcher 元素

dispatcher 元素 : 值定过滤器所拦截的资源被servlet 容器调用的方式 可以是REQUEST, INCLUDE, FORWARD和ERROR之-一,默认REQUEST.
  1. REQUEST: 当用户直接访问页面时,Web容器将会调用过滤器。如果目标资源是通过 RequestDispatcher的include( )forward( ) 方法访问,或通过GET或POST请求直接访问。

  2. FORWARD: 如果目标资源是通过 RequestDispatcher 的 forward( ) 方法访问时,那么该过滤器将被调用,或**< jsp:forward page="/…" />** 或通过 page 指令的 errorPage 转发页面. <%@ page errorPage=“test.jsp” %>

  3. INCLUDE: 如果目标资源是通过 RequestDispatcher 的 include( ) 方法访问时或 <jsp:include file="/…" />,那么该过滤器将被调用。除此之外,该过滤器不会被调用。

  4. ERROR :如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
    在web.xml文件中通过error-page节点进行声明:

<error-page>
	<exception-type>java.lang.ArithmeticException</exception-type>
	<location> /test.jsp </location>
</error-page>

<filter-mapping>
	< filter-name> secondFilter </filter-name>
	<url-pattern> /test.jsp </url-pattern>
	<dispatcher> REQUEST </dispatcher>
	<dispatcher> FORWARD </dispatcher>
	<dispatcher>INCLUDE </dispatcher>
	<dispatcher> ERROR </dispatcher>
</filter-mapping>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值