`Filter`和`LIstener`

FilterLIstener

Filter过滤器

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

作用:一般用于完成通用的操作。如:登录验证、统一编码处理、敏感字符过滤…

快速入门

步骤:

  1. 定义一个类,实现接口Filter
  2. 重写方法
  3. 配置拦截路径
    1. web.xml文件方式
    2. 注解方式
@WebFilter(urlPatterns = {"/*"})//表示拦截的资源路径
public class Filter1 implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
    @Override
    public void destroy() {
    }
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        // 放行语句
        filterChain.doFilter(servletRequest,servletResponse);
        System.out.printf("放行后执行了相关的业务代码后,还要回执行过滤器后面的代码");
    }
}

web.xml方式

<filter>
        <filter-name>filter1</filter-name>
        <filter-class>com.example.javawebServletFilter.Filter1</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <!--表示对所有的资源都进行拦截-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>

注解方式

@WebFilter("/*")//访问所有资源之前,都会执行该过滤器
过滤器细节
web.xml配置
<filter>
        <filter-name>filter1</filter-name>
        <filter-class>com.example.javawebServletFilter.Filter1</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <!--表示对所有的资源都进行拦截-->
        <url-pattern>/*</url-pattern>
    </filter-mapping>
过滤器执行流程
  1. 执行过滤器
  2. 执行放行后的业务逻辑
  3. 回来执行过滤器放行后面的代码
过滤器生命周期

1.web服务器启动时,就会创建Filter对象,然后调用init方法,只执行一次,用于加载资源文件

2.doFilter方法是每次一次请求都会被拦截资源时,会执行,执行多次

3.destroy在服务器正常关闭时,Filter对象被销毁时,就是会执行一次这【注意是正常关闭web服务器】

过滤器配置详解
拦截路径配置
1.具体资源路径:
/index.jsp    			只有访问`index.jsp`资源时,过滤器都会被执行

2.拦截目录
/user/*					访问`/user下的所有资源时,过滤器都会被执行

3.后缀名拦截
*.jsp					访问所有后缀名为`jsp`资源时,过滤器都会被执行

4.拦截所有资源 
/*						访问所有资源时,过滤器都会被执行
拦截方式配置:资源被访问方式

方式一:注解配置

设置`dispatcherType`属性
		1.REQUEST		默认传下,浏览器直接请求资源 
		2.FORWARD		转发访问资源 
		3.INCLUDE		包含访问资源 
		4.ERROR			错误跳转资源 
		5.ASYNC			异步访问资源 

方式二:web.xml配置

 <filter>
        <filter-name>filter1</filter-name>
        <filter-class>com.example.javawebServletFilter.Filter1</filter-class>
    </filter>
    
    <filter-mapping>
        <filter-name>filter1</filter-name>
        <!--表示对所有的资源都进行拦截-->
        <url-pattern>/*</url-pattern>
        <!--配置拦截的方式-->
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
    </filter-mapping>
过滤器链(配置多个过滤器)

执行顺序:如果有两个过滤器:过滤器1和过滤器2

  1. 过滤器1
  2. 过滤器2
  3. 资源执行
  4. 过滤器2
  5. 过滤器1

过滤器先后顺序问题:

1.注解配置:按照类名的字符串比较,值小的先执行	
		如:AFilter和BFilter, AFilter就先执行了
		
2.web.xml配置:`<filter-mapping>谁定义在上边,谁先执行

登录验证案例:

需求:
			1. 访问day17_case案例的资源。验证其是否登录
			2. 如果登录了,则直接放行。
			3. 如果没有登录,则跳转到登录页面,提示"您尚未登录,请先登录"。

步骤:

  1. 编写一个Filter过滤器,将所有与登录有关的资源,进行放行,其他的则,不放行
  2. 再判断该用户是否登录过,如果没有登录过,直接跳转回登录页面
  3. 如果登录过直接放行

案例—2:敏感词汇过滤

 需求:
			1. 对day17_case案例录入的数据进行敏感词汇过滤
			2. 敏感词汇参考《敏感词汇.txt》
			3. 如果是敏感词汇,替换为 *** 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1SEkUN2J-1651926281050)(D:\typora笔记\img\3.过滤敏感词汇.bmp)]

分析:

  1. 由于在访问多个资源时,都需要对敏感词汇进行过滤,需要将敏感词汇过滤功能放在过滤器中
  2. 将请求request对象中封装的数据获取出来,进行过滤
  3. 由于request对象没有setParameter方法,只能getParameter方法
  4. 需要对request对象进行增强功能,增加的功能就是对敏感词汇进行过滤
  5. 过滤后,重新将增强request对象封装放行

增加对象的功能

设计模式:一些通用解决固定问题方式

1.装饰模式

2.代理模式

代理模式

概念:

  1. 真实对象:被代理的对象
  2. 代理对象
  3. 代理模式:代理对象代理真实对象,达到增强真实对象功能的目的

实现方式:

方式一:静态代理:有一个类文件描述代理模式

方式二:动态代理:在内存中形成代理类

动态代理实现步骤:
  1. 代理对象和真实对象实现相同的接口
  2. 代理对象 = public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h);`
  3. 使用代理对象调用方法method.invoke("传入真实对象","参数");
  4. 增加方法
 //2.获取代理对象,调用Proxy类中的newProxyInstance()方法需要传入三个参数
        /**
         * 三个参数:
         *        1. 类加载器:真实对象.getClass().getClassLoader()
         *        2. 接口数组:真实对象.getClass().getInterfaces()
         *        3. 处理器:new InvocationHandler()
         */
        computer sell_Proxy = (computer) Proxy.newProxyInstance(realObject.getClass().getClassLoader(),
                realObject.getClass().getInterfaces(), new InvocationHandler() {

                    /**
                     * 代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法的执行
                     * @param proxy   代理对象
                     * @param method  代理对象调用的方法,被封装成的对象
                     * @param args     代理对象调用的方法时,传递的实际参数
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("invoke是否被调用了");
                        
                        return null;
                    }
                });

动态代理实现:

接口:

public interface computer {
    public String sell(double money);
}

真实对象类:

public class RealObject implements computer{
    @Override
    public String sell(double money) {
        return "卖出的电脑"+money+"钱";
    }
}

获取代理对象并调用方法:

public class ProxyObject {
    public static void main(String[] args) {
        // 实现动态代理步骤
        //1.代理对象和真实对象实现相同接口

        // 创建真实现对象
        RealObject realObject = new RealObject();

        //2.获取代理对象,调用Proxy类中的newProxyInstance()方法需要传入三个参数
        /**
         * 三个参数:
         *        1. 类加载器:真实对象.getClass().getClassLoader()
         *        2. 接口数组:真实对象.getClass().getInterfaces()
         *        3. 处理器:new InvocationHandler()
         */
        computer sell_Proxy = (computer) Proxy.newProxyInstance(realObject.getClass().getClassLoader(),
                realObject.getClass().getInterfaces(), new InvocationHandler() {

                    /**
                     * 代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法的执行
                     * @param proxy   代理对象
                     * @param method  代理对象调用的方法,被封装成的对象
                     * @param args     代理对象调用的方法时,传递的实际参数
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("invoke是否被调用了");
                        
                        return null;
                    }
                });

        // 动态代理的特点是:调用接口中的每一个方法都会触发invoke方法的执行
        String sell = sell_Proxy.sell(8000);
        System.out.printf("sell"+sell);
    }
}

动态代理增强功能方式:

  1. 增加参数列表
  2. 增加返回值类型
  3. 增加方法体执行逻辑
public class ProxyObject {
    public static void main(String[] args) {
        // 实现动态代理步骤
        //1.代理对象和真实对象实现相同接口

        // 创建真实现对象
        RealObject realObject = new RealObject();

        //2.获取代理对象,调用Proxy类中的newProxyInstance()方法需要传入三个参数
        /**
         * 三个参数:
         *        1. 类加载器:真实对象.getClass().getClassLoader()
         *        2. 接口数组:真实对象.getClass().getInterfaces()
         *        3. 处理器:new InvocationHandler()
         */
        computer sell_Proxy = (computer) Proxy.newProxyInstance(realObject.getClass().getClassLoader(),
                realObject.getClass().getInterfaces(), new InvocationHandler() {

                    /**
                     * 代理逻辑编写的方法:代理对象调用的所有方法都会触发该方法的执行
                     * @param proxy   代理对象
                     * @param method  代理对象调用的方法,被封装成的对象
                     * @param args     代理对象调用的方法时,传递的实际参数
                     * @return
                     * @throws Throwable
                     */
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        /**
                         * 对动态代理功能的增强
                         *     1.对参数进行参数列表增强
                         *     2.对返回值进行增强
                         *     3.对方法体进行增强
                         */
//                        System.out.println("invoke是否被调用了");
//                        Object invoke = method.invoke(realObject, args);
//                        return invoke;


                        // 获取方法名,判断是sell,如果是才进行增强
                        if (method.getName().equals("sell")){
                            // 3.对象方体进行增强
                            System.out.println("您好买电脑不?");
                            // 1.对参数进行列表增强
                            double money = (double) args[0];
                            String invoke = (String) method.invoke(realObject, money);
                            System.out.println("免费送货到家!");
                            // 2.对象返回值进行增强
                            return invoke+"送给您一些礼品";
                        }else {
                            String invoke = (String) method.invoke(realObject, args);
                            return invoke;
                        }
                    }
                });

        // 动态代理的特点是:调用接口中的每一个方法都会触发invoke方法的执行
        String sell = sell_Proxy.sell(8000);
        System.out.printf("sell"+sell);
    }
}

Listener监听器

概念:web的三大组件之一

事件监听机制:

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

作用:监听ServletContext对象的创建和销毁

ServletContextListener监听器是对ServletContext的创建和销毁进行监听的,

在服务器启动时,创建ServletContext对象,同时也创建了ServletContexListener对象,并且调用了ServletContexListener中的contextInitialzed方法用于加载一些资源文件

在服务器正常关闭时,ServletContext被销毁,同时执行ServletContexListener中的contextDestroyed方法一般用于释放资源

方法:
void contextDestroyed(ServletContextEvent sce):`servletContext`对象被销毁之前会调用该方法【一般用于释放一些资源】

void contextInitialzed(ServletContextEven sce):`ServletContext`对象创建后会调用该方法【一般用于加载一些资源】

监听器的使用步骤:

  1. 定义一个类,实现ServletContexListener接口

  2. 重写方法

  3. 配置

    1. web.xml方式

      @WebListener//说明该类是监听器,用于监听ServletListener的创建销毁 
      
      
    2. 注解方法

    <listener>
            <listener-class>com.example.javawebServletFilter.listener_.ServletListener</listener-class>
        </listener>
    
    

案例:

@WebListener//说明该类是监听器,用于监听ServletListener的创建销毁 
public class ServletListener implements ServletContextListener {
    /**
     * 监听ServletContext对象的创建,自动的调用contextInitialized方法
     * 用于加载资源文件
     * @param sce
     */
    @Override
    public void contextInitialized(ServletContextEvent sce) {
        System.out.println("ServletContext对象被创建了,用于加载资源 ");
    }

    /**
     * 用于监听ServletContext对象的销毁
     * 用于释放一些资源文件
     * @param sce
     */
    @Override
    public void contextDestroyed(ServletContextEvent sce) {
        System.out.println("ServletContext对象被销毁了,用于释放资源");
    }
}

<listener>
        <listener-class>com.example.javawebServletFilter.listener_.ServletListener</listener-class>
    </listener>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值