过滤器:
过滤器运行在客户端与web资源之间的,用户请求到达web资源之前,先会执行过滤器。
web资源:放在服务器上各种资源,如:JSP,Servlet,HTML,图片,CSS
-
请求进行修改
-
对请求进行拦截
过滤器的使用场景:
-
全局乱码问题解决。以前POST方法提交给Servlet时候,汉字有乱码问题。(没有请求体,只在地址栏显示)现在可以通过过滤器来集合解决。
-
用户权限验证,对没有登录的用户进行判断。
-
对请求的内容进行过滤,过滤掉一些广告,不健康的信息。(作业)
开发过滤器的步骤
- 创建一个类实现javax.servlet.Filter接口
- 重写接口中所有的方法,其中doFilter() 用来执行过滤任务的
- 需要配置web.xml或使用注解@WebFilter来配置过滤器
开发一个过滤器
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(name = "Demo1HelloServlet", urlPatterns = "/Demo1Hello")
public class Demo1HelloServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Web资源:Servlet执行");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
使用注解的方式
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/*
1. 创建一个类实现javax.servlet.Filter接口
2. 重写接口中所有的方法,其中doFilter() 用来执行过滤任务的
3. 需要配置web.xml或使用注解@WebFilter来配置过滤器
*/
//@WebFilter("/Demo1Hello") //要过滤的地址
@WebFilter(filterName = "demo1", urlPatterns = "/Demo1Hello")
public class Demo1HelloFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
System.out.println("过滤器:请求的时候执行");
//调用这个方法放行,如果没有调用这个方法,请求会被拦截
filterChain.doFilter(request, response);
System.out.println("过滤器:响应的时候执行");
}
@Override
public void destroy() {
}
}
使用配置文件的方式
<?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>demo1</filter-name>
<!-- 过滤器的类全名-->
<filter-class>com.itheima.filter.Demo1HelloFilter</filter-class>
</filter>
<!--配置过滤的地址-->
<filter-mapping>
<!-- 过滤器的名字和上面的名字一样-->
<filter-name>demo1</filter-name>
<!-- 这是过滤的地址,是web资源的地址-->
<url-pattern>/Demo1Hello</url-pattern>
</filter-mapping>
</web-app>
过滤器的执行特点
并没有主动去调用过滤器,如果我们访问的web资源匹配过滤器的过滤地址,则过滤器会自动执行。
过滤器的执行流程
- 用户发送请求,请求的是web资源地址。
- 如果过滤器匹配这个资源的地址,就会先执行过滤器
- 执行过滤器中doFilter()过滤方法,如果要将请求放行,调用chain.doFilter(request, response)方法。将请求和响应对象放行。
- 到达web资源,web资源访问完成以后,响应回来,还会再次经过过滤器。
- 返回到浏览器端
1.服务器启动,加载项目就初始化。
2. 过滤的方法每次请求都执行
3. 过滤器服务器关闭销毁
过滤器匹配多个地址
@WebFilter({"/demo1", "/demo2"})同时过滤demo1和demo2
@WebFilter({"/admin/*", "*.jsp"})过滤admin目录下所有的资源和所有的JSP页面,过滤的地址是所有过滤地址的并集,不是交集
在Servlet3.0中一共有5种拦截方式,常用的有2种。
- FORWARD 转发
- REQUEST 请求
如果没有指定拦截方式,默认是REQUEST。只对直接从浏览器访问的请求起作用。
注解的方式拦截:
dispatcherTypes 指定拦截方式
DispatcherType.FORWARD 转发的时候拦截
DispatcherType.REQUEST 请求的拦截
###过滤器链
在一个项目可以同时存在多个过滤器,每个过滤器实现一个不同的功能,有利于模块化的设计。
多个过滤器过滤同一个地址,多个过滤器就形成了一个过滤器链,如果下一个是过滤器则将请求和响应传递给下一个过滤器,如果下一个不是过滤器,就将请求和响应传递给web资源。而响应回来的时候,会再次经过所有的过滤器。
FilerChain接口就表示过滤器链
监听器
- 作用:用来监听上下文域的创建和销毁, 监听作用域中键和值的改变
- 创建时机:服务器启动,并且加载当前项目的时候
- 销毁时机:服务器关闭的时候
package com.itheima.listener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.sql.Timestamp;
/*
1. 编写1个类实现ServletContextListener接口
2. 重写接口中所有的方法
3. 使用配置<listener>或使用注解@WebListener
*/
@WebListener
public class MyContextListener implements ServletContextListener {
//监听上下文对象创建的事件
@Override
public void contextInitialized(ServletContextEvent se) {
System.out.println(new Timestamp(System.currentTimeMillis()) + ",创建了上下文对象:" + se.getServletContext());
}
//监听上下文对象销毁的事件
@Override
public void contextDestroyed(ServletContextEvent se) {
System.out.println(new Timestamp(System.currentTimeMillis()) + ", 销毁上下文对象");
}
}