17.Listener&Filter
17.1.JavaEE规范
- EE规范对于Web组件一共定义了三个标准,其中之一就是我们经常使用的Servlet,除此之外还有另外两个组件
- Listener:监听器。监听某一个对象的创建、销毁、属性的变更等。可以把之前写在某个servlet的init方法里面的代码写在listener里面。
- Filter:过滤器,拦截、过滤。黑名单。订单、个人主页
17.2.Listener监听器
17.2.1.介绍
- 概念:web的三大组件(web Component)之一。
- 事件监听机制
- 事件:一件事情
- 事件源 :事件发生的地方
- 监听器 :一个对象
- 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码
17.2.2.分类
- web中的监听器一共可以分为三大类8种,
- 三个域对象创建、销毁的监听器 ServletContextListener
- 三个域对象属性变更的监听器
- session数据钝化、活化的监听器
17.2.3.使用
-
ServletContextListener:监听ServletContext对象的创建和销毁
-
方法:
- void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
- void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法
- 步骤:
- 定义一个类,实现ServletContextListener接口
- 复写方法
- 配置
- 方式一:web.xml
<listener> <listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class> </listener> <context-param>指定初始化参数
- 方式二:注解:@WebListener
- Example
import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; @WebListener public class MyServletContextListener implements ServletContextListener { @Override public void contextInitialized(ServletContextEvent servletContextEvent) { System.out.println("context init"); } @Override public void contextDestroyed(ServletContextEvent servletContextEvent) { System.out.println("context destroy"); } }
17.3.Filter过滤器
17.3.1.介绍
- 过滤器介于客户端与Servlet/JSP等相关的资源之间,对于与过滤器关联的Servlet来说,过滤器可以在Servlet被调用之前检查并且修改request对象。在Servlet调用之后检查并修改response对象。
- 过滤器的作用:一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤等等
17.3.2.使用
- 步骤:
- 定义一个类,实现接口Filter
- 复写方法
- 配置拦截路径
- 方式一:web.xml
- 方式二:注解
@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
public class FilterDemo1 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("filterDemo1被执行了....");
//放行
filterChain.doFilter(servletRequest,servletResponse);
}
@Override
public void destroy() {
}
}
17.3.3.过滤器细节
- web.xml配置
<filter> <filter-name>demo1</filter-name> <filter-class>cn.itcast.web.filter.FilterDemo1</filter-class> </filter> <filter-mapping> <filter-name>demo1</filter-name> <!-- 拦截路径 --> <url-pattern>/*</url-pattern> </filter-mapping>
- 过滤器执行流程
- 执行过滤器
- 执行放行后的资源
- 回来执行过滤器放行代码下边的代码
- 过滤器生命周期方法
- void init(FilterConfig config):在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
- 用于初始化过滤器,当容器装载并初始化过滤器时调用。Web容器为此方法传递一个FilterConfig对象,
- FilterConfig对象可以获取web.xml文件中过滤器初始化参数的配置;
- 利用FilterConfig对象也可以获取当前Filter的名称以及相关联的ServletContext对象。
- void doFilter(ServletRequst request, ServletResponse response, FilterChain chain):每一次请求被拦截资源时,会执行。执行多次
- 此方法是Filter接口的核心方法,用于对请求对象和响应对象进行检查和处理。
- 访问服务器的时候执行chain.doFilter(request, response)上面的,响应的时候执行下面的
- 此方法包括三个输入参数。其中,
- ServletRequest对象为请求对象,包括表单数据、Cookie以及HTTP请求头等信息;
- ServletResponse对象为响应对象,用于响应使用ServletRequest对象访问的信息;
- FilterChain用来调用过滤器链中的下一个资源,
- 即将ServletRequest对象以及ServletResponse对象传递给下一个过滤器或者是其它的Servlet/JSP等资源。
- void destroy( ):在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
- 此方法用于销毁过滤器,当容器要销毁过滤器实例时调用此方法,Servlet过滤器占用的资源会被释放。
import javax.servlet.*; import javax.servlet.annotation.WebFilter; import java.io.IOException; @WebFilter("/filter1") public class FirstFilter implements Filter { //会在应用启动的时候直接实例化一个对象出来,然后执行init方法 @Override public void init(FilterConfig filterConfig) throws ServletException { System.out.println("filter init"); } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { System.out.println("filter doFilter"); } //应用被卸载、服务器关闭 @Override public void destroy() { System.out.println("filter destroy"); } }
- 过滤器配置详解
- 拦截路径配置:
- 具体资源路径: /index.jsp 只有访问index.jsp资源时,过滤器才会被执行2. 拦截目录: /user/* 访问/user下的所有资源时,过滤器都会被执行3. 后缀名拦截: .jsp 访问所有后缀名为jsp资源时,过滤器都会被执行4. 拦截所有资源:/ 访问所有资源时,过滤器都会被执行
- 拦截方式配置:资源被访问的方式
- 注解配置:
设置dispatcherTypes属性1. REQUEST:默认值。浏览器直接请求资源 2. FORWARD:转发访问资源 3. INCLUDE:包含访问资源 4. ERROR:错误跳转资源 5. ASYNC:异步访问资源 * web.xml配置 * 设置<dispatcher></dispatcher>标签即可
- 过滤器链(配置多个过滤器)
- 执行顺序:如果有两个过滤器:过滤器1和过滤器2
- 过滤器12. 过滤器23. 资源执行4. 过滤器25. 过滤器1
- 过滤器先后顺序问题:
- 注解配置:按照类名的字符串比较规则比较,值小的先执行 * 如: AFilter 和 BFilter,AFilter就先执行了。2. web.xml配置: 谁定义在上边,谁先执行
17.4.Filter关联Servlet
- 通过url-pattern产生关联。
- filter和servlet设置相同的url-pattern并不会导致出错。
- servlet:开发动态web资源的组件。一个请求只有一个组件来响应
- filter:拦截器、过滤器。它不是主要去做出响应的组件,所以设置它可以和servlet的url-pattern。
17.5.工作原理
- 客户端将请求发送给Web容器
- Web容器根据客户端发送的请求生成请求对象request和响应对象response
- Web容器在调用与过滤器相关联的Web组件(例如Servlet/JSP)之前,先将request对象以及response对象发送给过滤器。
- 过滤器对request对象进行必要的处理;
- 过滤器把处理过的reques对象以及response对象传递给Web组件
- Web组件调用完成后,再次通过过滤器,此时过滤器对response对象进行必要的处理;
- 过滤器把处理过的response对象传递给Web容器;
- Web容器将响应的结果返回到客户端,并在浏览器上显示。
17.6.案例
- 实现只有登录才能打开欢迎界面,即登录过后放行,未登录过滤
//登录的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;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
request.getSession().setAttribute("username", username);
response.setHeader("refresh", "2;url=" + request.getContextPath() + "/info.jsp");
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
//过滤器
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter("/*")
public class FirstFilter implements Filter {
//会在应用启动的时候直接实例化一个对象出来,然后执行init方法
@Override
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("filter init");
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
servletRequest.setCharacterEncoding("utf-8");
servletResponse.setContentType("text/html;charset=utf-8");
System.out.println("filter doFilter before");
// 验证页面是否需要被验证权限
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String servletPath = request.getServletPath();
if(auth(servletPath)){
//如何判断是否登录
Object username = request.getSession().getAttribute("username");
if(username == null){
//跳转到登录页面
response.sendRedirect(request.getContextPath() + "/login.jsp");
return;
}
}
//如果没有这行代码,那么就是执行的拦截
filterChain.doFilter(servletRequest, servletResponse);
System.out.println("filter doFilter after");
}
//验证身份、权限 学的知识点落地
/**
* 该方法用来验证某个请求路径是否需要验证身份 阿里巴巴编程规范
* @param servletPath
* @return <code>true</code>表示需要验证身份,返回值<code>false</code>表示不需要验证身份
*/
private boolean auth(String servletPath) {
if("/info.jsp".equals(servletPath)){
return true;
}
return false;
}
//应用被卸载、服务器关闭
@Override
public void destroy() {
System.out.println("filter destroy");
}
}
- 前端页面
<!-- 欢迎界面 -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
欢迎您,<%=session.getAttribute("username")%>
</body>
</html>
<!-- 登录界面 -->
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
<form action="<%=request.getContextPath()%>/login" method="post">
<input type="text" name="username"><br>
<input type="submit">
</form>
</body>
</html>
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/181050.html