过滤器

02.过滤器介绍与应用场景【理解】
导入

**疑问:**浏览器提交请求后会直接先到目标资源处理请求与响应吗?

答:请求先到过滤器再到目标资源,还会回到过滤器,最终给到浏览器

目标

掌握过滤器的作用

过滤器适合解决什么问题

过滤器介绍

过滤器的作用:用于拦截请求与响应

[外链图片转存失败(img-3AklInac-1566639913019)(assets/)]

应用场景介绍
  1. 解决post提交中文乱码应用场景

    [外链图片转存失败(img-NvshJ8B2-1566639913020)(assets/)]

  2. 登录权限控制

    [外链图片转存失败(img-tJs0lYFq-1566639913021)(assets/)]

小结
  1. 过滤器的作用?

    拦截请求与响应
    
  2. 过滤器是解决什么问题的?

    解决代码冗余,如果每个资源都需要处理同一个操作,那么这个处理操作就可以放在过滤器中集中处理
    
03.开发方式1-手动XML配置实现过滤器【了解】
目标

掌握手动xml配置实现过滤器

实现步骤
1. 创建一个目标资源Demo1Servlet处理请求与响应
2. 创建一个类Demo1Filter并实现Filter接口,重写拦截请求与响应的方法doFilter
3. 在web.xml中配置过滤器拦截目标资源url(因为拦截资源,每个资源都是通过url访问的)
4. 部署项目测试运行,观察是否进行拦截请求与响应
代码位置

[外链图片转存失败(img-9bfBr5Ph-1566639913021)(assets/)] 

Servlet代码
package com.itheima.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(name = "_01Demo1Servlet", urlPatterns = "/_01Demo1Servlet")
public class _01Demo1Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //输出一句信息
        System.out.println("执行了_01Demo1Servlet代码");
    }
}
过滤器代码
package com.itheima.filter;

import javax.servlet.*;
import java.io.IOException;

public class _01Demo1Filter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

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

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

        //2.放行,给目标资源去执行【有这句代码就放行,没有就不放行,不放行导致目标资源不执行】
        filterChain.doFilter(request,response);//本质就是转发跳转到目标资源

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

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

    <!--目标:建立Demo1Filter拦截Demo1Servlet
        1.定义过滤器全名,使用<filter>标签
        2.给这个过滤器配置拦截的url,(url就是Demo1Servlet的访问路径),使用<filter-mapping>标签
    -->
    <filter>
        <filter-name>_01Demo1Filter</filter-name>
        <filter-class>com.itheima.filter._01Demo1Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>_01Demo1Filter</filter-name>
        <url-pattern>/_01Demo1Servlet</url-pattern>
    </filter-mapping>
</web-app>
访问地址
http://localhost:8080/day29_01_filter_war_exploded/_01Demo1Servlet
效果

[外链图片转存失败(img-6yOp6Gis-1566639913022)(assets/)]

小结
  1. 实现过滤器的接口是什么?

    javax.servlet.Filter
    
  2. 过滤器拦截请求与响应的方法是什么?

    doFilter方法
    
04.开发方式2-模板向导注解实现过滤器【推荐】
目标

使用模板向导和注解配置路径实现过滤器

实现步骤
1. 创建一个Demo2Servlet处理请求与响应
2. 根据模板向导创建过滤器,重写doFilter方法进行拦截请求与响应
3. 设置注解配置拦截的资源地址

[外链图片转存失败(img-Bi03RK6Q-1566639913023)(assets/)] 

过滤器代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

/*
* @WebFilter 用于配置过滤器的注解
* filterName = "_02Demo2Filter", 功能与xml中<filter-name>标签功能一样,可有可无
* urlPatterns = "/_02Demo1Servlet",功能与xml中<url-pattern>标签功能一样,必须有参数
* */
@WebFilter(filterName = "_02Demo2Filter",urlPatterns = "/_02Demo2Servlet")
public class _02Demo2Filter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_02Demo2Filter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}
Servlet资源代码
package com.itheima.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(name = "_02Demo2Servlet", urlPatterns = "/_02Demo2Servlet")
public class _02Demo2Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //输出一句信息
        System.out.println("执行了_02Demo2Servlet代码");
    }
}

运行效果

方法地址

http://localhost:8080/day29_01_filter_war_exploded/_02Demo2Servlet

效果

[外链图片转存失败(img-xdPA6OPi-1566639913024)(assets/)]

小结
  • 注解实现代码是什么?

    @WebFilter(fileName="过滤器名字",urlPatterns="拦截的资源路径")
    
  • 注解配置与xml配置出现冲突的时候,谁的优先级高?

    xml优先级高于注解
    
05.过滤器执行流程【理解】
执行流程(时序图)

[外链图片转存失败(img-kC4PYH3m-1566639913025)(assets/)]

06.过滤器生命周期【理解】
目标

掌握过滤器对象什么时候创建,什么时候销毁和3个生命周期方法

实现步骤
1. 创建Demo3Servlet资源
2. 创建LifeCycleFilter拦截请求与响应,重写3个方法(init方法, doFilter方法, destroy方法)
3. 观察运行
过滤器代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;


/*
* 过滤器生命周期需要解决的面试题:
* 1.过滤器什么时候创建?
*   比servlet早创建,服务器启动时候就创建了
*
* 2.一个过滤器类全局创建几个对象?
*   init方法只被调用一次,说明全局只创建一个过滤器对象,全局唯一,节省内存
* */
@WebFilter(filterName = "_03LifeCycleFilter",urlPatterns = "/_03Demo3Servlet")
public class _03LifeCycleFilter implements Filter {
    //init初始化方法,过滤器对象创建的时候调用
    public void init(FilterConfig config) throws ServletException {
        System.out.println("==调用了_03LifeCycleFilter的init方法==");
    }

    //doFilter拦截请求与响应的方法,每次访问拦截资源url就会调用
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        System.out.println("==调用了_03LifeCycleFilter的doFilter方法==");
        //这里没有放行,不会去到目标资源,最后没有任何数据响应给浏览器
    }

    //destroy销毁方法,当前服务器关闭之前调用
    public void destroy() {
        System.out.println("==调用了_03LifeCycleFilter的destroy方法==");
    }

}
运行效果

访问地址

http://localhost:8080/day29_01_filter_war_exploded/_03Demo3Servlet

效果

[外链图片转存失败(img-tpjscWnP-1566639913025)(assets/)]

小结
  • 过滤器对象什么时候创建?对象全局唯一吗?

    服务器启动时创建的,全局唯一
    
  • 过滤器对象什么时候销毁?

    服务器关闭的时候
    
07.过滤器拦截路径的配置【应用】
思考
  • 一个过滤器只能拦截一个资源吗?如何做到一个过滤器拦截多个资源?

    需要学习拦截路径的配置
    
目标

过滤器通过拦截路径配置可以拦截一个或多个资源

过滤路径映射配置介绍
拦截路径配置方式有2种:
第一种:精确匹配,配置的路径与资源访问的路径要一模一样就可以拦截
	   任何资源路径都是可以的
	   urlPatterns = "/img/3.jpg",
	   urlPatterns = "/index.jsp"
第二种:模糊匹配,只能使用一个“*”号通配符操作,代表0~多个字符
	   1.前缀匹配,匹配开头一致的
	   	要求:以“/”开头,以"/*"结尾
	   	例子:
	   		/abc/*,拦截资源访问路径以/abc开头的所有资源
	   		/*,拦截所有资源
	   2.后缀匹配,匹配结尾一致的
	   	要求:以“*”开头,以“.扩展名”方式结尾
	   	例子:
	   		*.action,拦截资源访问路径以.action为结尾的所有资源
	   		*.do,拦截资源访问路径以.do为结尾的所有资源
注意
1.urlPatterns = "/abc/*/abc",这是精确匹配
2.在过滤器里面可以使用“/”或“/*”,但是在Servlet里面不可以,否则静态资源无法访问
过滤器代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;


/*
* 路径的配置通过urlPatterns属性完成的,这个属性有2中写法
* 方式1:拦截一个路径,urlPatterns = "/url"
* 方式2:拦截多个路径,urlPatterns = {"/url1","/url2",...}
* */
@WebFilter(filterName = "_04URLFilter",urlPatterns = {
        //精确匹配
        "/img/6.jpg","/index.jsp","/index.html",
        //模糊匹配
        "/abc/*","*.do"
})
public class _04URLFilter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_02Demo2Filter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}
小结
  1. 过滤器的映射路径配置方式有几种?

2种,精确与模糊




2. 常用的路径配置如下,分别代表什么意思?

| 路径     | 含义                    |
| -------- | ----------------------- |
| /admin/* | 拦截admin目录下所有资源 |
| /*       | 拦截项目内所有资源      |

#### 08.拦截方式1—默认不拦截转发跳转资源【应用】

##### 疑问

* request请求转发跳转的目标资源,过滤器默认会不会拦截目标资源的请求与响应?

不会


##### 目标

理解过滤器默认不拦截请求转发跳转的目标资源

##### 过滤器默认不拦截请求转发访问的资源演示,实现步骤

1. 创建2个Servlet,OneServlet与TwoServlet
2. 在OneServlet实现转发跳转到TwoServlet
3. 创建过滤器拦截TwoServlet资源请求与响应
4. 观察运行,不可以拦截

![\[外链图片转存失败(img-p1a4CHiz-1566639913026)(assets/)\]&nbsp;](https://img-blog.csdnimg.cn/20190824175023798.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L0J1bGlkX0V2b2x0bw==,size_16,color_FFFFFF,t_70)

##### OneServlet代码

```java
package com.itheima.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(name = "_05OneServlet", urlPatterns = "/_05OneServlet")
public class _05OneServlet extends HttpServlet {
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doGet(request, response);
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      //转发跳转到TwoServlet
      request.getRequestDispatcher("/_05TwoServlet").forward(request,response);
  }
}
TwoServlet代码
package com.itheima.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(name = "_05TwoServlet", urlPatterns = "/_05TwoServlet")
public class _05TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //输出一句信息
        System.out.println("来到了TwoServlet");
    }
}
过滤器代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;


@WebFilter(filterName = "_05DemoFilter",urlPatterns = "/_05TwoServlet")
public class _05DemoFilter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_05DemoFilter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}

效果
http://localhost:8080/day29_01_filter_war_exploded/_05OneServlet

[外链图片转存失败(img-VpwyHbJL-1566639913026)(assets/)]

小结
  • 过滤器默认可以拦截请求转发访问的目标资源请求与响应吗?

    不可以
    
09.拦截方式2—修改拦截方式拦截转发资源【应用】
疑问
  • 过滤器默认不拦截request请求转发跳转的目标资源,能不能改变呢?

    可以改变,使过滤器拦截请求转发的目标资源,需要学习拦截方式

拦截方式介绍

拦截方式是指过滤器根据浏览器访问的资源方式的不同进行不同的拦截。

浏览器访问资源的方式

第一种:浏览器直接url访问目标资源(重定向也属于直接url访问资源)

第二种:浏览器访问一个资源服务器内部请求转发跳转到另一个目标资源

拦截方式就是根据不同访问资源的方式进行不同的拦截,默认过滤器只会拦截第一种直接url访问资源

拦截方式类型
类型介绍
REQUEST默认拦截方式,过滤器只拦截浏览器直接url访问目标资源的请求与响应
FORWARD过滤器只拦截服务器内部请求转发跳转的目标资源的请求与响应
注解方式修改拦截方式的语法
注解属性说明
dispatcherTypes = {DispatcherType.REQUEST}设置采用默认拦截方式,拦截浏览器直接url访问的资源请求与响应
dispatcherTypes = {DispatcherType.FORWARD}设置采用请求转发拦截方式,注意,如果只配置这种方式,默认方式直接url访问资源将无效不能拦截
dispatcherTypes = {DispatcherType.REQUEST,
DispatcherType.FORWARD}
设置采用直接url与请求转发2种拦截方式
扩展web.xml配置过滤器修改拦截方式设置

[外链图片转存失败(img-U5tpau4O-1566639913027)(assets/)]

过滤器实现拦截请求转发访问和直接url访问的资源演示,实现步骤
  1. 创建2个Servlet,OneServlet与TwoServlet
  2. 在OneServlet实现转发跳转到TwoServlet
  3. 创建过滤器拦截TwoServlet资源请求与响应
  4. 观察运行,可以拦截
代码位置

[外链图片转存失败(img-8lnxZnKv-1566639913027)(assets/)] 

OneServlet
package com.itheima.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(name = "_06OneServlet", urlPatterns = "/_06OneServlet")
public class _06OneServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //转发跳转到TwoServlet
        request.getRequestDispatcher("/_06TwoServlet").forward(request,response);
    }
}

TwoServlet
package com.itheima.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(name = "_06TwoServlet", urlPatterns = "/_06TwoServlet")
public class _06TwoServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //输出一句信息
        System.out.println("来到了TwoServlet");
    }
}

过滤器代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;


@WebFilter(filterName = "_06DemoFilter",urlPatterns = "/_06TwoServlet",
        /*配置拦截方式,拦截直接url访问和间接url访问(转发)*/
        dispatcherTypes = {DispatcherType.REQUEST,DispatcherType.FORWARD}
)
public class _06DemoFilter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_05DemoFilter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}

小结
  • 过滤器拦截方式常用有几种?分别是什么?

2种, 直接url访问REQUEST,间接url访问FORWARD




#### 10.过滤器链介绍与实现【应用】

##### 疑问

* 上面的演示,都是一个资源只被一个过滤器拦截,那么一个资源可以被多个过滤器进行拦截请求与响应吗?

可以,这就是过滤器链




##### 过滤器链介绍

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

##### 实现过滤器链的步骤

1. 创建Demo4Servlet资源
2. 创建Chain1Filter和Chain2Filter2个过滤器并都拦截Demo4Servlet资源
3. 运行观察2个过滤器拦截一个资源的效果

##### Demo4Servlet资源代码

```java
package com.itheima.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(name = "_07Demo4Servlet", urlPatterns = "/_07Demo4Servlet")
public class _07Demo4Servlet extends HttpServlet {
  protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
      doGet(request, response);
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

      //输出一句信息
      System.out.println("执行了_07Demo4Servlet代码");
  }
}
Chain1Filter代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "_07Chain1Filter",urlPatterns = "/_07Demo4Servlet")
public class _07Chain1Filter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_07Chain1Filter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}
Chain2Filter代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "_07Chain2Filter",urlPatterns = "/_07Demo4Servlet")
public class _07Chain2Filter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_07Chain2Filter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}
运行效果

访问地址

http://localhost:8080/day29_01_filter_war_exploded/_07Demo4Servlet

[外链图片转存失败(img-s7Z3BJPu-1566639913028)(assets/)]

小结
  • 什么是过滤器链?

    一个资源同时被多个过滤器拦截
    
11.过滤器链执行顺序分析与修改【理解】
疑问
  • 根据上面案例效果发现先执行Chain1Filter过滤器拦截,为什么会这样?

    需要分析过滤器链执行的顺序

执行顺序分析

[外链图片转存失败(img-jo63fXVq-1566639913028)(assets/)]

案例使用web.xml修改过滤器运行顺序,先运行Chain2Filter,再运行Chain1Filter
代码位置

[外链图片转存失败(img-CoznTXIX-1566639913028)(assets/)] 

Demo4Servlet
package com.itheima.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(name = "_08Demo4Servlet", urlPatterns = "/_08Demo4Servlet")
public class _08Demo4Servlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //输出一句信息
        System.out.println("执行了_08Demo4Servlet代码");
    }
}
Chain1Filter
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "_08Chain1Filter",urlPatterns = "/_08Demo4Servlet")
public class _08Chain1Filter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_08Chain1Filter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}
Chain2Filter
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(filterName = "_08Chain2Filter",urlPatterns = "/_08Demo4Servlet")
public class _08Chain2Filter implements Filter {
    public void destroy() {
    }

    //重写拦截请求与响应的方法
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        //1.拦截请求
        System.out.println("==执行了_08Chain2Filter拦截请求的代码==");

        //2.放行,给目标资源去执行
        filterChain.doFilter(request,response);

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

    public void init(FilterConfig config) throws ServletException {

    }

}
web.xml配置
<!--目标:配置过滤器执行顺序,先执行Chain2Filter,后执行Chain1Filter-->
    <filter>
        <filter-name>_08Chain2Filter</filter-name>
        <filter-class>com.itheima.filter._08Chain2Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>_08Chain2Filter</filter-name>
        <url-pattern>/_08Demo4Servlet</url-pattern>
    </filter-mapping>

    <filter>
        <filter-name>_08Chain1Filter</filter-name>
        <filter-class>com.itheima.filter._08Chain1Filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>_08Chain1Filter</filter-name>
        <url-pattern>/_08Demo4Servlet</url-pattern>
    </filter-mapping>
运行效果

访问地址

http://localhost:8080/day29_01_filter_war_exploded/_08Demo4Servlet

[外链图片转存失败(img-h4BiH3Ll-1566639913029)(assets/)]

12.案例1-解决全站乱码【应用】
需求

解决访问项目任何资源请求与响应传输中文乱码问题

分析

项目应用程序乱码的地方:

  1. post提交中文请求
  2. response输出中文数据
实现步骤
  1. 准备一个表单数据提交post中文请求
  2. 新建一个EncodingServlet处理请求接收中文数据并使用response输出
  3. 创建一个过滤器EncodingFilter拦截所有资源解决全站乱码
Form.jsp页面
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
</head>
<body>
<form action="encoding" method="post">
    <input type="text" name="name"/>
    <input type="submit" value="提交"/>
</form>
</body>
</html>
EncodingServlet代码
package com.itheima.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(name = "_09EncodingServlet", urlPatterns = "/encoding")
public class _09EncodingServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //目标:接收数据并输出数据
        //1.获取post提交中文的数据
        String name = request.getParameter("name");

        //2.控制台打印接收的数据
        System.out.println(name);

        //3.输出中文数据到浏览器'
        response.getWriter().write(name);
    }
}
EncodingFilter代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/*
* 目标:拦截所有资源“/*”, 处理乱码
* */
@WebFilter(filterName = "_09EncodingFilter",urlPatterns = "/*")
public class _09EncodingFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.将req,resp父接口转换为子接口
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //2.处理post提交中文乱码
        //获取提交数据的方法类型
        String method = request.getMethod();

        //判断提交数据访问为post请求才处理乱码
        if("post".equalsIgnoreCase(method)){
            request.setCharacterEncoding("utf8");
        }


        //3.处理response输出中文乱码
        response.setContentType("text/html;charset=utf8");

        //4.放行
        chain.doFilter(request, response);

    }

    public void init(FilterConfig config) throws ServletException {

    }

}
没有过滤器效果

控制台打印

[外链图片转存失败(img-TlAwObHm-1566639913029)(assets/)]

浏览器输出

[外链图片转存失败(img-UC52HM35-1566639913030)(assets/)]

有过滤器效果

控制台打印

[外链图片转存失败(img-qwwptLZ3-1566639913031)(assets/)]

浏览器输出

[外链图片转存失败(img-QKAt5t8W-1566639913031)(assets/)]

小结
  • 过滤器如何可以拦截所有资源?

    urlPatterns="/*"

13.案例2-登录权限控制1-环境搭建与登录功能【理解】
需求

[外链图片转存失败(img-7Ao98Vfr-1566639913032)(assets/)]

实现分析
  1. 创建一个项目
  2. 导入页面素材(“资料\原型”)
  3. 实现登录
搭建环境结构

[外链图片转存失败(img-1X7hP7w7-1566639913033)(assets/)] 

LoginServlet代码
package com.itheima.web;

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(name = "LoginServlet", urlPatterns = "/login")
public class LoginServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        /*目标:模拟处理登录功能*/

        //1.获取用户名与密码
        String user = request.getParameter("user");
        String password = request.getParameter("password");

        //2.判断用户名必须为admin,密码必须为123,代表登录成功
        if("admin".equals(user) && "123".equals(password)){
            //登录成功,将用户名写入session,以后用于判断是否登登录的依据
            request.getSession().setAttribute("loginUser",user);

            //登录成功后跳转/list.jsp
            response.sendRedirect(request.getContextPath()+"/list.jsp");

        }else {
            //3.校验失败,登录失败
            //将错误信息存储到请求域中
            request.setAttribute("errorMsg","用户名或密码错误");
            //转发跳转到登录页面,使用el显示错误信息
            request.getRequestDispatcher("/login.jsp").forward(request,response);
        }
    }
}

修改login.jsp页面显示的错误消息

[外链图片转存失败(img-1rm8uF3k-1566639913034)(assets/]

运行效果

访问地址

http://localhost:8080/day29_02_loginControl_war_exploded/login.jsp

登录失败效果

[外链图片转存失败(img-tzO1qvCH-1566639913035)(assets/)]

登录成功效果

[外链图片转存失败(img-CvzEMtSJ-1566639913035)(assets/)]

14.案例2-登录权限控制2-实现登录控制【应用】
目标

使用过滤器实现登录权限控制

  • 我们的目标是admin目录下的资源必须登录以后才可以访问,那就需要在admin目录的每个资源里面都要判断是否用户登录了,如果没有登录不能访问,这样操作是否麻烦?有没有更好的操作?

    使用过滤器

过滤器代码
package com.itheima.filter;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/*目标:拦截admin目录下资源的所有访问*/
@WebFilter(filterName = "LoginFilter",urlPatterns = "/admin/*")
public class LoginFilter implements Filter {
    public void destroy() {
    }

    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
        //1.将父接口转换为子接口
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) resp;

        //2.获取session中的登录数据“loginUser”
        String loginUser = (String) request.getSession().getAttribute("loginUser");

        //3.判断登录数据是否有效,有效放行
        if(loginUser!=null){

            //放行
            chain.doFilter(request, response);

        }else {

            //4.无效返回登录页面
            response.sendRedirect(request.getContextPath()+"/login.jsp");
        }

    }

    public void init(FilterConfig config) throws ServletException {

    }

}
小结
  • 过滤器如何拦截浏览器访问admin目录下的所有资源?

    拦截路径为:“/admin/*”

  • 如何知道用户是否登录了?

    判断session中是否有登录数据,有代表登录了,否则代码没有登录

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值