过滤器
1、什么是过滤器
Filter:一个实现了特殊接口(Filter)的Java类. 实现对请求资源(jsp,servlet,html,)的过滤的功能.
过滤器是一个运行在服务器的程序, **优先于**请求资源(Servlet或者jsp,html)之前执行. 过滤器是javaweb技术中**最为实用**的技术.
我们可以理解成这是客户端请求经历过的第一个关卡,之后才是servlet或者html等静态资源;
2、filter作用
对目标资源(Servlet,jsp)进行过滤.
应用场景:登录权限检查,解决网站乱码,过滤敏感字符 ...
3、Filter
跟servlet一样,有注解方式,也有xml配置方式,但是更加通用的是使用注解方式。
但是因为filter存在着调用链条方式
3.1、过滤器链
过滤器链作用:当一个filter收到请求的时候,调用chain.doFilter才可以访问下一个匹配的filter,若当前的filter是最后一个filter,调用chain.doFilter才能访问目标资源
过滤器链执行顺序
- 配置文件: 谁先配置
filter-mapping
谁先执行 - 注解方式: 按照Filter的首字母顺序 eg: AFilter BFilter A在B的前面, AFilter先执行
那么首先写一个filter先来测试一下:
filter:
@WebFilter(filterName = "HelloFilter",urlPatterns="/*")
public class HelloFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("请求来了filter...........");
chain.doFilter(request, response);
}
}
servlet:
@WebServlet(name = "HelloServlet", value = "/HelloServlet")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("请求来了request...........");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doGet(request, response);
}
}
直接在浏览器请求:http://localhost:8080/filter_war_exploded/HelloServlet
可以看到控制台输出:
��������filter...........
��������request...........
存在乱码问题,那么首先在过滤器中来进行解决处理。
直接修改filter中的方法
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
//1.强转两个参数
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//2.处理乱码
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//3.放行
chain.doFilter(request, response);
}
4、生命周期方法
public interface Filter {
void init(FilterConfig var1) throws ServletException;
void doFilter(ServletRequest var1, ServletResponse var2, FilterChain var3) throws IOException, ServletException;
void destroy();
}
init方法在容器启动的时候进行加载;(与servlet类似,但是servlet需要修改启动的顺序,而filter是默认的)
doFilter方法,每次在访问路径被拦截的时候,都会在来执行这个方法;
destroy方法:在容器销毁的时候执行代码;
5、映射路径
- 完全路径匹配
- 目录匹配
- 扩展名匹配
- 缺省匹配
假设有一个管理员权限的过滤器,它应该对用户发出的管理员功能的请求进行条件的过滤。但是当用户发出登录、注册等请求的时候,不应该进行过滤。所以我们过滤器,应该有选择的过滤器请求。这就需要学习配置过滤器不同的映射路径,从而让过滤器过滤希望过滤器的请求。
5.1完全路径匹配
以"/"开始
/demo01 ---> 过滤器只能拦截路径/demo01;
5.2目录匹配
以"/"开始 以 *结束 .
/* --->当前项目下的所有的路径都可以拦截; /aa/* ---> 可以拦截 /aa/bb, /aa/bb/cc
5.3扩展名匹配
以"*"开始 例如: *.jsp *.do
*.do--->可以拦截路径的后缀是 do的 ; *.jsp--->拦截所有JSP
5.4缺省匹配
/ 除了jsp以外的资源都匹配
当前Filter里面不支持, Servlet里面可行的. 后面在Servlet里面遇到
6、拦截方式
有了上面学习的映射路径,我们可以控制过滤器过滤指定的内容,但是我们在访问资源的时候,并不是每次都是直接访问,有时是以转发的方式访问的,这就需要我们要让过滤器可以区分不同的访问资源的方式,有不同的拦截方式。 是通过 DispatcherType 来指定的.
-
DispatcherType.REQUEST
默认值,过滤从浏览器发送过来的请求和重定向 不过滤转发
-
DispatcherType.FORWARD
只过滤转发过来的请求
/*只拦截转发*/
/*@WebFilter(urlPatterns = "/demo05",dispatcherTypes={DispatcherType.FORWARD})*/
/*转发,重定向,浏览器的直接请求都会拦截了*/
@WebFilter(urlPatterns = "/demo05",dispatcherTypes={DispatcherType.FORWARD,DispatcherType.REQUEST})
public class FilterDemo05 implements Filter {
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("FilterDemo05() 收到了请求...");
chain.doFilter(req, resp);
}
public void destroy() {
}
public void init(FilterConfig config) throws ServletException {
}
}
7、综合案例
7.1、非法字符过滤
在web文件夹下面建立一个a.txt文件,然后写上对应的违法的字符
@WebFilter(filterName = "IlleaglFilter",urlPatterns = "/*")
public class IlleaglFilter implements Filter {
private static List<String> wordList = new ArrayList<String>();
public void init(FilterConfig config) throws ServletException {
InputStream is = null;
try {
//1.读取文件到集合List<String> list (方式一:根据is获得字符串 存到List 方式二:包装)
//a.根据aa.txt获得InputStream
is = config.getServletContext().getResourceAsStream("aa.txt");
//b包装
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "utf-8"));
String line = null;
while ((line = reader.readLine()) != null) {
wordList.add(line);
}
System.out.println(wordList);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void destroy() {
}
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
// 1.强转两个参数
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
// 2.获得用户发布的言论(请求参数)
String message = request.getParameter("message");
System.out.println("对应的信息是:"+message);
// 3.遍历List集合, 判断用户发布的言论是否包含非法字符
if(message != null){
for (String word : wordList) {
if(message.contains(word)){
// 3.1 包含, 拦截, 响应 "重新发布"
//response.getWriter().print("发布的言论包含非法字符,重新发布");
message = message.replace(word,"***");
response.getWriter().print("您发布的言论是:"+message);
return;
}
}
}
// 3.2 不包含, 放行
chain.doFilter(request,response);
}
}
然后上面的IlleaglFilter的fileName=IlleaglFilter,而HelloFilter的HelloFilter,根据字母H在I之前,所以H先执行,所以乱码问题已经处理过了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?