• Java学习之Filter与Listener篇


    Java学习之Filter与Listener篇

    0x00 前言

    在一些登录点或者是登录后才能使用的一些功能点里面,需要该用户登录后才去才能去访问或使用这些功能。但我们如果每个servlet都去进行一个判断是否登录,这些会有很多重复代码,而且效率也比较低。那么我们可以把这些代码都放到Filter过滤器里面去进行编写。

    web里面有三大组件:servlet、Filter、Listener。

    下来会来写Filter和Listener的相关内容。

    0x01 Filter 过滤器

    filter作用:当访问服务器的资源时,过滤器可以将请求拦截下来,完成一些特殊的功能。

    一般用于完成一些统一的操作,比如登录验证。

    定义步骤:

    1. 定义一个类,实现接口Filter
    2. 复写方法
    3. 配置拦截路径
    

    配置拦截路径有2种方式,分别是web.xml和注解进行配置。

    注解配置拦截路径

    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    @WebFilter("/*")
    public class FilerDemo1 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("filterdemo执行");
            filterChain.doFilter(servletRequest, servletResponse);  //放行
    
    
        }
    
        @Override
        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>demo1</filter-name>  //声明名字
            <filter-class>cn.test.web.filter.FilerDemo1</filter-class> //声明对应的filter过滤器
        </filter>
    
        <filter-mapping>
            <filter-name>demo1</filter-name>
            <url-pattern>/*</url-pattern>     //声明filter拦截资源
        </filter-mapping>
    </web-app>
    

    这里可以看到filter类,需要重写3个方法,这里的三个方法的作用分别是:

    
    1. init:在服务器启动后,会创建Filter对象,然后调用init方法。只执行一次。用于加载资源
    
    2. doFilter:每一次请求被拦截资源时,会执行。执行多次
    
    3. destroy:在服务器关闭后,Filter对象被销毁。如果服务器是正常关闭,则会执行destroy方法。只执行一次。用于释放资源
    

    服务器会先执行过滤器,再执行过滤器放行的资源,最好再执行过滤器放行后面的代码。

    上面的代码直接拦截了所有的资源,定义的时候过滤器有多种的定义方式

    1. 具体资源路径: /index.jsp   只有访问index.jsp资源时,过滤器才会被执行
    
    2. 拦截目录: /user/*	访问/user下的所有资源时,过滤器都会被执行
    
    3. 后缀名拦截: *.jsp		访问所有后缀名为jsp资源时,过滤器都会被执行
    
    4. 拦截所有资源:/*		访问所有资源时,过滤器都会被执行
    
    

    我们可以将后台的一些功能servlet定义为amdin/addUserserlvlet,定义多一层目录,拦截器可以直接定义拦截路径为admin/*这样,如果携带了登录的session后,才选择放行。

    定义拦截方式

    注解里面定义拦截路径,默认是REQUEST方式,也就是浏览器直接访问,使用转发或者或者是其他这些方式访问一样是会被拦截器给拦截的。

    如果我们需要使用转发访问资源不被拦截器拦截,可以在注解中配置dispatcherTypes属性的值。

    dispatcherTypes 五种属性:

    1. REQUEST:默认值。浏览器直接请求资源
    
    2. FORWARD:转发访问资源
    
    3. INCLUDE:包含访问资源
    
    4. ERROR:错误跳转资源
    
    5. ASYNC:异步访问资源
    
    

    代码:

    package cn.test.web.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import java.io.IOException;
    
    @WebFilter(value = "/*",dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD})  //定义浏览器请求和转发拦截器被执行
    public class FilerDemo1 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("filterdemo执行");
            filterChain.doFilter(servletRequest, servletResponse);  //放行
    
    
        }
    
        @Override
        public void destroy() {
    
        }
    }
    
    

    如果是在web.xml里面进行配置,那么我们只需要加入

    REQUEST

    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>demo1</filter-name>
            <filter-class>cn.test.web.filter.FilerDemo1</filter-class>
        </filter>
    
        <filter-mapping>
            <filter-name>demo1</filter-name>
            <url-pattern>/*</url-pattern>
    
            <dispatcher>REQUEST</dispatcher>
        </filter-mapping>
    
    </web-app>
    
    

    登陆过滤器案例:

    package cn.test.web.filter;
    
    import javax.servlet.*;
    import javax.servlet.annotation.WebFilter;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    @WebFilter("/*")
    public class loginFilter implements Filter {
        public void destroy() {
        }
    
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
                System.out.println(req);
                //强制转换成 HttpServletRequest
                HttpServletRequest request = (HttpServletRequest) req;
    
                //获取资源请求路径
                String uri = request.getRequestURI();
                //判断是否包含登录相关资源路径,排除掉 css/js/图片/验证码等资源
                if(uri.contains("/login.jsp") || uri.contains("/loginServlet") || uri.contains("/css/") || uri.contains("/js/") || uri.contains("/fonts/") || uri.contains("/checkCodeServlet")  ){
                    //包含,用户就是想登录。放行
                    chain.doFilter(req, resp);
                }else{
                    //不包含,需要验证用户是否登录
                    //从获取session中获取user
                    Object user = request.getSession().getAttribute("user");
                    if(user != null){
                        //登录了。放行
                        chain.doFilter(req, resp);
                    }else{
                        //没有登录。跳转登录页面
    
                        request.setAttribute("login_msg","您尚未登录,请登录");
                        request.getRequestDispatcher("/login.jsp").forward(request,resp);
                    }
                }
    
    
                // chain.doFilter(req, resp);
            }
        
    
        public void init(FilterConfig config) throws ServletException {
    
        }
    
    }
    
    

    0x02 Listener 监听器

    事件监听机制:

    * 事件	:一件事情
    
    * 事件源 :事件发生的地方
    
    * 监听器 :一个对象
    
    * 注册监听:将事件、事件源、监听器绑定在一起。 当事件源上发生某个事件后,执行监听器代码
    

    listener 监听器实现:

    首先我们需要实现ServletContextListener的接口,该接口并没有一个定义好的实现类,需要自己进行定义。

    ServletContextListener方法:

    * void contextDestroyed(ServletContextEvent sce) :ServletContext对象被销毁之前会调用该方法
    
    * void contextInitialized(ServletContextEvent sce) :ServletContext对象创建后会调用该方法
    
    

    代码:

    @WebListener
    public class ContextLoadListeter implements ServletContextListener {
        @Override
        public void contextInitialized(ServletContextEvent servletContextEvent) {
            ServletContext servletContext = servletContextEvent.getServletContext();   
            String contextConfig = servletContext.getInitParameter("configLocation");  //获取configLocation的参数
            String realPath = servletContext.getRealPath(contextConfig);  //获取路径
            try {
                FileInputStream ifs = new FileInputStream(realPath);  //读取文件
                System.out.println(ifs);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
    
        }
    
    
        @Override
        public void contextDestroyed(ServletContextEvent servletContextEvent) {
            System.out.println("listeter被销毁");
        }
    }
    
    

    web.xml配置:

     <context-param>
            <param-name>configLocation</param-name>
            <param-value>/WEB-INF/config.xml</param-value>
        </context-param>
    

    监听器一般用于默认加载资源。

    0x03 结尾

    Filter与Listener篇完结。

  • 相关阅读:
    Shell学习(四)Shell运算符
    Shell学习(三)Shell参数传递
    Shell学习(二)Shell变量
    Shell学习(一)认识Shell
    JVM学习(四)JVM调优
    JVM学习(三)JVM垃圾回收
    JVM学习(二)JVM加载类
    JVM学习(一)什么是JVM
    Python学习————包
    Python学习————模块
  • 原文地址:https://www.cnblogs.com/nice0e3/p/13551701.html
Copyright © 2020-2023  润新知