Listener&Filter

不管现实多么惨不忍睹,都要持之以恒地相信,这只是黎明前短暂的黑暗而已。不要惶恐眼前的难关迈不过去,不要担心此刻的付出没有回报,别再花时间等待天降好运。真诚做人,努力做事!你想要的,岁月都会给你。Listener&Filter,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

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种,
    1. 三个域对象创建、销毁的监听器 ServletContextListener
    2. 三个域对象属性变更的监听器
    3. session数据钝化、活化的监听器
17.2.3.使用
  • ServletContextListener:监听ServletContext对象的创建和销毁

  • 方法:

    • void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
    • void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法
    • 步骤:
      1. 定义一个类,实现ServletContextListener接口
      2. 复写方法
      3. 配置
      • 方式一:web.xml
      <listener>
      	<listener-class>cn.itcast.web.listener.ContextLoaderListener</listener-class>
      </listener>
      
      <context-param>指定初始化参数
      
      • 方式二:注解:@WebListener
      1. 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.使用
  • 步骤:
    1. 定义一个类,实现接口Filter
    2. 复写方法
    3. 配置拦截路径
      • 方式一: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.过滤器细节
  1. 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>
    
  2. 过滤器执行流程
  3. 执行过滤器
  4. 执行放行后的资源
  5. 回来执行过滤器放行代码下边的代码
  6. 过滤器生命周期方法
  7. void init(FilterConfig config):在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
    • 用于初始化过滤器,当容器装载并初始化过滤器时调用。Web容器为此方法传递一个FilterConfig对象,
    • FilterConfig对象可以获取web.xml文件中过滤器初始化参数的配置;
    • 利用FilterConfig对象也可以获取当前Filter的名称以及相关联的ServletContext对象。
  8. void doFilter(ServletRequst request, ServletResponse response, FilterChain chain):每一次请求被拦截资源时,会执行。执行多次
    • 此方法是Filter接口的核心方法,用于对请求对象和响应对象进行检查和处理。
    • 访问服务器的时候执行chain.doFilter(request, response)上面的,响应的时候执行下面的
    • 此方法包括三个输入参数。其中,
      • ServletRequest对象为请求对象,包括表单数据、Cookie以及HTTP请求头等信息;
      • ServletResponse对象为响应对象,用于响应使用ServletRequest对象访问的信息;
      • FilterChain用来调用过滤器链中的下一个资源,
        • 即将ServletRequest对象以及ServletResponse对象传递给下一个过滤器或者是其它的Servlet/JSP等资源。
  9. 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");
        }
    }
    
  10. 过滤器配置详解
  • 拦截路径配置:
    1. 具体资源路径: /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. 过滤器链(配置多个过滤器)
  • 执行顺序:如果有两个过滤器:过滤器1和过滤器2
    1. 过滤器12. 过滤器23. 资源执行4. 过滤器25. 过滤器1
  • 过滤器先后顺序问题:
    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.工作原理
  1. 客户端将请求发送给Web容器
  2. Web容器根据客户端发送的请求生成请求对象request和响应对象response
  3. Web容器在调用与过滤器相关联的Web组件(例如Servlet/JSP)之前,先将request对象以及response对象发送给过滤器。
  4. 过滤器对request对象进行必要的处理;
  5. 过滤器把处理过的reques对象以及response对象传递给Web组件
  6. Web组件调用完成后,再次通过过滤器,此时过滤器对response对象进行必要的处理;
  7. 过滤器把处理过的response对象传递给Web容器;
  8. 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

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!