Javaweb过滤器是一种用于在Servlet处理请求之前或之后对请求进行预处理或后处理的组件。过滤器可以用于拦截请求、修改请求参数、过滤响应内容等操作。其主要作用包括:
-
拦截请求:过滤器可以拦截客户端请求,对请求进行验证、过滤或修改,以确保请求符合要求。
-
过滤响应:过滤器可以拦截服务器响应,对响应内容进行处理或过滤,以确保响应符合要求。
-
日志记录:过滤器可以用于记录请求和响应的日志,帮助开发人员进行调试和监控。
-
权限控制:过滤器可以用于进行权限验证,限制用户访问某些资源或操作。
-
数据压缩:过滤器可以用于对响应数据进行压缩,减少网络传输流量。
-
字符编码转换:过滤器可以用于对请求和响应数据进行字符编码转换,确保数据在不同编码之间正确传输。
通过配置不同的过滤器链,开发人员可以灵活地对请求和响应进行处理,实现更加灵活和高效的Web应用程序。
目录
[四. Filter的配置(url-pattern)](#四. Filter的配置(url-pattern))
一.过滤器说明
为什么需要过滤器?
我们如果只通过Session技术实现对登录用户的身份校验,会造成功能重复,代码冗余,使用过滤器可以很好的解决这个问题
二.过滤器介绍
- Filter 过滤器它是 JavaWeb 的三大组件之一(Servlet 程序、Listener 监听器、Filter 过滤器)
2.FIlter是一种JavaEE规范下的接口
3.Filter的主要作用是:拦截请求,过滤响应 常用于 权限检查,日记操作,事务管理
三.图解过滤器的基本原理
应用实例(用户在login.jsp完成登录,通过过滤器manageFiltter决定访问admin.jsp或重新登陆
login.jsp
html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>管理后台登录</title>
</head>
<body>
<h1>管理后台登录</h1>
<%
System.out.println("request=" + request);
%>
<form action="<%=request.getContextPath() %>/loginCheckServlet" method="post">
u:<input type="text" name="username"/> <br/><br/>
p:<input type="password" name="password"/> <br/><br/>
<input type="submit" value="用户登录"/></form>
</body>
</html>
managerFiltter.java
java
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
/**
* 1. filter在web项目启动时, 由tomcat 来创建filter实例, 只会创建一个
* 2. 会调用filter默认的无参构造器, 同时会调用 init方法, 只会调用一次
* 3. 在创建filter实例时,同时会创建一个FilterConfig对象,并通过init方法传入
* 4. 通过FilterConfig对象,程序员可以获取该filter的相关配置信息
* 5. 当一个http请求和该filter的的url-patter匹配时,就会调用doFilter方法
* 6. 在调用doFilter方法时,tomcat会同时创建ServletRequest 和 ServletResponse 和 FilterChain对象
* , 并通过doFilter传入.
* 7. 如果后面的请求目标资源(jsp,servlet..) 会使用到request,和 response,那么会继续传递
*/
public class ManageFilter implements Filter {
private int count = 0;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//当Tomcat 创建 Filter创建,就会调用该方法,进行初始化
//
System.out.println("ManageFilter init被调用...");
}
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
System.out.println("ManageFilter doFilter() 被调用=" + (++count));
//到每次调用该filter时,doFilter就会被调用
//如果这里,没有调用继续请求的方法,则就停止
//如果继续访问目标资源-> 等价于放行
//在调用过滤器前,servletRequest对象=request已经被创建并封装
//所以:我们这里就可以通过servletRequest获取很多信息, 比如访问url , session
//比如访问的参数 ... 就可以做事务管理,数据获取,日志管理等
//获取到session
//可以继续使用 httpServletRequest 方法.
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
System.out.println("输入密码=" + httpServletRequest.getParameter("password"));
HttpSession session = httpServletRequest.getSession();
//获取username session对象, 还可以继续使用
Object username = session.getAttribute("username");
if (username != null) {
//filterChain.doFilter(servletRequest, servletResponse)
//1. 继续访问目标资源url
//2. servletRequest 和 servletResponse 对象会传递给目标资源/文件
//3. 一定要理解filter传递的两个对象,再后面的servlet/jsp 是同一个对象(指的是在一次http请求)
System.out.println("servletRequest=" + servletRequest);
System.out.println("日志信息==");
System.out.println("访问的用户名=" + username.toString());
System.out.println("访问的url=" + httpServletRequest.getRequestURL());
System.out.println("访问的IP=" + httpServletRequest.getRemoteAddr());
filterChain.doFilter(servletRequest, servletResponse);
} else {//说明没有登录过..回到登录页面
servletRequest.getRequestDispatcher("/login.jsp").
forward(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
//当filter被销毁时,会调用该方法
System.out.println("ManageFilter destroy()被调用..");
}
}
admin.jsp
html
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>后台管理</title>
<base href="<%=request.getContextPath() %>/manage/"/>
</head>
<body>
<h1>后台管理</h1>
<%
//验证request对象是和前面的filter是一个对象
System.out.println("request=" + request);
%>
<a href="#">用户列表</a>||<a href="#">添加用户</a>||<a href="#">删除用户</a>
<hr/>
<img src="resourse.jpg" height="300"/>
</body>
</html>
web.xml
XML
<filter>
<filter-name>ManageFilter</filter-name>
<filter-class>filter.ManageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ManageFilter</filter-name>
<url-pattern>/manage/*</url-pattern>
</filter-mapping>
四. Filter的配置(url-pattern)
filter一般写在其它servlet的前面
1. 观察我们发现filter 配置和 servlet 非常相似. filter也是被tomcat管理和维护
2. url-pattern 就是当请求的url 和 匹配的时候,就会调用该filter
1、<url-pattern> : Filter 的拦截路径, 即浏览器在请求什么位置的资源时,过滤器会进行拦截过滤
2.、精确匹配
/a.jsp对应的请求地址 http://ip[域名]:port/工程 路径/a.jsp 会拦截
3、目录匹配
/manage/* 对应的请求地址 http://ip[域名]:port/ 工程路径/manage/xx , 即 web 工程 manage 目录下所有资源会拦截
4、后缀名匹配
*.jsp 后缀名可变,比如 *.action *.do 等等对应 的 请求地址 http://ip[域名]:port/工程路径/xx.jsp , 后缀名为 .jsp 请求会拦截
5、Filter 过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在
五.Filter生命周期
六.FilterConfig
1.接口图
2.Config说明
FilterConfig 是 Filter 过滤器的配置类
Tomcat 每次创建 Filter 的时候,也会创建一个 FilterConfig 对象,这里包含了 Filter 配 置文件的配置信息。
FilterConfig 对象作用是获取 filter 过滤器的配置内容 在web.xml <init-param>标签下
实例说明
web.xml 配置config中的配置参数
XML
<filter>
<filter-name>FilterConfig</filter-name>
<filter-class>com.hspedu.filter.HspFilterConfig</filter-class>
<!--这里就是给该filter配置的参数-有程序员根据业务逻辑来设置-->
<init-param>
<param-name>ip</param-name>
<param-value>127.0</param-value>
</init-param>
<init-param>
<param-name>port</param-name>
<param-value>8888</param-value>
</init-param>
<init-param>
<param-name>email</param-name>
<param-value>leon@sohu.com</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>FilterConfig</filter-name>
<url-pattern>/abc/*</url-pattern>
</filter-mapping>
FilterConfig.java 演示显示config数据/利用存储的ip进行对该网段过滤
java
public class FilterConfig implements Filter {
private String ip; //从配置获取的ip
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("HspFilterConfig init() 被调用..");
//通过filterConfig 获取相关的参数
String filterName = filterConfig.getFilterName();
ip = filterConfig.getInitParameter("ip");
ServletContext servletContext = filterConfig.getServletContext();
//可以获取到该filter所有的配置参数名
Enumeration<String> initParameterNames =
filterConfig.getInitParameterNames();
//遍历枚举
while (initParameterNames.hasMoreElements()) {
System.out.println("名字=" + initParameterNames.nextElement());
}
System.out.println("filterName= " + filterName);
System.out.println("ip= " + ip);
System.out.println("servletContext= " + servletContext);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//通过forbidden ip 来进行控制
//先获取到访问ip
String remoteAddr = servletRequest.getRemoteAddr();
if(remoteAddr.contains(ip)) {
System.out.println("封杀该网段..");
servletRequest.getRequestDispatcher("/login.jsp").
forward(servletRequest,servletResponse);
return; //直接返回
}
//继续访问目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
七.FilterChain过滤器链
在处理某些复杂业务时,一个过滤器不够,可以设计多个过滤器 共同完成过滤任务,形成过滤器链.
注意事项:
-
多个 filter 和目标资源在一次 http 请求,在同一个线程中
-
当一个请求 url 和 filter 的 url-pattern 匹配时, 才会被执行, 如果有多个匹配上,就会顺序执行,形成一个 filter 调用链
-
多个 filter 共同执行时,因为是一次 http 请求, 使用同一个 request 对象
-
多个 filter 执行顺序,和 web.xml 配置顺序保持一致.
-
chain.doFilter(req, resp)方法 将执行下一个过滤器的 doFilter 方法, 如果后面没有过滤器, 则执行目标资源。
-
小结:注意执行过滤器链时, 顺序是(用前面的案例分析) Http请求 -> A 过滤器 dofilter() -> A 过滤器前置代码 -> A 过滤器 chain.doFilter() -> B 过滤器 dofilter() -> B 过滤器前置代 码 -> B过滤器 chain.doFilter() -> 目标文件 -> B过滤器后置代码 -> A过滤器后置代码 -> 返回给浏览器页面/数据