一 过滤器Filter
01 基础理论
1、概念说明
1. 什么是过滤器? 过滤器就是 Filter 他是JavaWeb的三大组件之一。 三大组件: Servlet、Filter、Listener 2. 过滤器有什么作用呢? 可以去拦截或者增强, 请求(request)和响应(response) 3. 应用场景有哪些呢? 自动登录 统一的编码设置 访问权限控制 敏感词过滤
生活实例
2、操作步骤
1. 如果是 XML 版本: A. 写一个类去实现 Filter 接口 B. 重写方法 init()、doFilter()、destroy() C. 在 web/WEB-INF/web.xml 当中配置过滤器 2. 如果是 注解 版本: A. 写一个类去实现 Filter 接口 B. 重写方法 init()、doFilter()、destroy() C. 在 类的上面添加注解 @WebFilter("过滤的规则等")
02 快速入门
1、filer过滤器实现类
位置 src/com.chc01.DoorFilter
import javax.servlet.*;
import java.io.IOException;
public class DoorFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DoorFilter.init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("DoorFilter.doFilter ... 放行前");
//放行,才能往下执行。
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("DoorFilter.doFilter ... 放行后");
}
@Override
public void destroy() {
System.out.println("DoorFilter.destroy");
}
}
2、web.xml的配置
位置 web/WEB-INF/web.xml
<filter-mapping>
<filter-name>DoorFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>DoorFilter</filter-name>
<filter-class>blb.chc02.DoorFilter</filter-class>
</filter>
3、Servlet的代码实现
位置 src/blb.chc02.DoorServlet
/***
* 访问地址: http://localhost:8080/JavaWebDay20/DoorServlet
*/
@WebServlet("/DoorServlet")
public class DoorServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("DoorServlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("DoorServlet.doPost");
}
}
03 统一编码
1、CodeFilter
位置 src/blb.chc03.CodeFilter
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
//写一个类 去实现过滤器的接口 Filter
@WebFilter("/*")
public class CodeFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("CodeFilter.init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("CodeFilter.doFilter...执行前...");
//----------------
//可以给请求进行增强,设置统一的编码方式
servletRequest.setCharacterEncoding("UTF-8");
//可以给响应进行增强,设置响应文本信息
servletResponse.setContentType("text/html;charset=UTF-8");
//----------------
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("CodeFilter.doFilter...执行后...");
}
@Override
public void destroy() {
System.out.println("CodeFilter.destroy");
}
}
2、CodeServlet
位置 src/blb.chc03.CodeServlet
/***
* 访问地址: http://localhost:8080/JavaWebDay20/CodeServlet?username=张三&password=1234
*/
@WebServlet("/CodeServlet")
public class CodeServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("CodeServlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("CodeServlet.doPost");
//获取到请求的参数
String username = req.getParameter("username");
String password = req.getParameter("password");
//展示结果
if (username!=null && password!=null){
System.out.println("username = " + username);
System.out.println("password = " + password);
//回复数据
resp.getWriter().println(username+","+password);
}
}
}
04 三个细节
1、urlpatten 的写法
过滤参数的四种写法
编号 | 代码 | 说明 |
---|---|---|
1 | /* | 拦截所有的URL信息 |
2 | /dir/* | 拦截URL信息,在dir下面的会被拦截到 |
3 | *.jsp | 拦截URL信息,jsp 文件会被拦截到 |
案例代码
位置: blb.chc04.DemoUrl01Filter
//拦截war包下面,dir文件夹下面的所有信息
@WebFilter("/dir/*")
public class DemoUrl01Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DemoUrl01Filter.init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("DemoUrl01Filter.doFilter");
System.out.println("拦截war包下面,dir文件夹下面的所有信息");
//...
}
@Override
public void destroy() {
System.out.println("DemoUrl01Filter.destroy");
}
}
位置: blb.chc04.DemoUrl02Filter
//拦截war包下面所有的 jsp文件
@WebFilter(urlPatterns={"*.jsp"})
public class DemoUrl02Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("DemoUrl02Filter.init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("DemoUrl02Filter.doFilter");
System.out.println("拦截war包下面所有的 jsp文件");
//...
}
@Override
public void destroy() {
System.out.println("DemoUrl02Filter.destroy");
}
}
2、过滤器参数配置
过滤参数的五种写法 dispatcherTypes
编号 | 枚举类型 | 说明 |
---|---|---|
1 | FORWARD | 转发,当出现请求转发的时候,触发过滤器 |
2 | INCLUDE | 包含,当出现请求包含的时候,触发过滤器 |
3 | REQUEST | 请求,当发起请求的时候,触发过滤器 |
4 | ASYNC | 异步,当出现异步请求的时候,会触发过滤器 |
5 | ERROR | 出错,当出现错误信息的时候,触发过滤器 |
案例代码
代码位置 src/blb.chc05.ForwardFilter
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;
/***
* 用于请求转发的过滤器
* urlPatterns = "/*" 表示拦截所有的
* dispatcherTypes = DispatcherType.FORWARD 拦截请求转发的
*/
@WebFilter(urlPatterns = "/*",dispatcherTypes = DispatcherType.FORWARD)
public class ForwardFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("ForwardFilter.init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("ForwardFilter.doFilter....前");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("ForwardFilter.doFilter....后");
}
@Override
public void destroy() {
System.out.println("ForwardFilter.destroy");
}
}
代码位置 src/blb.chc05.Forward01Servlet
@WebServlet("/Forward01Servlet")
public class Forward01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Forward01Servlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Forward01Servlet.doPost");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("Forward01Servlet....");
//定义请求转发的代码
req.getRequestDispatcher("/Forward02Servlet").forward(req,resp);
}
}
代码位置 src/blb.chc05.Forward02Servlet
@WebServlet("/Forward02Servlet")
public class Forward02Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Forward02Servlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("Forward02Servlet.doPost");
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("Forward02Servlet....");
}
}
3、过滤器先后顺序问题
说明
1. 在我们的 web.xml 当中,如果采用的是 XML形式配置的过滤器。 谁写在上面,谁的优先级越高。 2. 如果我们采用的是注解的方式进行的配置,则会出现 过滤器类名称的顺序,字符串字典顺序,小的在前,大的在后。
案例
<filter-mapping>
<filter-name>Order01Filer</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>Order01Filer</filter-name>
<filter-class>blb.chc06.Order01Filer</filter-class>
</filter>
<filter-mapping>
<filter-name>Order02Filer</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>Order02Filer</filter-name>
<filter-class>blb.chc06.Order02Filer</filter-class>
</filter>
<filter-mapping>
<filter-name>Order03Filer</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter>
<filter-name>Order03Filer</filter-name>
<filter-class>blb.chc06.Order03Filer</filter-class>
</filter>
说明:
配置的方式是
从上往下分别是 01-02-03
请求开启的顺序是
01->02->03
响应开启的顺序是
03->02->01
采用注解的方式配置过滤器
过滤器 Order01Filer
@WebFilter("/*") public class Order01Filer implements Filter { ..... }
过滤器 Order02Filer
@WebFilter("/*") public class Order02Filer implements Filter { ..... }
过滤器 Order03Filer
@WebFilter("/*") public class Order03Filer implements Filter { ..... }
说明:
配置的方式是
从上往下分别是 Order01Filer-Order02Filer-Order03Filer
请求开启的顺序是
01->02->03
响应开启的顺序是
03->02->01
二 监听器 Listener
01 基础理论
1、概念说明
1. 什么是监听器? 过滤器就是 Listener 他是JavaWeb的三大组件之一。 三大组件: Servlet、Filter、Listener 2. 监听器有什么作用呢? 目前来说,作为一个简单的了解就行了,因为后期框架当中会对监听器进行包装。 我们可以采用监听器,去实时监听变化的数据。 例如: 在线直播的人数,实时变化。
2、操作步骤
1. 写一个类去实现接口 2. 重写方法,创建的方法和销毁的方法 3. 配置,可以采用 xml 配置,也可以采用 注解配置
3、八个常用接口
监听四大域对象的接口,只有三个。其中页面域不在范围内。
ServletContextListener HttpSessionListener ServletRequestListener
监听四大域对象属性的接口。只有三个。其中页面域不在范围内。
ServletContextAttributeListener HttpSessionAttributeListener ServletRequestAttributeListener
监听会话感知型的接口。会话域,可以进行永久性保存。钝化和活化
HttpSessionBindingListener HttpSessionActivationListener
02 快速入门
1、DoorListener
位置 src/blb.chc07.DoorListener
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class DoorListener implements ServletRequestListener {
//请求销毁的时候,调用此方法
@Override
public void requestDestroyed(ServletRequestEvent sre) {
System.out.println("DoorListener.requestDestroyed...销毁");
}
//请求初始化的时候,调用此方法
@Override
public void requestInitialized(ServletRequestEvent sre) {
System.out.println("DoorListener.requestInitialized...初始化");
}
}
2、DoorServlet
位置 src/blb.chc07.DoorServlet
/***
* 访问地址: http://localhost:8080/JavaWebDay20/DoorServlet
*/
@WebServlet("/DoorServlet")
public class DoorServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("DoorServlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("DoorServlet.doPost");
}
}
03 记录用户流量
1、需求说明
俊杰在抖音开直播,晒豪车,保时捷 Panamera 现在吸引了很多忠实的小粉丝过来观看。 最后在结束直播之后,需要去查看流量。 有多少人观看了直播。 说明: 只要开启了直播界面,我们就要计数。开启计数器,不断的增加。
2、案例代码
位置 src/blb.chc08.LiveListener
import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebListener;
import javax.servlet.http.HttpServletRequest;
/***
* 写一个类,实现接口 ServletRequestListener
*/
@WebListener
public class LiveListener implements ServletRequestListener {
//定义计数器, 准备用于记录观看直播的人数。
private int count = 0;
@Override
public void requestInitialized(ServletRequestEvent sre) {
//强制类型转换,成为http请求
HttpServletRequest request = (HttpServletRequest) sre.getServletRequest();
String uri = request.getRequestURI();
//含义是:只有在直播的 Servlet 当中才去做记录,否则不去记录
if (uri.contains("/LiveServlet")) {
System.out.println("LiveListener.requestInitialized....嘻嘻,小伙,又来看我啦...");
//只要有人来观看直播,计数器就要增加
count++;
//还需要把数据保存起来,可以采用会话对象保存
request.getSession().setAttribute("count", count);
}
}
}
位置 src/blb.chc08.LiveServlet
/**
* 直播的 Servlet
* 访问地址: http://localhost:8080/JavaWebDay20/LiveServlet
*/
@WebServlet("/LiveServlet")
public class LiveServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LiveServlet.doGet");
doPost(req,resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("LiveServlet.doPost");
//直接获取到会话域的数据
Object count = req.getSession().getAttribute("count");
//展示结果到浏览器当中
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().println("当前浏览量:"+count);
}
}