JavaWeb day06 过滤器、监听器、Web项目路径

Java Web三大组件
在这里插入图片描述

过滤器

介绍

javaee体系提供一个Filter接口,实现这个接口后可以对所有资源进行拦截,拦截通过后才会达到目标资源执行

在这里插入图片描述

1、开发方式–手动配置xml文件

<filter>、 <filter-name>、<filter-class>、<url-pattern>

<?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">

    <!--
    web.xml配置过滤器要拦截的资源
      1.定义过滤器类全名  <filter>
      2.配置拦截的目标资源路径 <filter-mapping>

      应用场景:以后配置别人开发的jar中过滤器类的时候使用
    -->
    <filter>
        <filter-name>Demo1Filter</filter-name>
        <filter-class>com.itheima._01filter开发方式1_手动XML.Demo1Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>Demo1Filter</filter-name>
        <url-pattern>/DemoServlet1</url-pattern>
    </filter-mapping>
</web-app>

2、开发方式2–注解实现

跟@WebServlet(" ")一样


/**
 * @WebFilter("/Demo2Servlet")
 * 含义: 拦截/Demo2Servlet资源的过滤器注解配置
 * 注解属性1: filterName, 功能与xml中<filter-name>标签功能一致,起别名,可有可无的属性
 * 注解属性2: urlPatterns,这是默认注解值属性,配置拦截路径,支持如下格式:
 *     @WebFilter("/拦截路径")
 *     @WebFilter(urlPatterns={"/拦截路径1","/拦截路径2",...})
 */
@WebFilter("/Demo2Servlet")
public class Demo2Filter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    //拦截请求与响应的方法
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {

        //1.拦截请求
        System.out.println("==执行了Demo2Filter拦截请求的代码==");

        //2.放行
        filterChain.doFilter(request,response);

        //3.拦截响应‘
        System.out.println("==执行了Demo2Filter拦截响应的代码==");
    }

    @Override
    public void destroy() {

    }
}

注意:

没有 filterChain.doFilter(request,response) 默认拦截。

3、执行流程

在这里插入图片描述

4、过滤器生命周期

过滤器的3个方法:

1、初始化方法,init()
2、拦截请求和响应方法 ,doFilter()
3、销毁方法,destroy()

过滤器对象什么时候被创建?

服务器启动时创建,比servlet的创建早,servlet的创建在访问网站的时候创建的。

服务创建过滤器对象创建了几次?

由于init方法只调用1次,所以过滤器对象创建1次,全局唯一,节省内存

什么时候销毁过滤器?

服务器关闭之前

5、过滤器拦截路径的配置

拦截路径配置方式有2种(精确匹配和模糊匹配):

第一种:精确匹配,配置的路径与资源访问的路径要一模一样就可以拦截
urlPatterns = “/img/3.jpg”,
urlPatterns = “/index.jsp”

第二种:模糊匹配,只能使用一个“*”号通配符操作,代表0~多个字符

1.前缀匹配,匹配开头一致的
要求:以“/”开头,以"/*"结尾
例子:
/abc/*,拦截资源访问路径以/abc开头的所有资源
/*,拦截所有资源

2.后缀匹配,匹配结尾一致的
要求:以“*”开头,以“ . 扩展名”方式结尾
例子:
*. action,拦截资源访问路径
. action为结尾的所有资源
*. do,拦截资源访问路径
. do为结尾的所有资源

6、过滤器默认不拦截转发跳转

在这里插入图片描述

过滤器默认类型是REQUEST,默认不拦截转发跳转。

注解方式修改拦截方式的语法

在这里插入图片描述

@WebFilter(urlPatterns = "/Two2Servlet",
        //配置拦截方式: 拦截浏览器直接访问和转发跳转的目标资源
        dispatcherTypes ={DispatcherType.FORWARD,DispatcherType.REQUEST} )
public class Demo4Filter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了Demo4Filter的请求拦截代码==");

        //2.放行:允许访问目标资源了
        filterChain.doFilter(request,response);

        //3.拦截响应
        System.out.println("==执行了Demo4Filter的响应拦截代码==");
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

xml修改拦截方式
在这里插入图片描述

7、过滤器链

同一个资源同时被多个过滤器拦截形成过滤器链,一个过滤器一个过滤器进行串行拦截

过滤器链执行顺序

在这里插入图片描述

1、 使用web.xml的配置方式:哪个配置在前面就先执行哪个
2、使用注解的配置方式:按过滤器类名的字母顺序进行排序,哪个在前面就先执行。

<!--配置过滤器链:先执行Chain2Filter2, 再执行Chain1Filter2
        注意:xml配置过滤器,执行顺序就是配置的顺序
    -->
<filter>
    <filter-name>Chain2Filter2</filter-name>
    <filter-class>com.itheima._09过滤器链使用xml方式修改执行顺序.Chain2Filter2</filter-class>
</filter>
<filter-mapping>
    <filter-name>Chain2Filter2</filter-name>
    <url-pattern>/Demo4Servlet2</url-pattern>
</filter-mapping>

<filter>
    <filter-name>Chain1Filter2</filter-name>
    <filter-class>com.itheima._09过滤器链使用xml方式修改执行顺序.Chain1Filter2</filter-class>
</filter>
<filter-mapping>
    <filter-name>Chain1Filter2</filter-name>
    <url-pattern>/Demo4Servlet2</url-pattern>
</filter-mapping>

先执行Chain2Filter2,再执行Chain1Filter2


解决全站post提交中文乱码

@WebFilter("/*")
public class EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {

        //1.获取请求数据的类型
        //req.getMethod() ServletRequest接口中没有getMethod()方法,子接口HttpServletRequest才有
        //将父接口转换为子接口
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        String method = request.getMethod(); //返回get或post

        //2.如果类型为post处理乱码
        if("post".equalsIgnoreCase(method)){
            request.setCharacterEncoding("utf-8");
        }

        //3.放行
        chain.doFilter(req, resp);
    }

    public void init(FilterConfig config) throws ServletException {

    }

}

注意:

请求乱码过滤器解决,响应乱码JSP解决。
码表过滤器一定要放在最前面运行
推荐使用xml配置过滤器,因为注解的监听器会自动进行排序,浪费内存

监听器

web开发三大组件

​ servlet: 用于处理请求与响应, 响应资源给浏览器

​ filter: 用于拦截请求与响应, 重复操作代码抽取优化

​ listener: 监听器, 监听三大域的变化, 在变化的时候的时间点允许开发人员调用自己业务逻辑

监听器分类
在这里插入图片描述
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">
    <listener>
        <listener-class>com.halulu.listener.ListenerDemo1</listener-class>
    </listener>
</web-app>

注解方式配置监听器

@WebListener
public class ListenerDemo1 implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        System.out.println("监听器创建:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date()));
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        System.out.println("监听器销毁:" + new SimpleDateFormat("yyyy-MM-dd HH-mm-ss").format(new Date()));
    }
}

监听器应用场景

1.加载自定义配置文件数据,spring框架的配置文件就是使用这个监听器进行加载的
2.开启定时器任务运行

java定时器

@WebListener
public class MyServletContextListener2 implements ServletContextListener {
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

        /*
         * 获取到servletContext创建的时间点有什么用?ServletContextListener的作用?
         * 答:我们认为上下文域对象的创建是服务器启动时候最早的时间点,通常可以做如下2个操作:
         *       1.加载自定义配置文件数据,spring框架的配置文件就是使用这个监听器进行加载的
         *       2.开启定时器任务运行
         *              定时器任务:按照指定的时间执行任务
         *              js的定时器语法:setInterval()或setTimeout(),这里我们要学习java的定时器
         * */

        /*
         * java定时器类:Timer
         * 创建语法:new Timer()
         * 设置定时任务语法:
         *   语法1:timer.schedule(TimerTask,long,long);
         *          参数1:TimerTask接口,用于编写任务代码
         *          参数2:long,毫秒数,设置距离第一次任务执行的毫秒数
         *          参数3:long,毫秒数,间隔执行任务的毫秒数
         *   语法2:timer.schedule(TimerTask,Date,long);
         *          参数1:TimerTask接口,用于编写任务代码
         *          参数2:Date,设置距离第一次任务执行的时间
         *          参数3:long,毫秒数,间隔执行任务的毫秒数
         * */
        //1、创建定时器类
        Timer timer = new Timer();
        //2、设置定时器任务(每3秒输出一次hello world)
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                //任务代码
                System.out.println("hello world");
            }
        },0,3000);
    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {

    }
}

ServletContextAttributeListener 介绍
在这里插入图片描述

在这里插入图片描述

@WebListener
public class MyServletContextAttributeListener implements ServletContextAttributeListener {

    //写入数据的监听
    @Override
    public void attributeAdded(ServletContextAttributeEvent sc) {

        //新增属性名获取
        String name = sc.getName();
        //新增属性值获取
        String value = (String) sc.getValue();
        System.out.println("新增属性名:"+name+",属性值:"+value);
    }

    //修改数据的监听
    @Override
    public void attributeReplaced(ServletContextAttributeEvent sc) {
        //修改属性名获取
        String name = sc.getName();
        //修改前属性值获取
        String oldValue = (String) sc.getValue();
        //修改后的属性值获取
        String newValue = (String) sc.getServletContext().getAttribute(name);

        System.out.println("修改属性名:"+name+",修改前属性值:"+oldValue+",修改后属性值:"+newValue);

    }

    //删除数据的监听
    @Override
    public void attributeRemoved(ServletContextAttributeEvent sc) {
        //删除属性名获取
        String name = sc.getName();
        //删除前属性值获取
        String oldValue = (String) sc.getValue();
        System.out.println("删除属性名:"+name+",修改前属性值:"+oldValue);
    }


}

Web项目路径

路径方式1:

相对路径,使用相对路径访问资源
比如请求转发跳转,由于转发跳转是在服务器内部进行的,所以使用相对路径。
相对路径不安全,除了请求转发跳转使用相对路径外,其余使用全路径

路径方式2:

全路径,使用完整资源路径访问资源
浏览器之间的跳转需要使用全路径,使用相对路径不安全
比较重定向跳转
response.sendRedirect(request.getContextPath()+"/DemoServlet");
jsp页面的跳转:
<a href="${pageContext.request.contextPath}/DemoServlet">demo</a>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

halulu.me

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值