Filter过滤器
Filter的基本功能是对servlet容器调用servlet的过程进行拦截,从而在servlet进行响应处理的前后实现一些特殊的功能。
在servletAPI中定义了三个接口类来供开发人员编写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程序回送给servlet容器的相应内容进行拦截,可以决定是否将请求继续传递给servlet程序,以及对请求和相应信息是否进行修改。
在一个web应用程序中可以注册多个filter程序,每个filter程序都可以对一个或一组servlet程序进行拦截。
若有多个Filter程序对某个servlet程序的访问过程进行拦截,当针对该servlet的访问请求到达时,web容器将把这多个Filter程序组合成Filter链(过滤器链)。Filter链中各个Filter的拦截顺序与它们在应用程序 web.xml中映射的顺序一致。
简单Filter实例:
新建两个页面,实现跳转:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<a href="two.jsp">to two.jsp</a>
</body>
</html>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h2>TWO</h2>
</body>
</html>
实现filter接口:
package com.sa.filter;
import javax.servlet.*;
import java.io.IOException;
public class HelloFilter implements Filter{
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("doFilter");
}
@Override
public void destroy() {
System.out.println("destroy");
}
}
在web.xml中配置filter:
<filter>
<filter-name>helloFilter</filter-name>
<filter-class>com.sa.filter.HelloFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>helloFilter</filter-name>
<url-pattern>/pages/filter/two.jsp</url-pattern>
</filter-mapping>
测试:
Filter相关API:
Filter接口:
public void init(FilterConfig filterConfig) throws ServletException :类似于servlet的init方法,在创建filter对象后,立即执行,且只执行一次。filter对象在servlet容器加载当前web应用时被创建。该方法用于对当前的filter进行初始化操作,Filter实例是单例的。FilterConfig类似于ServletConfig,可以在web.xml文件中,配置当前filter的初始化参数。
<filter>
<filter-name>helloFilter</filter-name>
<filter-class>com.sa.filter.HelloFilter</filter-class>
<init-param> <param-name>name</param-name> <param-value>sasa</param-value> </init-param>
</filter>
<filter-mapping>
<filter-name>helloFilter</filter-name>
<url-pattern>/pages/filter/two.jsp</url-pattern>
</filter-mapping>
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException :真正的filter逻辑代码需要编写在该方法中。每次拦截都会调用该方法。
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("doFilter");
//放行 filterChain.doFilter(servletRequest,servletResponse);
}
FilterChain:Filter链,多个Filter构成一个Filter链。把请求传给Filter链中的下一个Filter,若当前Filter是Filter链的最后一个,将把请求给到目标Servlet或JSP。多个filter拦截的顺序和
public void destroy():销毁释放当前filter所占用的资源,在filter销毁之前被调用,且只被调用一次。
实现登录拦截:
login.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登录</title>
</head>
<body>
<h2>${msg}</h2>
<form action="<%=request.getContextPath()%>/pages/filter/hello.jsp" method="post">
name:<input type="text" name="name">
pwd:<input type="text" name="pwd">
<input type="submit" value="提交">
</form>
</body>
</html>
hello.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>hello:{param.name}></h1>
</body>
</html>
NameFilter:
package com.sa.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class NameFilter implements Filter{
private FilterConfig filterConfig;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig=filterConfig;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String name=request.getParameter("name");
String name1=filterConfig.getInitParameter("name");
if (!name.equals(name1)) {
request.setAttribute("msg", "名字错辣");
request.getRequestDispatcher("/pages/filter/login.jsp").forward(request,response);
return;
} else {
filterChain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
}
PwdFilter:
package com.sa.filter;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class PwdFilter implements Filter{
private FilterConfig filterConfig;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
this.filterConfig=filterConfig;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
String pwd=request.getParameter("pwd");
String pwd1=filterConfig.getServletContext().getInitParameter("pwd");
if (!pwd.equals(pwd1)) {
request.setAttribute("msg", "密码错辣");
request.getRequestDispatcher("/pages/filter/login.jsp").forward(request,response);
return;
} else {
filterChain.doFilter(request, response);
}
}
@Override
public void destroy() {
}
}
配置web.xml:
<filter>
<filter-name>nameFilter</filter-name>
<filter-class>com.sa.filter.NameFilter</filter-class>
<init-param>
<param-name>name</param-name>
<param-value>sasa</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>nameFilter</filter-name>
<url-pattern>/pages/filter/hello.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>pwdFilter</filter-name>
<filter-class>com.sa.filter.PwdFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>pwdFilter</filter-name>
<url-pattern>/pages/filter/hello.jsp</url-pattern>
</filter-mapping>
<context-param>
<param-name>pwd</param-name>
<param-value>123</param-value>
</context-param>
测试:
Dispatcher元素:指定过滤器所拦截的资源被servlet容器调用的方式,可以是request,include,forword,error之一,默认为request,可以设置多个
①:request:当用户直接访问页面时,web容器将会调用过滤器,如果目标资源是通过requestDispatcher的include()或forWord()方法访问则不会触发过滤器。
通过get或post请求直接访问。
②:forword:如果目标资源是通过requestDispatcher的forword()方法访问时,那么该过滤器将会被调用,除此之外,该过滤器不会被调用。
或
③:include:如果目标资源是通过requestDispatcher的include()方法访问时,那么该过滤器将被调用。除此之外,该过滤器不会被调用。
或
④:error:如果目标资源是通过声明式异常处理机制调用时,那么该过滤器将被调用。除此之外,过滤器不会被调用。
在web.xml文件中通过error-page节点声明
测试:
现在想通过两种方式访问two.jsp:一种是通过request请求,一种是通过forword请求。
one.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<script>
function a() {
window.location.href="<%=request.getContextPath()%>/pages/1011/two.jsp";
}
</script>
<head>
<title>one</title>
<button οnclick="a();" >request</button>
</head>
<body>
</body>
</html>
two.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>two</title>
</head>
<body>
<h1>this is two</h1>
</body>
</html>
three.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>three</title>
</head>
<body>
<a href="four.jsp">forword</a>
</body>
</html>
four.jsp:
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>four</title>
</head>
<body>
<jsp:forward page="two.jsp"></jsp:forward>
</body>
</html>
filter1:
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("Filter1");
chain.doFilter(req, resp);
}
filter2:
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("Filter2");
chain.doFilter(req, resp);
}
配置xml:
<filter>
<filter-name>Filter1</filter-name>
<filter-class>com.sa.filter.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/pages/1011/two.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>Filter2</filter-name>
<filter-class>com.sa.filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/pages/1011/two.jsp</url-pattern>
</filter-mapping>
通过request访问two.jsp:
通过forword访问two.jsp:
可以得知filter的默认监视请求方式是request。
修改xml文件:
<filter>
<filter-name>Filter1</filter-name>
<filter-class>com.sa.filter.Filter1</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter1</filter-name>
<url-pattern>/pages/1011/two.jsp</url-pattern>
</filter-mapping>
<filter>
<filter-name>Filter2</filter-name>
<filter-class>com.sa.filter.Filter2</filter-class>
</filter>
<filter-mapping>
<filter-name>Filter2</filter-name>
<url-pattern>/pages/1011/two.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
通过request访问two.jsp:
通过forword访问two.jsp:
还没有评论,来说两句吧...