过滤器
java web的三种组件
过滤器的基本概念
过滤器介绍
过滤器检查是否带红包,带红包方可进场参加婚礼,否则禁止入内
过滤器使用场景
编写第一个过滤器
Demo1Filter
package com.itheima.filter;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/**
* 开发过滤器步骤:
* 1.编写一个类实现javax.servlet.Filter接口
* 2.重写接口中的所有方法,其中doFilter就是过滤方法
* 3.通过xml或注解@WebFilter进行配置
*/
@WebFilter("/demo1") //demo1不是访问地址而是拦截地址,如果访问的资源经过demo1,那么就进行过滤
public class Demo1Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
/**
*
* @param req 请求对象 ServletRequest 是HttpServletRequest的父接口
* @param resp 响应对象 ServletRequest 是HttpServletRequest的父接口
* 在 tomcat里面,请求和响应生成的就是同一个对象
* @param chain 过滤器链 放行或拦截
*/
@Override
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
System.out.println("过滤器请求时候执行");
chain.doFilter(req,resp);
System.out.println("过滤器响应时候执行");
}
@Override
public void destroy() {
}
}
Demo1Servlet
package com.itheima.servlet;
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;
import java.io.PrintWriter;
@WebServlet("/demo1")
public class Demo1Servlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.设置响应类型和编码
response.setContentType("text/html;charset=utf-8");
//2.获取打印流
PrintWriter out = response.getWriter();
//在浏览器输出
out.println("到达web资源,访问servlet");
//同时也在服务器的控制台输出
System.out.println("到达web资源,访问servlet");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
服务器端&浏览器端输出结果
过滤器的执行流程
过滤器的生命周期
Servlet是在用户第一次访问的时候创建
过滤器实在服务器启动时候创建
例如:上学路口拦妹子
FilterConfig接口
案例练习
package com.itheima.filter;
import javax.servlet.*;
import java.io.IOException;
import java.util.Enumeration;
public class Demo2ConfigFilter implements Filter {
/**
* 如果要读取xml的配置文件的信息,要是用FilterConfig接口中的方法
* 前提:要是用xml的配置方式,而不是注解
* @param config
* @throws ServletException
*/
public void init(FilterConfig config) throws ServletException {
//读取init-param的参数名和参数值
//通过名字获取一个值
String encoding = config.getInitParameter("encoding");
System.out.println("编码是:"+encoding);
//获取所有参数的名字
Enumeration<String> parameterNames = config.getInitParameterNames();
//遍历所有的参数名字
while (parameterNames.hasMoreElements()){
//获取参数名
String name = parameterNames.nextElement();
//获取值
String value = config.getInitParameter(name);
//打印
System.out.println("参数名:"+name+",值是:"+value);
}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
System.out.println("过滤器请求时候执行");
chain.doFilter(request, response);
System.out.println("过滤器响应时候执行");
}
public void destroy() {
}
}
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">
<!--使用配置方式创建过滤器-->
<filter>
<!--过滤器的名字-->
<filter-name>demo2</filter-name>
<!--过滤器的类全名-->
<filter-class>com.itheima.filter.Demo2ConfigFilter</filter-class>
<!--配置初始化参数-->
<init-param>
<param-name>encoding</param-name>
<param-value>GBK</param-value>
</init-param>
<init-param>
<param-name>country</param-name>
<param-value>China</param-value>
</init-param>
</filter>
<!--配置映射地址-->
<filter-mapping>
<!--过滤器的名字要与上面的相同-->
<filter-name>demo2</filter-name>
<!--拦截demo1的地址,多个过滤器可以同时拦截一个地址-->
<url-pattern>/demo1</url-pattern>
</filter-mapping>
</web-app>
映射的访问路径
/**
* 匹配路径
* 1.精确匹配:过滤地址与资源地址完全相同:@WebFilter("/demo1")
* 2.目录匹配:过滤某个路径下的所有资源:@WebFilter("/demo1/*")
* 3.过滤所有地址:@WebFilter("/*")
* 4.扩展名匹配:过滤某一类资源:@WebFilter("*.do")
* 5.如果同时出现以/开头和以扩展名结尾,并且有通配符的路径,会出现异常:@WebFilter("/*.do")
* 如果没有通配符的情况下是可以的:@WebFilter("/index.jsp")
*
* 匹配多个路径:路径是一个字符串的数组,所以可以同时指定多个路径
* 注解的属性:
* value:可以省略: @WebFilter(value={"/demo1","/demo2"})
* urlPatterns:与value的功能是一样的:URLPatterns={"/demo1","/demo2"}
* filterName:过滤器的名字,不能出现相同的名字
*/
三种拦截方式
过滤器的拦截行为
过滤多个地址
匹配多个路径:路径是一个字符串的数组,所以可以同时指定多个路径
- 注解的属性:
-
value:可以省略: @WebFilter(value={"/demo1","/demo2"})
-
urlPatterns:与value的功能是一样的:URLPatterns={"/demo1","/demo2"}
-
filterName:过滤器的名字,不能出现相同的名字
-
1.DispatcherType.FORWARD 拦截服务器的转发
-
dispatcherTypes = DispatcherType.FORWARD
-
2.DispatcherType.REQUEST 拦截浏览器的请求和服务器的转发
-
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
-
3.DispatcherType.INCLUDE 拦截服务器的包含
注解的方式拦截
- filterName:过滤器的名字,不能出现相同的名字
-
1.DispatcherType.FORWARD 拦截服务器的转发
-
dispatcherTypes = DispatcherType.FORWARD
-
2.DispatcherType.REQUEST 拦截浏览器的请求和服务器的转发
-
dispatcherTypes = {DispatcherType.FORWARD,DispatcherType.REQUEST}
-
3.DispatcherType.INCLUDE 拦截服务器的包含
配置方式拦截
<!--配置映射地址-->
<filter-mapping>
<!--过滤器的名字要与上面的相同-->
<filter-name>demo2</filter-name>
<!--拦截demo1的地址,多个过滤器可以同时拦截一个地址-->
<url-pattern>/demo1</url-pattern>
<!--配置拦截类型-->
<dispatcher>INCLUDE</dispatcher>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>
过滤器案例
使用过滤器过滤全局汉字乱码的问题
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录 </title>
</head>
<body>
<form action="login" method="post">
登录名:<input type="text" name="user"><br/>
<input type="submit" value="登录">
</form>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用户注册</title>
</head>
<body>
<h2>用户注册</h2>
<form action="register" method="post">
注册名:<input type="text" name="name">
<input type="submit" value="注册">
</form>
</body>
</html>
CharacterEncodingFilter
package com.itheima.servlet;
import javax.servlet.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebFilter(filterName = "CharacterEncodingFilter", urlPatterns = "/*")
public class CharacterEncodingFilter implements Filter {
public void init(FilterConfig config) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws ServletException, IOException {
//指定编码utf-8
request.setCharacterEncoding("utf-8");
//必须放行
chain.doFilter(request, response);
}
public void destroy() {
}
}
LoginServlet
package com.itheima.servlet;
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;
import java.io.PrintWriter;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户提交的参数
String user =request.getParameter("user");
//1.设置响应类型和编码
response.setContentType("text/html;charset=utf-8");
//2.获取打印流
PrintWriter out = response.getWriter();
out.println("登录成功,用户名是:"+user);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
RegisterServlet
package com.itheima.servlet;
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;
import java.io.PrintWriter;
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户提交的参数
String name =request.getParameter("name");
//1.设置响应类型和编码
response.setContentType("text/html;charset=utf-8");
//2.获取打印流
PrintWriter out = response.getWriter();
out.println("注册成功:"+name);
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
用户权限的过滤
分析
项目布局
login.jsp(登录页面)
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022-05-10
Time: 0:06
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>用户登录</title>
</head>
<body>
<form action="login" method="post">
用户名:<input type="text" name="user"><br/>
密码:<input type="text" name="pass"><br/>
<input type="submit" value="登录">${msg}
</form>
</body>
</html>
LoginServlet
package com.itheima.controller;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//获取用户输入的账户和密码
String user = request.getParameter("user");
String pass = request.getParameter("pass");
//判断账户密码是否正确
if("NewBoy".equals(user)&&"1234".equals(pass)){
//密码正确,创建会话域
HttpSession session = request.getSession();
//创建会话域对象
session.setAttribute("user",user);
//重定向到添加页面
response.sendRedirect(request.getContextPath()+"/admin/add.jsp");
}else {
//密码不正确,向请求域中存信息
request.setAttribute("msg","账户或者密码错误");
//转发到登录页面
request.getRequestDispatcher(request.getContextPath()+"login.jsp").forward(request,response);
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
this.doPost(request, response);
}
}
list.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022-05-10
Time: 0:33
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>显示用户列表</title>
</head>
<body>
<h2>显示用户列表</h2>
登录或者未登录都可以访问
</body>
</html>
add.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022-05-10
Time: 0:15
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>添加用户</h1>
必须登录后才可以访问
<a href="logout.jsp">退出</a>
</body>
</html>
update.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022-05-10
Time: 0:16
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>修改</title>
</head>
<body>
<h2>修改用户</h2>
必须登录后才可以访问
</body>
</html>
logout.jsp
<%--
Created by IntelliJ IDEA.
User: Administrator
Date: 2022-05-10
Time: 0:36
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>退出</title>
</head>
<body>
<%
//销毁会话
session.invalidate();
%>
<h2>您已成功退出</h2>
<a href="../login.jsp">重新登陆</a>
</body>
</html>
案例:过滤敏感词汇
过滤链FilterChain的使用
FilterChain介绍
案例:过滤器链
注解的方式:
多个过滤器过滤同一个访问地址
如果使用注解的方式配置过滤器,按类名的字母的顺序来确定先后顺序
配置的方式
多个过滤器过滤同一个访问地址
按照配置文件的先后顺序来
小结
监听器
监听器的概述
ServletContextListener监听器
注解的方式创建上下文域监听器
配置的方式监听上下文域
只需要写类名即可
区分使用
总结写的类使用注解,引用第三方工具类的使用配置.
ServletContextAttributeListener监听器
写的是修改前的数据
小结
案例:统计网站当前在线人数
案例分析
CounterListener
count.jsp
logout.jsp