目录
一 Filter 概述
生活中的过滤器
净水器、空气净化器、地铁安检、山大王
web中的过滤器
当用户访问服务器资源时,过滤器将请求拦截下来,完成一些通用的操作
应用场景
如:登录验证、统一编码处理、敏感字符过滤
二 快速入门
需求:编写filter对目标资源servlet进行拦截
public class TargetServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("目标资源被访问到了.....");
resp.setContentType("text/html;charset=utf-8");
resp.getWriter().write("目标资源被访问到了.....");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
<!--TargetServlet-->
<servlet>
<servlet-name>TargetServlet</servlet-name>
<servlet-class>com.lagou.servlet.TargetServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>TargetServlet</servlet-name>
<url-pattern>/targetServlet</url-pattern>
</servlet-mapping>
① 编写java类,实现filter接口
package com.lagou.filter;
import javax.servlet.*;
import java.io.IOException;
public class QuickFilter implements Filter {
/*
初始化方法
*/
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/*
拦截用户请求的方法
servletRequest: 请求对象
servletResponse:响应对象
filterChain:过滤器链(是否放行)
*/
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("QuickFilter拦截了请求....");
// 没有以下语句时, 不放行
// 放行状态
filterChain.doFilter(servletRequest,servletResponse);
// 再进行拦截
System.out.println("QuickFilter拦截了响应....");
}
/*
销毁方法
*/
@Override
public void destroy() {
}
}
② 配置web.xml
<!--QuickFilter-->
<filter>
<filter-name>QuickFilter</filter-name>
<filter-class>com.lagou.filter.QuickFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>QuickFilter</filter-name>
<!-- 该拦截器的拦截路径 /* -->
<url-pattern>/targetServlet</url-pattern>
</filter-mapping>
三 工作原理
四 使用细节
4.1 生命周期
生命周期:指的是一个对象从生(创建)到死(销毁)的一个过程
public class LifecycleFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("LifecycleFilter对象创建了...执行init方法");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("LifecycleFilter对象拦截了请求...执行doFilter方法");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
System.out.println("LifecycleFilter对象销毁了了...执行destroy方法");
}
}
4.2 拦截路径
在开发时,我们可以指定过滤器的拦截路径来定义拦截目标资源的范围
4.3 过滤器链
在一次请求中,若我们请求匹配到了多个filter,通过请求就相当于把这些filter串起来了,形成了过滤器链
public class AFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("AFilter拦截请求");
//放行
filterChain.doFilter(servletRequest,servletResponse);
// 对响应进行增强
System.out.println("AFilter响应增强");
}
@Override
public void destroy() {
}
}
public class BFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("BFilter拦截请求");
//放行
filterChain.doFilter(servletRequest,servletResponse);
// 对响应进行增强
System.out.println("BFilter响应增强");
}
@Override
public void destroy() {
}
}
<!-- B先声明, 因此B先执行 -->
<!--BFilter-->
<filter>
<filter-name>BFilter</filter-name>
<filter-class>com.lagou.filter.BFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>BFilter</filter-name>
<!--该拦截器的拦截路径 /*-->
<url-pattern>/targetServlet</url-pattern>
</filter-mapping>
<!--AFilter-->
<filter>
<filter-name>AFilter</filter-name>
<filter-class>com.lagou.filter.AFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AFilter</filter-name>
<!--该拦截器的拦截路径 /*-->
<url-pattern>/targetServlet</url-pattern>
</filter-mapping>
五 综合案例
5.1 用户评论留言
需求
用户访问某论坛网站,可以写评论的方式对比赛内容进行留言
5.1.1 需求分析
5.1.2 代码实现
① bbs.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h3>LPL季后赛观看留言板</h3>
<form action="/filter_demo/wordsServlet" method="post">
<textarea name="content" id="" cols="30" rows="10"></textarea>
<input type="submit" value="请留言">
</form>
</body>
</html>
② WordsServlet
public class WordsServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 获取表单中的留言信息(获取请求参数)
String content = req.getParameter("content");
// 2. 将请求参数的值输出到浏览器
resp.getWriter().write(content);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
5.2 统一网站编码
需求
tomcat8.5版本中已经将get请求的中文乱码解决了,但是post请求还存在中文乱码
浏览器发出的任何请求,通过过滤器统一处理中文乱码
5.2.1 需求分析
5.2.2 代码实现
真实场景中,过滤器不会统一响应mime类型
public class EncodeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
// 类型向下转型
HttpServletRequest request= (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
// 判断用户发出的请求是否是post请求,是,才设置编码
if(request.getMethod().equalsIgnoreCase("post")){
request.setCharacterEncoding("UTF-8");
}
response.setContentType("text/html;charset=utf-8");
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
<!--EncodeFilter-->
<filter>
<filter-name>EncodeFilter</filter-name>
<filter-class>com.lagou.filter.EncodeFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>EncodeFilter</filter-name>
<!--该拦截器的拦截路径 /*-->
<url-pattern>/*</url-pattern>
</filter-mapping>
Listener【了解】
1.1 概述
生活中的监听器
我们很多商场有摄像头,监听着客户的一举一动。如果客户有违法行为,商场可以采取相应的措施。
javaweb中的监听器
在我们的java程序中,有时也需要监视某些事情,一旦被监听的对象发生相应的变化,我们应该采取相应的操作。
监听web三大域对象:HttpServletRequest、HttpSession、ServletContext 通过监听器监听三大域对象它们的创建和销毁
场景
历史访问次数、统计在线人数、系统启动时初始化配置信息
1.2 快速入门
监听器在web开发中使用的比较少,见的机会就更少了,所以我们就使用ServletContextListenner来带领大家学习下监听器,因为这个监听器是监听器中使用率最高的一个,且监听器的使用方式都差不多。
我们使用这个监听器可以在项目启动和销毁的时候做一些事情,例如,在项目启动的时候加载配置文件。
ServletContextListener接口的API介绍--重要
使用步骤
1.创建一个类实现ServletContextListenner接口
2.实现ServletContextListenner的contextInitialized和contextDestroyed方法。
3.给这个类在xml中配置
public class MyServletContextListener implements ServletContextListener {
/*
监听servletContext对象创建的方法
*/
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
System.out.println("监听到servletContext对象创建了.....");
}
/*
监听servletContext对象销毁的方法
*/
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
System.out.println("监听到servletContext对象销毁了.....");
}
}
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">
<!--配置MyServletContextListener-->
<listener>
<listener-class>com.lagou.listener.MyServletContextListener</listener-class>
</listener>
</web-app>
同理:使用如下接口以相同的方式也可以监听到session对象和request对象的创建和销毁
HttpSessionListener:监听Httpsession域的创建于销毁的监听器
ServletRequestListener:监听ServletRequest域的创建于销毁的监听器