Filter过滤器(重点)
基本概念
- Filter本意为”过滤“的含义,是JavaWeb的三大组件之一,三大组件为:Servlet、Filter、Listener。
- 过滤器是向 Web 应用程序的请求和响应处理添加功能的 Web 服务组件。
过滤器相当于浏览器与Web资源之间的一道过滤网,在访问资源之前通过一系列的过滤器对请求进行修改、判断以及拦截等,也可以对响应进行修改、判断以及拦截等。
工作方式
使用方式
自定义类实现Filter接口并重写doFilter方法。
public class LoginFilter implements Filter {
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,ServletException {
//TODO 处理逻辑,必须调用下面的方法
chain.doFilter(request,response);
}
}
在web.xml文件中配置过滤器。 ```javascript
LoginFilter com.lagou.LoginFilter
LoginServlet.java
```javascript
package com.lagou.demo01;
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 = "LoginServlet",urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 1.接收前端页面输入的用户名和密码信息并打印
String userName = request.getParameter("userName");
System.out.println("接收到的用户名为:" + userName);
String password = request.getParameter("password");
System.out.println("接收到的密码为:" + password);
// 2.使用固定的用户名和密码信息来进行登录的校验
if ("admin".equalsIgnoreCase(userName)&&"123456".equalsIgnoreCase(password)){
System.out.println("登录成功,欢迎使用!");
// 存储用户信息
request.getSession().setAttribute("userName",userName);
// 重定向 跳转
response.sendRedirect("main.jsp");
}else {
System.out.println("用户名或密码错误,请重新输入!");
//登录失败,转发
request.getRequestDispatcher("login.jsp").forward(request,response);
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
LoginFilter.java
package com.lagou.demo01;
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LoginFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 1.实现对用户访问主页面的过滤操作,也就是只有用户登录后才能访问主页面,否则一律拦截
// 判断session中是否已有用户名信息,若没有则进行拦拦截,否则放行
HttpServletRequest httpServletRequest = (HttpServletRequest)servletRequest;
HttpSession session = httpServletRequest.getSession();
Object userName = session.getAttribute("userName");
// 获取Servlet的请求路径
String servletPath = httpServletRequest.getServletPath();
// 若没有登录,则回到登录页面
if (null == userName && !servletPath.contains("login")){
servletRequest.getRequestDispatcher("login.jsp").forward(servletRequest,servletResponse);
}else {
// 若已经登录,则放行
filterChain.doFilter(servletRequest,servletResponse);
}
}
@Override
public void destroy() {
}
}
Filter接口
基本概念
- javax.servlet.Filter接口主要用于描述过滤器对象,可以对资源的请求和资源的响应操作进行筛选操作。
常用的方法
| 方法声明 | 功能介绍 | | —- | —- | | void init(FilterConfig filterConfig) | 实现过滤器的初始化操作 | | void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | 执行过滤操作的功能 | | void destroy() | 实现过滤器的销毁操作 |
FilterConfig接口
基本概念
javax.servlet.FilterConfig接口主要用于描述过滤器的配置信息。
常用方法
方法声明 | 功能介绍 |
---|---|
String getFilterName() | 获取过滤器的名字 |
String getInitParameter(String name) | 获取指定的初始化参数信息 |
Enumeration getInitParameterNames() | 获取所有的初始化操作名称 |
ServletContext getServletContext() | 获取ServletContext对象 |
LifeFilter.java
package com.lagou.demo02;
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
public class LifeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("初始化操作正在火热进行中...");
System.out.println("获取到的过滤器名称为:" + filterConfig.getFilterName());
String userName = filterConfig.getInitParameter("userName");
System.out.println("获取到指定初始化参数的数值为:" + userName); // admin
Enumeration<String> initParameterNames = filterConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
// userName password
System.out.println("获取到的初始化参数名为:" + initParameterNames.nextElement());
}
ServletContext servletContext = filterConfig.getServletContext();
System.out.println("获取到的上下文对象是:" + servletContext);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("阻拦一切不合理的访问哦!");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("销毁操作执行完毕了!");
}
}
多个过滤器的使用
- 如果有多个过滤器都满足过滤的条件,则容器依据映射的先后顺序来调用各个过滤器。
过滤器优点
- 实现代码的“可插拔性”,即增加或减少某个功能模块,不会影响程序的正常执行。
- 可以将多个相同处理逻辑的模块集中写在过滤器里面,可实现重复利用、也方便代码的维护。
Listener监听器(重点)
基本概念
Servlet规范中定义的一种特殊的组件,用来监听Servlet容器产生的事件并进行相应的处理。
容器产生的事件分类如下:
生命周期相关的事件。
属性状态相关的事件。
存值状态相关的事件。-
基本分类
| 监听器类型 | 功能介绍 | | —- | —- | | javax.servlet.ServletRequestListener | 监听request作用域的创建和销毁 | | javax.servlet.ServletRequestAttributeListener | 监听request作用域的属性状态变化 | | javax.servlet.http.HttpSessionListener | 监听session作用域的创建和销毁 | | javax.servlet.http.HttpSessionAttributeListener | 监听session作用域的属性状态变化 | | javax.servlet.ServletContextListener | 监听application作用域的创建和销毁 | | javax.servlet.ServletContextAttributeListener | 监听application作用域的属性状态变化 | | javax.servlet.http.HttpSessionBindingListener | 监听对象与session的绑定和解除 | | javax.servlet.http.HttpSessionActivationListener | 监听session数值的钝化和活化 |
监听器详解
ServletRequestListener监听器
- 在ServletRequest创建和关闭时都会通知ServletRequestListener监听器。
- 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void requestInitialized(ServletRequestEvent sre) | 实现ServletRequest对象的初始化 | | void requestDestroyed(ServletRequestEvent sre) | 实现ServletRequest对象的销毁 |
ServletRequestAttributeListener监听器
- 向ServletRequest添加、删除或者替换一个属性的时候,将会通知ServletRequestAttributeListener监听器。
- 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void attributeAdded(ServletRequestAttributeEvent srae) | 增加属性时触发 | | void attributeReplaced(ServletRequestAttributeEvent srae) | 修改属性时触发 | | void attributeRemoved(ServletRequestAttributeEvent srae) | 删除属性时触发 |
HttpSessionListener监听器
- 当一个HttpSession刚被创建或者失效(invalidate)的时候,将会通知HttpSessionListener监听器。
- 常用方法如下:
| 方法声明 | 功能介绍 |
| —- | —- |
| void sessionCreated(HttpSessionEvent se) | 当一个HttpSession对象被创建时会调用这个方法 |
| void sessionDestroyed(HttpSessionEvent se) | 当一个HttpSession超时或者调用HttpSession的
invalidate()方法让它销毁时,将会调用这个方法 |
HttpSessionAttributeListener监听器
- HttpSession中添加、删除或者替换一个属性的时候,将会通知HttpSessionAttributeListener监听器。
- 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void attributeAdded(HttpSessionBindingEvent se) | 当往会话中加入一个属性的时候会调用这个方法 | | void attributeRemoved(HttpSessionBindingEvent se) | 当从会话中删除一个属性的时候会调用这个方法 | | void attributeReplaced(HttpSessionBindingEvent se) | 当改变会话中的属性的时候会调用这个方法 |
ServletContextListener监听器
- 在ServletContext创建和关闭时都会通知ServletContextListener监听器。
- 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void contextInitialized(ServletContextEvent sce) | 当ServletContext创建的时候,将会调用这个方法 | | void contextDestroyed(ServletContextEvent sce) | 当ServletContext销毁的时候(例如关闭应用服务器或者重新加载应用),将会调用这个方法 |
ServletContextAttributeListener监听器
- 向ServletContext添加、删除或者替换一个属性的时候,将会通知ServletContextAttributesListener监听器
- 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void attributeAdded(ServletContextAttributeEvent scae) | 往ServletContext中加入一个属性的时候触发 | | void attributeRemoved(ServletContextAttributeEvent scae) | 从ServletContext中删除一个属性的时候触发 | | void attributeReplaced(ServletContextAttributeEvent scae) | 改变ServletContext中属性的时候触发 |
HttpSessionBindingListener监听器
- HttpSession中绑定和解除绑定时,将会通知HttpSessionListener监听器。
- 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void valueBound(HttpSessionBindingEvent event) | 有对象绑定时调用该方法 | | void valueUnbound(HttpSessionBindingEvent event) | 有对象解除绑定时调用该方法 |
HttpSessionActivationListener监听器
- 当有session数值的钝化和活化操作时,将会通知HttpSessionActivationListener监听器。
- 常用方法如下: | 方法声明 | 功能介绍 | | —- | —- | | void sessionWillPassivate(HttpSessionEvent se) | 有钝化操作时调用该方法 | | void sessionDidActivate(HttpSessionEvent se) | 有活化操作时调用该方法 |
活化操作需要进行如下配置
- 配置context.xml文件的方式如下:
<Manager className="org.apache.catalina.session.PersistentManager" saveOnRestart="true">
<!-- 配置文件存放的路径信息,可以自由指定 -->
<Store className="org.apache.catalina.session.FileStore" directory="C:\session"/>
</Manager>xml
实战案例
- 自定义类实现监听器接口并重写相关的方法。
OnlineUser.java
package com.lagou.demo04;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class OnlineUser implements HttpSessionListener, ServletContextListener {
// 声明一个ServletContex类型的引用负责作为全局对象来记录当前在线用户的数量,通过属性记录
private ServletContext servletContext = null;
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
servletContext = servletContextEvent.getServletContext();
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
servletContext = null;
}
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
System.out.println("有新用户上线了...");
Object count = servletContext.getAttribute("count");
// 若当前用户为第一个用户,则将全局对象中的属性值设置为1即可
if (null == count) {
servletContext.setAttribute("count", 1);
}
// 若当前用户不是第一个用户,则将全局对象中原有的数据取出来加1后再设置进去
else {
Integer integer = (Integer)count;
integer++;
servletContext.setAttribute("count", integer);
}
System.out.println("当前在线用户数量为:" + servletContext.getAttribute("count"));
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
System.out.println("有用户已下线...");
}
}
onlineUser.jsp
<%--
Created by IntelliJ IDEA.
User: pingmao
Date: 2021/5/8
Time: 下午5:21
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>实现当前在线的用户数量</title>
</head>
<body>
<h1>当前在线用户人数为:${applicationScope.count}</h1>
</body>
</html>
- 在web.xml中配置监听器