【JavaWeb学习笔记】14 - 三大组件其二 Listener Filter
API文档JAVA_EE_api_中英文对照版
Listener
一、监听器Listener
1. Listener监听器它是JavaWeb的三大组件之一。 JavaWeb的三大组件分别是: Servlet程序、Listener监听器、Filter过滤器
2. Listener是JavaEE的规范,就是接口
3.监听器的作用是,监听某种变化(一般就是对象创建/销毁,属性变化),触发对应方法完成相应的任务
4. JavaWeb中的监听器(共八个),目前最常用的是ServletContextListener,后面案例演示.
二、JavaWeb中的监听器
1.ServletContextListener监听器
1.作用:监听ServletCon text创建或销毁(当我们Web应用启动时,就会创建ServletContext),即生命周期监听,应用场景(1 )加载初始化的配置文件;比如spring的配置文件(2)任务调度(配合定时器Timer/TimerTask)
2.相关方法
????????void contextInitialized(ServletContextEvent sce)创建Servletcontext时触发void
????????contextDestroyed(ServletContextEvent sce)销毁Servletcontext时
/**
* 1. 当一个类实现了 ServletContextListener
* 2. 该类就是一个监听器
* 3. 该类可以监听的事件 由该类实现的监听接口决定 ,比如 实现ServletContextListener
* , 则该类就可以监听 ServletContext对象的创建和销毁, 以此类推
* 4. HspServletContextListener 就是一个监听者
* 5. 当web应用启动时,就会产生 ServletContextEvent 事件, 会调用监听器的对应事件处理方法
* contextInitialized, 同时会传递 事件对象
* 6. 程序员可以通过 ServletContextEvent 事件对象,来获取需要的信息, 然后再进行业务处理
* 7. tomcat怎么知道这个监听器存在 ? 因为我们需要在web.xml中配置(Tomcat底层有容器管理这个监听器)
*/
public class YhServletContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
System.out.println("YhServletContextListener 监听到" + servletContext + "被创建");
}
@Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
ServletContext servletContext = servletContextEvent.getServletContext();
System.out.println("YhServletContextListener 监听到" + servletContext + "被销毁");
//比如可以对ServletContext对象进行善后工作
}
}
2.ServletContextAttributeListener监听器
1.作用:监听ServletContext属性变化
2.相关方法
????????void attributeAdded(ServletContextAttributeEvent event)添加属性时调用
????????void attributeReplaced(ServletContextAttributeEvent event)替换属性时调用
????????void attributeRemoved(ServletContextAttributeEvent event)移除属性时调用
@WebListener()
public class YhServletContextAttributeListener implements ServletContextAttributeListener {
public void attributeAdded(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("HspServletContextAttributeListener 监听到添加属性.."
+ servletContextAttributeEvent.getName() + "=" + servletContextAttributeEvent.getValue() );
}
@Override
public void attributeRemoved(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("HspServletContextAttributeListener 监听到删除属性.."
+ servletContextAttributeEvent.getName() + "=" + servletContextAttributeEvent.getValue() );
}
@Override
public void attributeReplaced(ServletContextAttributeEvent servletContextAttributeEvent) {
System.out.println("HspServletContextAttributeListener 监听到修改属性.."
+ servletContextAttributeEvent.getName() + "=" + servletContextAttributeEvent.getValue() );
}
}
@WebServlet(name = "HiServlet",urlPatterns = "/hi")
public class HiServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//给servletContext 对象操作属性
ServletContext servletContext = request.getServletContext();
servletContext.setAttribute("name", "你好!!!!!!!!");
servletContext.setAttribute("name", "你好1");
servletContext.setAttribute("name", "你好2");
servletContext.setAttribute("name", "你好3");
servletContext.setAttribute("name", "你好4");
servletContext.setAttribute("name", "你好5");
servletContext.setAttribute("name", "你好6");
servletContext.setAttribute("name", "你好7");
servletContext.setAttribute("name", "你好8");
servletContext.setAttribute("name", "你好9");
servletContext.removeAttribute("name");
//获取session对象
//Filter
HttpSession session = request.getSession();
session.setAttribute("age", 100);
session.setAttribute("age", 400);
session.removeAttribute("age");
System.out.println("HiServlet 处理完毕....");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
3.HttpSessionListener
1.作用:监听Session创建或销毁,即生命周期监听
2.相关方法
????????void sessionCreated(HttpSessionEvent se)创建session时 调用void
????????sessionDestroyed(HttpSessionEvent se )销毁session时调用
3.可以用于监控用户上线,离线
?
@WebListener()
public class YhHttpSessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
//当session创建时,我们给它设置一个生命周期 30s
session.setMaxInactiveInterval(30);
System.out.println("YhHttpSessionListener 监听到 session创建= " +
session.getId());
System.out.println("用户id=" + session.getId() + " 上线");
}
@Override
public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
HttpSession session = httpSessionEvent.getSession();
System.out.println("YhHttpSessionListener 监听到 session销毁= " +
session.getId());
System.out.println("用户id=" + session.getId() + " 离线");
}
}
默认访问首页 会创建两个session
session可以获得其生命周期并设置
4.HttpSessionAttributeListener监听器
1.作用:监听Session属性的变化
2.相关方法
????????void attributeAdded(ServletRequestAttributeEvent srae)添加属性时
????????void attributeReplaced(ServletRequestAttributeEvent srae)替换属性时
????????void attributeRemoved(ServletRequestAttributeEvent srae)移除属性时
@WebListener
public class YhHttpSessionAttributeListener implements HttpSessionAttributeListener {
@Override
public void attributeAdded(HttpSessionBindingEvent httpSessionBindingEvent) {
//HttpSession session = httpSessionBindingEvent.getSession();
System.out.println("HspHttpSessionAttributeListener 监听到session添加属性" +
httpSessionBindingEvent.getName() + "=" + httpSessionBindingEvent.getValue());
}
@Override
public void attributeRemoved(HttpSessionBindingEvent httpSessionBindingEvent) {
HttpSession session = httpSessionBindingEvent.getSession();
System.out.println("HspHttpSessionAttributeListener 监听到session删除属性" +
httpSessionBindingEvent.getName());
}
@Override
public void attributeReplaced(HttpSessionBindingEvent httpSessionBindingEvent) {
System.out.println("HspHttpSessionAttributeListener 监听到session修改属性" +
httpSessionBindingEvent.getName() + "=" + httpSessionBindingEvent.getValue());
}
}
5.ServletRequestListener监听器
1. ServletRequestListener监听器
2.作用:监听Request创建或销毁,即Request生命周期监听
3.相关方法
????????void requestInitialized(ServletRequestEvent sre)创建request时
????????void requestDestroyed(ServletRequestEvent sre)销毁request时
4.可以用来监控,某个IP,访问我们网站的频率
@WebListener
public class YhRequestListener implements ServletRequestListener {
@Override
public void requestInitialized(ServletRequestEvent servletRequestEvent) {
System.out.println("HspRequestListener 监听到 request对象创建");
ServletRequest servletRequest = servletRequestEvent.getServletRequest();
System.out.println("记录访问日志....");
System.out.println("访问IP= " + servletRequest.getRemoteAddr());
System.out.println("访问的资源= " + ((HttpServletRequest)servletRequest).getRequestURL());
}
@Override
public void requestDestroyed(ServletRequestEvent servletRequestEvent) {
System.out.println("HspRequestListener 监听到 request对象被销毁");
}
}
6.ServletRequestAttributeListener监听器
1.作用:监听Request属性变化
2.相关方法
????????void attributeAdded(ServletRequestAttributeEvent srae)添加属性时
????????void attributeReplaced(ServletRequestAttributeEvent srae)替换属性时
????????void attributeRemoved(ServletRequestAttributeEvent srae)移除属性时
3.使用方法和前面类似
Filter
一、过滤器Filter
1.示意图
2.过滤器介绍
1. Filter过滤器它是JavaWeb的三大组件之工(Servlet程序、Listener监听器、Filter 过滤器)
2. Filter过滤器是JavaEE的规范,是接口
3. Filter过滤器它的作用是:拦截请求,过滤响应。
4.应用场景
????????权限检查
????????日记操作
????????事务管理
二、过滤器的基本原理
三、Filter过滤器的快速入门
需求:在web工程下,有后台管理目录manage,要求该目录下所有资源(html、图片、jsp、Servlet等)用户验证成功登录后才能访问
过滤器工作流程
两个jsp页面?一个表单登录?一个后台管理?一个servlet验证用户登录
创建Filter并在web.xml配置
<!--filter一般写在其它servlet的前面
1. 观察我们发现filter 配置和 servlet 非常相似. filter也是被tomcat管理和维护
2. url-pattern 就是当请求的url 和 匹配的时候,就会调用该filter
3. /manage/* 第一个 / 解析成 http://ip:port/工程路径
4. 完整的路径就是 http://ip:port/工程路径/manage/* 当请求的资源url满足该条件时
都会调用filter , /manage/admin.jsp
-->
<filter>
<filter-name>ManageFilter</filter-name>
<filter-class>com.yinhai.filter.ManageFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ManageFilter</filter-name>
<url-pattern>/manage/*</url-pattern>
</filter-mapping>
Tomcat底层维护这个filter容器?
/**
*
* 1. filter在web项目启动时, 由tomcat 来创建filter实例, 只会创建一个
* 2. 会调用filter默认的无参构造器, 同时会调用 init方法, 只会调用一次
* 3. 在创建filter实例时,同时会创建一个FilterConfig对象,并通过init方法传入
* 4. 通过FilterConfig对象,程序员可以获取该filter的相关配置信息
* 5. 当一个http请求和该filter的的url-patter匹配时,就会调用doFilter方法
* 6. 在调用doFilter方法时,tomcat会同时创建ServletRequest 和 ServletResponse 和 FilterChain对象
* , 并通过doFilter传入.
* 7. 如果后面的请求目标资源(jsp,servlet..) 会使用到request,和 response,那么会继续传递
* 8. 老师的提醒:到javaweb - ssm - springboot , 有 浏览器和 web服务器(tomcat)参与, 而这两个部分不是我们
* 程序员自己写,所以理解起来比 java se要困难!!!
*/
public class ManageFilter implements Filter {
private int count = 0;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//当Tomcat 创建 Filter创建,就会调用该方法,进行初始化
//回忆我们自己实现tomcat底层机制+servlet程序, 就会了然
System.out.println("ManageFilter init被调用...");
}
@Override
public void doFilter(ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain) throws IOException, ServletException {
System.out.println("ManageFilter doFilter() 被调用=" + (++count));
//到每次调用该filter时,doFilter就会被调用
//如果这里,没有调用继续请求的方法,则就停止
//如果继续访问目标资源-> 等价于放行
//老师说明:在调用过滤器前,servletRequest对象=request已经被创建并封装
//所以:我们这里就可以通过servletRequest获取很多信息, 比如访问url , session
//比如访问的参数 ... 就可以做事务管理,数据获取,日志管理等
//获取到session
//可以继续使用 httpServletRequest 方法.
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
System.out.println("输入密码=" + httpServletRequest.getParameter("password"));
HttpSession session = httpServletRequest.getSession();
//获取username session对象, 还可以继续使用
Object username = session.getAttribute("username");
if (username != null) {
//filterChain.doFilter(servletRequest, servletResponse)
//1. 继续访问目标url上的资源
//2. servletRequest 和 servletResponse 对象会传递给目标资源/文件
//3. 一定要理解filter传递的两个对象,再后面的servlet/jsp 是同一个对象(指的是在一次http请求)
System.out.println("servletRequest=" + servletRequest);
System.out.println("日志信息==");
System.out.println("访问的用户名=" + username.toString());
System.out.println("访问的url=" + httpServletRequest.getRequestURL());
System.out.println("访问的IP=" + httpServletRequest.getRemoteAddr());
filterChain.doFilter(servletRequest, servletResponse);//相当于放行
} else {//说明没有登录过..回到登录页面
servletRequest.getRequestDispatcher("/login.jsp").
forward(servletRequest, servletResponse);
}
}
@Override
public void destroy() {
//当filter被销毁时,会调用该方法
System.out.println("ManageFilter destroy()被调用..");
}
}
四、Filter过滤器url-pattern
1、url-pattern : Filter的拦截路径,即浏览器在请求什么位置的资源时,过滤器会进行拦截过滤
2、精确匹配<url-pattern> /a.jsp</ url-pattern>对应的请求地址http:/ /ip[域名]:port/工程路径/a.jsp会拦截
3、目录匹配<url-pattern>/manage/*</url-pattern>对应的请求地址http://ip[域名]:port/工程路径/manage/xx,即web工程manage目录下所有资源会拦截
4、后缀名匹配<url-pattern> *.jsp< /url-pattern> 后缀名可变,比如* .action * .do 等等对应的请求地址http:/ /ip[域名]:port/工程路径/xx.jsp ,后缀名为.jsp请求会拦截
5、Filter过滤器它只关心请求的地址是否匹配,不关心请求的资源是否存在
五、Filter过滤器生命周期
1.?filter在web项目启动时,?由tomcat?来创建filter实例,?只会创建一个
2.?会调用filter默认的无参构造器,?同时会调用?init方法,?只会调用一次
3.?在创建filter实例时,同时会创建一个FilterConfig对象,并通过init方法传入
4.?通过FilterConfig对象,程序员可以获取该filter的相关配置信息
5.?当一个http请求和该filter的的url-patter匹配时,就会调用doFilter方法
6.?在调用doFilter方法时,tomcat会同时创建ServletRequest?和?ServletResponse?和?FilterChain对象并通过doFilter传入.
7.?如果后面的请求目标资源(jsp,servlet..)?会使用到request,和?response,那么会继续传递
8.到javaweb?-?ssm?-?springboot?,?有?浏览器和?web服务器(tomcat)参与,?而这两个部分不是我们程序员自己写,所以理解起来比?java?se要困难!!!
?
六、FilterConfig
FilterConfig说明
1. FilterConfig是Filter过滤器的配置类
2. Tomcat每次创建Filter的时候,也会创建一一个 FilterConfig对象,这里包含了Filter配置文件的配置信息。
3.FilterConfig对象作用是获取filter过滤器的配置内容
使用web.xml配置或者使用注解配置
注解配置?03-Servlet-注解配置_注解配置servlet-CSDN博客
@WebFilter(filterName = "YhFilterConfig",urlPatterns = "/abc/*",initParams = {
? ? ? ? @WebInitParam(name = "ip",value = "166.66.66.66"),
? ? ? ? @WebInitParam(name = "port",value = "8888")
})
演示设定过滤器的参数以及如何根据参数过滤访问IP?
@WebFilter(filterName = "YhFilterConfig",urlPatterns = "/abc/*",initParams = {
@WebInitParam(name = "ip",value = "127.0"),
@WebInitParam(name = "port",value = "8888")
})
public class YhFilterConfig implements Filter {
private String ip; //从配置获取的ip
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("YhFilterConfig init() 被调用..");
//通过filterConfig 获取相关的参数
String filterName = filterConfig.getFilterName();
ip = filterConfig.getInitParameter("ip");
ServletContext servletContext = filterConfig.getServletContext();
//可以获取到该filter所有的配置参数名
Enumeration<String> initParameterNames =
filterConfig.getInitParameterNames();
//遍历枚举
while (initParameterNames.hasMoreElements()) {
System.out.println("名字=" + initParameterNames.nextElement());
}
System.out.println("filterName= " + filterName);
System.out.println("ip= " + ip);
System.out.println("servletContext= " + servletContext);
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//通过forbidden ip 来进行控制
//先获取到访问ip
String remoteAddr = servletRequest.getRemoteAddr();//获得访问客户端的IP
String localAddr = servletRequest.getLocalAddr();//获得本机IP
System.out.println(localAddr);
System.out.println(remoteAddr);
if(remoteAddr.contains(ip)) {
System.out.println("封杀该网段..");
servletRequest.getRequestDispatcher("/login.jsp").
forward(servletRequest,servletResponse);
return; //直接返回
}
//继续访问目标资源
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
?
?七、Filter过滤器链
1.案例
注意?过滤器链的顺序和XML书写顺序一样,但是注解没有顺序!
@WebFilter(filterName = "AFilter",urlPatterns = "/admin/*")
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---> 线程id=" +
Thread.currentThread().getId());
System.out.println("AFilter doFilter 的前置代码...");
System.out.println("执行 AFilter doFilter()");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("AFilter doFilter 的后置代码...");
}
@Override
public void destroy() {
}
}
@WebFilter(filterName = "BFilter",urlPatterns = "/admin/*")
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---> 线程id=" +
Thread.currentThread().getId());
System.out.println("BFilter doFilter 的前置代码...");
System.out.println("执行 BFilter doFilter()");
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("BFilter doFilter 的后置代码...");
}
@Override
public void destroy() {
}
}
2.FilterChain注意事项和细节
1.多个filter和目标资源在一次http请求, 在同一个线程中
2.当一个请求url和filter的 url-pattern 匹配时,才会被执行,如果有多个匹配上,就会顺序执行,形成一个filter调用链
3.多个filter共同执行时,因为是一次http请求, 使用同一个request对象
4.多个filter执行顺序,和web.xmI配置顺序保持一致
5. chain.doFilter(req, resp)方法将执行下一个过滤器的doFilter方法,如果后面没有过滤器,则执行目标资源。
6.注意执行过滤器链时,顺序是(用前面的案例分析) Http请求 -> A过滤器dofilter() -> A过滤器前置代码 -> A过滤器chain.doFilter() -> B过滤器dofilter() -> B过滤器前置代码 -> B过滤器chain.doFilter()? -> 目标文件 -> B过滤器后置代码 -> A过滤器后置代码 -> 返回给浏览器页面/数据
八、Filter作业
需求分析:使用过滤器,完成如下要求.
1)点击发表评论页面topic.jsp,可以在showTopic.jsp显示评论内容
2)如果发表的评论内容,有关键字比如"苹果" "香蕉",就返回topic,并提示有禁用词
3)要求发表评论到showTopic.jsp时,经过过滤器的处理
4)禁用词,配置在过滤器,在启动项目时动态的获取,注意处理中文
过滤器?
@WebFilter(filterName = "TopicFilter",urlPatterns = "/homework/*",initParams = {
@WebInitParam(name = "forbiddenword",value = "apple,hello,hi")
})
public class TopicFilter implements Filter {
//属性-> 存放禁用词
private String[] forbiddenWords = null;
@Override
public void init(FilterConfig filterConfig) throws ServletException {
//获取禁用词
String forbiddenword = filterConfig.getInitParameter("forbiddenword");
forbiddenWords = forbiddenword.split(",");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
//解决从topic.jsp 提交的中文乱码问题
servletRequest.setCharacterEncoding("utf-8");
//判断评论是不是有禁用词
String content = servletRequest.getParameter("content");
//循环遍历一把,看看有没有禁用词
for (String forbiddenWord : forbiddenWords) {//java基础
if (content.contains(forbiddenWord)) {
//返回topic.jsp
servletRequest.setAttribute("errorInfo", "你输入的有禁用词");
servletRequest.getRequestDispatcher("/topic.jsp")
.forward(servletRequest, servletResponse);
return;//返回
}
}
//继续到目标
filterChain.doFilter(servletRequest, servletResponse);
}
@Override
public void destroy() {
}
}
页面
<%@ page contentType="text/html;charset=UTF-8" language="java"%>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>发表对阿凡达电影评论</h1>
过滤词: 苹果, 香蕉 ${errorInfo}
<form method="post" action="<%=request.getContextPath()%>/topic/showTopic.jsp">
用户: <input type="text" name="username"><br/>
评论: <textarea rows="10" name="content" cols="20"></textarea><br/>
<input type="submit" value="发表评论">
</form>
</body>
</html>
展示页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<h1>你发表的评论是</h1>
评论内容: <%=request.getParameter("content")%>
</body>
</html>
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!