1.Filter Tomcat提供的一个组件
2.Filter是一个特殊的Servlet
3.基本使用
创建一个类 继承HttpFilter(Tomcat9之后) 实现Filter接口(Tomcat9之前)
重写方法doFilter方法
三个参数HttpServletRequest HttpServletResponse FilterChain
配置xml文件
4.管理机制
继承或实现的关系
filter对象是单例 生命周期托管的方式 立即加载的方式
发送请求 从浏览器出发 会经过filter
从服务器内部出发 转发默认是不经过filter(设置) 重定向经过filter
5.过滤器链
好多个filter对象 都处理相同的请求 /*
我们经过filter不是目的 找到真实的资源
经过的filter会在真实资源执行之前做些事情 之后也会做事情
1.先自定义一个class类,继承HttpFilter(在Tomcat9.0之后是继承HttpFilter,在Tomcat9.0之前是实现Filter接口)这里以Tomcat9.0为例
package filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Enumeration;
//小护士
public class FilterOne extends HttpFilter {
public void init(FilterConfig filterConfig) throws ServletException {
Enumeration en = filterConfig.getInitParameterNames();
while(en.hasMoreElements()){
String key = (String)en.nextElement();
String value = filterConfig.getInitParameter(key);
System.out.println(key+"--"+value);
}
}
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("我是filter 找我干嘛呀");
HttpSession session = request.getSession();
String aname = (String)session.getAttribute("aname");
//获取请求路径
String uri = request.getRequestURI();
//先判断大前提 请求的时候 是否包含index login
if(uri.contains("index") || uri.contains("login")){
//这俩个请求是登陆请求,所以直接放行,要不然死循环,session中永远不会有值
//放行 此时还没有真正做登录判断
chain.doFilter(request,response);
}else{
//应该是登录成功之后的某一个功能
if(aname!=null){
chain.doFilter(request,response);
}else{
request.setAttribute("result","登录已超时,请重新登录");
request.getRequestDispatcher("index.jsp").forward(request,response);
}
}
//1.直接给予响应 自己拼接字符串
//response.getWriter().write("<>");
//2.可以(请求)转发
//request.getRequestDispatcher("路径").forward(request,response);
//3.可以(请求)重定向
//response.sendRedirect("路径");
//4.可以放行
//chain.doFilter(request,response);
}
}
2.自定义一个class类,继承HttpServlet
package controller;
import service.AtmService;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
//目标
public class LoginController extends HttpServlet {
private AtmService service = new AtmService();
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
//1.获取请求参数
String aname = request.getParameter("aname");
String apassword = request.getParameter("apassword");
//2.调用业务方法干活儿
String result = service.login(aname,apassword);
//3.给予响应 转发
if(result.equals("登录成功")) {
//将人名存储在session作用域内啦
HttpSession session = request.getSession();
session.setAttribute("aname",aname);
session.setMaxInactiveInterval(8); <!--设置session的有效期-->
request.getRequestDispatcher("welcome.jsp").forward(request, response);
}else {
request.setAttribute("result",result);
request.getRequestDispatcher("index.jsp").forward(request,response);
}
}
}
3.在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_4_0.xsd"
version="4.0">
<!--处理login请求的servlet-->
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>controller.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
<!--处理项目下所有请求的filter-->
<filter>
<filter-name>filterOne</filter-name>
<filter-class>filter.FilterOne</filter-class>
<init-param>
<param-name>key1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>key2</param-name>
<param-value>value2</param-value>
</init-param>
<init-param>
<param-name>key3</param-name>
<param-value>value3</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>filterOne</filter-name>
<url-pattern>/*</url-pattern> <!--/代码项目根目录的意思,/*代表项目根目录下的所有请求-->
<!--<dispatcher>REQUEST</dispatcher>--> <!-- 默认不填写是这个-->
<!--<dispatcher>FORWARD</dispatcher>--> <!-- 如果填写了这个,则只拦截forward请求-->
<!-- 如果俩个请求都想拦截,则两个都需要写,只写一个会默认覆盖其他的-->
<dispatcher>REQUEST</dispatcher>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
</web-app>
请求转发和重定向在过滤器中的过程
当同时存在多个filter时候:
web.xml
<?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_4_0.xsd"
version="4.0">
<filter>
<filter-name>three</filter-name>
<filter-class>filter.FilterThree</filter-class>
</filter>
<filter-mapping>
<filter-name>three</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>one</filter-name>
<filter-class>filter.FilterOne</filter-class>
</filter>
<filter-mapping>
<filter-name>one</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>two</filter-name>
<filter-class>filter.FilterTwo</filter-class>
</filter>
<filter-mapping>
<filter-name>two</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<servlet>
<servlet-name>login</servlet-name>
<servlet-class>controller.LoginController</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>login</servlet-name>
<url-pattern>/login</url-pattern>
</servlet-mapping>
</web-app>
过滤器链
在控制台的输出结果
在控制台的输出结果
FilterOne.java
public class FilterOne extends HttpFilter {
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("我是FilterOne放行之前的事情,我执行啦");
chain.doFilter(request,response);
System.out.println("我是FilterOne放行之后的事情,啦啦啦");
}
}
FilterTwo.java
public class FilterTwo extends HttpFilter {
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("我是FilterTwo放行之前的事情,我执行啦");
chain.doFilter(request,response);
System.out.println("我是FilterTwo放行之后的事情,啦啦啦");
}
}
FilterThree.java
public class FilterThree extends HttpFilter {
protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("我是FilterThree放行之前的事情,我执行啦");
chain.doFilter(request,response);
System.out.println("我是FilterThree放行之后的事情,啦啦啦");
}
}
如果有多个过滤器,则chain.doFilter(request,response)
会调用下一个过滤器,如果没有,则调用目标方法
过滤器链在执行的时候,他的本质是方法的压栈和弹栈,也就是只有dofilter方法中的chain.doFilter(request,response)
执行完之后,才会执行后续的代码。在此期间,过滤器会一个等一个。
网友评论