过滤器、监听器、拦截器三者联系
过滤器(Filter)
主要用于对用户的请求进行预处理
通过过滤器Filter技术,可以管理Web服务器的所有资源(例如jsp,html,静态资源文件等),并进行拦截,从而实现一些特殊的功能(例如实现URL级别的权限访问控制,过滤铭感词汇,设置字符集编码格式等)。
功能实现:
- 在HttpServletRequest到达Servlet之前,拦截客户的HttpServletRequest请求(检查或修改其数据)。
- 在HttpServletResponse到达客户端之前,拦截HttpServletResponse请求(检查或修改其数据)。
如何实现:
- 编写Java类实现Filiter接口,并实现doFilter()方法
- 在web.xml中注册编写的Filter类
示例:(对请求统一设置字符编码格式utf-8,解决乱码问题)
1.创建项目--filter,增加web框架支持(add Frameworks Support)
2.创建包--cn.zero.servlet,编写类MyServlet
package cn.zero.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
//Servlet需要继承HttpServlet接口
public class MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.getWriter().write("你好,世界!");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
3.在web.xml中配置servlet
<?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">
<!--配置servlet-->
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>cn.zero.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
</web-app>
4.配置tomcat,启动项目,运行:http://localhost:8080/hello
我们发现页面存在乱码的情况,为了解决这个问题,我们需要在请求中设置字符编码格式来解决这类问题。
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("你好,世界!");
这样便解决了乱码问题!
可是我们存在多个方法,倘若都可能存在乱码问题的话,我们就需要重复增加上述代码,久而久之代码便会更加繁重冗余,那么有没有一种方法可以解决这类问题呢?
有,使用拦截器!!!
5.创建包--cn.zero.filter,编写类MyFilter
package cn.zero.filter;
import javax.servlet.*;
import java.io.IOException;
//实现Filter接口
public class MyFilter implements Filter {
//1.过滤器的初始化工作
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("Filiter初始化完成!");
}
//过滤器执行过滤操作
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
resp.setContentType("text/html;charset=utf-8");
System.out.println("过滤器执行前--before");
chain.doFilter(req, resp); // doFilter过滤操作将请求获取,然后再将请求抛出去
System.out.println("过滤器执行后--after");
}
//3.过滤器销毁
public void destroy() {
System.out.println("Filter销毁!");
}
}
6.修改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">
<!--配置servlet-->
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>cn.zero.servlet.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<!--配置filter-->
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>cn.zero.filter.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
</web-app>
配置filter时,设置url-pattern为:/*,因此所有的请求执行都会进过cn.zero.filter.MyFilter类中的方法!
7.配置tomcat,再次启动项目,运行:http://localhost:8080/hello
这样,我们增加的拦截器便发挥了作用!
监听器(Listener)
用于监听web应用中某些对象、信息的创建、销毁、增加、修改、删除等动作的发生,然后做出相应的响应处理。当范围对象的状态发生变化的时候,服务器自动调用监听器对象中的方法。
常用于统计在线人数和在线用户,系统加载时进行信息的初始化,统计网站的访问量等。
示例:(使用监听器统计网站的在线人数)
实现原理:每当有访问连接到服务器时,服务器就会创建一个session来管理会话,由此我们可通过session的数量多少来统计在线人数。
1.创建项目--listener,增加web框架支持(add Frameworks Support)
2.创建包cn.zero.listener,编写MyListener类
package cn.zero.listener;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
//实现HttpSessionListener接口,通过session会话了解监听器
public class MyListener implements HttpSessionListener {
/**
* 我们使用 访问网页的在线人数 做Demo
* 创建session时,在线人数onLine+1
* 销毁session时,在线人数onLine-1
*/
//session创建时,将执行该方法
//也证明程序创建session时被监听器监听到
public void sessionCreated(HttpSessionEvent se) {
ServletContext sc = se.getSession().getServletContext();
//在线人数onLine
Integer onLine = (Integer) sc.getAttribute("onLine");
if (onLine == null) {
onLine = 1;
} else {
onLine = onLine + 1;
}
sc.setAttribute("onLine", onLine);
}
//session销毁时,将执行该方法
//也证明程序销毁session时被监听器监听到
public void sessionDestroyed(HttpSessionEvent se) {
ServletContext sc = se.getSession().getServletContext();
//在线人数onLine
Integer onLine = (Integer) sc.getAttribute("onLine");
if (onLine == null) {
onLine = 0;
} else {
onLine = onLine - 1;
}
sc.setAttribute("onLine", onLine);
}
}
3.编写index.jsp页面内容
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<title>测试在线人数Demo--listener</title>
</head>
<body>
<p>
当前共有<%=request.getSession().getServletContext().getAttribute("onLine") %>人在线<br>
</p>
</body>
</html>
4.在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">
<listener>
<listener-class>cn.zero.listener.MyListener</listener-class>
</listener>
</web-app>
5.配置tomcat,发布项目,访问路径:http://localhost:8080/ 使用不同浏览器访问,可以发现session数量的增加。
拦截器(Interceptor)
实现对每一个请求处理前后进行相关的业务处理。
基于Java反射机制实现,拦截的对象只能是实现了接口的类,而不能拦截url类似的链接。
Java中的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Action中可重用部分代码的方式。
在Aop中,拦截器用于在某个方法或者字段被访问之前,进行拦截,然后在其前后加入某些操作。
示例:
1.创建项目--interceptor,创建包 cn.zero.interceptor
2.编写接口 InterDao, 编写InterDaoImpl实现接口
package cn.zero.interceptor;
public interface InterDao {
//执行处理业务
void doSomething();
}
package cn.zero.interceptor;
public class InterDaoImpl implements InterDao {
//执行处理业务
public void doSomething() {
System.out.println("处理业务!");
}
}
3.自定义拦截器Interceptor
package cn.zero.interceptor;
//自定义拦截器
public class Interceptor {
//拦截器执行前方法
public void before() {
System.out.println("拦截器执行前--before");
}
////拦截器执行后方法
public void after() {
System.out.println("拦截器执行后--after");
}
}
4.创建拦截器代理对象
package cn.zero.interceptor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//拦截器代理对象
public class InterceptorProxy {
//被代理对象
private Object target;
//实例化一个拦截器对象
Interceptor interceptor = new Interceptor();
//动态生成一个代理对象,并绑定被代理类和代理处理器
public Object getProxyInstance(final Object target) {
this.target = target;
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
interceptor.before();
Object object = method.invoke(target, args);
interceptor.after();
return object;
}
});
}
}
5.编写启动类,测试运行
package cn.zero.interceptor;
public class InterceptorMain {
public static void main(String[] args) {
//创建动态代理工具
InterceptorProxy interceptorProxy = new InterceptorProxy();
//创建业务组件
InterDao interDao = new InterDaoImpl();
//获取代理对象
InterDao proxy = (InterDao) interceptorProxy.getProxyInstance(interDao);
//通过代理对象调用目标对象方法
proxy.doSomething();
}
}
6.控制台查看运行结果
我们看到,我们执行目标方法doSomething()时,通过拦截器,可以在其前后增加我们需要的业务!
来源:CSDN
作者:cnid_linyl
链接:https://blog.csdn.net/Lin_yl/article/details/104911582