web组件之Filter

1.Filter

[1] Filter简介

  • Filter是JavaWeb中三大组件之一Servlet、Filter、Listener

  • Filter直译过来就叫过滤器

  • Filter是用来过滤请求的

  • Filter在JavaEE中实际上就是一个接口

  • Filter的作用

1 Filter可以在请求到达目标资源(JSP、Servlet、Html、CSS)之前来拦截请求

2 Filter可以放行请求,使请求到达目标资源

3 Filter可以在响应到达浏览器之前做一些处理

[2] Filter的HelloWorld

1.创建一个类并实现Filter接口

2.在web.xml配置文件中注册Filter

<filter>

<filter-name>别名</filter-name>

<filter-class>全类名</filter-class>

可以添加初始化参数标签

</filter>

<filter-mapping>

<filter-name>别名</filter-name>

<url-pattern>要拦截的地址</url-pattern>

</filter-mapping>

[3] Filter的生命周期

Filter的对象从被创建到被销毁的过程

生命周期方法:

  • 构造器:

  • Filter的构造器在服务器一启动时就被调用,也就是Filter的实例在服务器启动时创建。

  • init()方法:

  • init在构造器调用之后马上被调用,用来做一些初始化操作。

  • 服务器在调用init方法时,会传过来一个FilterConfig对象,该对象的作用和ServletConfig差不多

  • 可以获取到Filter的别名

  • 可以获取到当前Filter的初始化参数

  • 可以获取到ServletContext对象

  • doFilter()方法:

  • doFilter方法在Filter每次拦截请求时都会调用,是Filter中的主要方法

  • 服务器在调用doFilter方法时会传来这么几个参数:

  • ServletRequest

  • 作用和Servlet中的一样,封装请求报文

  • ServletResponse

  • 作用和Servlet中的一样,封装了响应报文

  • FilterChain

  • 对象就是用来放行请求:

chain.doFilter(request,response);

  • destroy()方法:

  • destroy在项目卸载之前调用,用来在Filtert对象销毁之前做一些收尾工作

url-pattern的规则:

  • url-pattern用来指定需要Filter拦截的请求的地址

  • 精确匹配:

  • 访问地址和url-pattern的地址要一模一样,Filter才会起作用

  • 例子 : /1.jsp

  • 只有访问我们项目根目录下的1.jsp时才会调用Filter

  • 在一个filter-mapping可以写多个url-pattern

  • 路径匹配

  • 访问的地址是在url-pattern的地址所配置的路径之下,Filter才会起作用。

  • 例子 : /hello/*

  • 只要访问项目根目录下的hello下的资源就会调用Filter

  • 例子 : /*

  • /* 会拦截发送到当前项目的所有请求

  • 后缀匹配:

  • 访问的路径和url-pattern配置的后缀名一致时,Filter才会起作用

  • 例子 : *.abc

  • 只要访问以abc结尾的路径时,才会调用Filter

  • 例子:*.jsp

  • 会拦截所有以jsp为后缀的请求

  • 我们所配置url-pattern必须符合以上规则。

  • Servlet的url-pattern同样适用以上规则,url-pattern中的/表示:项目根目录。!!!

[4] Filter的执行顺序

  • 我们可以为一个目标资源设置多个Filter,这样多个Filter就会组成一个Filter链的结构,

如果我们在Filter中去调用chain.doFilter()如果Filter之后还有Filter,就相当于调用了下一个Filter的doFilter方法

如果Filter之后没有其他的Filter了,调用chain.doFilter相当于调用了目标资源的service()方法

如果Filter的顺序是A B C , 则拦截请求时的顺序就是A B C ,而响应回到浏览器时的拦截顺序是 C B A

  • 多个Filter的执行顺序是由谁决定的呢?

Filter的执行顺序,web.xml配置文件中filter-mapping的上下顺序执行,我们可以通过调整filter-mapping的顺序,来调整Filter的执行顺序

注意filter-mapping不能在其对应的filter标签的上边

拦截Servlet的两种方式:

<servlet>

<servlet-name>HelloServlet</servlet-name>

<servlet-class>com.atguigu.servlet.HelloServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>HelloServlet</servlet-name>

<url-pattern>/HelloServlet</url-pattern>

</servlet-mapping>
  • 当使用一个Filter去拦截一个Servlet时,可以将Filter的url-pattern和Servleturl-pattern设置成一样的即可
<filter-mapping>

<filter-name>CFilter</filter-name>

<url-pattern>/HelloServlet</url-pattern>

</filter-mapping>
  • 也可以使用在filter-mapping中设置一个servlet-name标签,将该标签设置为和要拦截的Servlet的name一致

CFilter

HelloServlet

禁止浏览器缓存所有动态页面的过滤器:

有 3 个 HTTP 响应头字段都可以禁止浏览器缓存当前页面,它们在 Servlet 中的示例代码如下:

response.setDateHeader("Expires",-1);

response.setHeader("Cache-Control","no-cache");

response.setHeader("Pragma","no-cache");

并不是所有的浏览器都能完全支持上面的三个响应头,因此最好是同时使用上面的三个响应头。

Expires数据头:值为GMT时间值,为-1指浏览器不要缓存页面

Cache-Control响应头有两个常用值:

no-cache指浏览器不要缓存当前页面。

max-age:xxx指浏览器缓存页面xxx秒。

[5] 登录练习

  • 准备两个页面

login.jsp

success.jsp

  • 创建两个Filter

UsernameFilter –> 检查用户名是否正确(是否为admin)

  • 如果正确,则放行请求

  • 如果错误,设置一个错误消息,然后转发到login.jsp重新输入

PasswordFilter –> 检查密码是否正确 (是否为123123)

  • 如果正确,则放行请求

  • 如果错误,设置一个错误消息,然后转发到login.jsp重新输入

[6] dispatcher

  • Filter默认只会拦截直接发送到目标资源的请求,而向转发到目标资源的请求他是不会拦截的。

  • 如果希望Filter可以拦截转发到目标资源的请求,可以在filter-mapping中的dispatcher标签中配置

<dispatcher>REQUEST</dispatcher>

<dispatcher>FORWARD</dispatcher>

<dispatcher>INCLUDE</dispatcher>

<dispatcher>ERROR</dispatcher>
  • dispatcher有四个可选值:dispatcher可以多选。

REQUEST

  • 指只会拦截直接发送到目标资源的请求,默认值,如果被配置dispatcher则默认就是该值

  • 一旦指定了dispatcher则以指定的属性为准

FORWARD

  • 会拦截所有通过转发来访问目标资源的请求。

INCLUDE

  • 会拦截所有通过动态包含访问目标资源的请求。

ERROR

  • 会拦截在web.xml配置文件中的错误页面

404

/2.jsp

[7] HttpFilter

public abstract class HttpFilter implements Filter {

private FilterConfig filterConfig;

@Override

public void init(FilterConfig filterConfig) throws ServletException {

this.filterConfig = filterConfig;

this.init();

}

public void init()throws ServletException{

}

public abstract void doFilter(HttpServletRequest request, HttpServletResponse response,

FilterChain chain) throws IOException, ServletException;

@Override

public void doFilter(ServletRequest request, ServletResponse response,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest req = (HttpServletRequest) request;

HttpServletResponse resp = (HttpServletResponse) response;

this.doFilter(req, resp, chain);

}


@Override

public void destroy() {


}


}
  • 我们一不小心讲了一种设计模式

  • 装饰者模式

  • 装饰者模式指的就是通过一个包装类去包装原有的对象,从而对原有对象的方法进行修改。

  • 当我们需要扩展某个对象的某个功能时,但是又不能去修改该对象的源代码,还有就是不需要永久修改该方法,

这时我们就可以使用装饰者模式,创建一个包装类,包装要扩展或修改的对象。

  • 装饰者模式使用步骤:

1.创建一个包装类,包装类要求要和被包装类有相同的接口或直接或者间接父类。

2.包装类中要有一个被包装类的引用

3.在包装类中创建一个有参数的构造器,

并通过构造器将被包装类的实例传进来。

不能提供无参构造器

4.不需要修改方法可以直接通过被包装对象间接实现。

5.修改我们需要扩展或修改的方法。

6.我们在使用包装类时,需要用包装类将被包装类包装。(即包装类在实例化的时候,需要一个被包装类的对象,并将其作为包装类的构造器的参数传递进来。)

当某个对象的方法不适应业务需求时,通常有2种方式可以对方法进行增强:

编写子类,覆盖需增强的方法

使用Decorator设计模式对方法进行增强

疑问:在实际应用中遇到需增强对象的方法时,到底选用哪种方式呢?

没有具体的定式,不过有一种情况下,必须使用Decorator设计模式:即被增强的对象,开发人员只能得到它的对象,无法得到它的class文件。

比如request、response对象,开发人员之所以在servlet中能通过sun公司定义的HttpServletRequest\response接口去操作这些对象,是因为Tomcat服务器厂商编写了request、response接口的实现类。web服务器在调用servlet时,会用这些接口的实现类创建出对象,然后传递给servlet程序。

此种情况下,由于开发人员根本不知道服务器厂商编写的request、response接口的实现类是哪个?在程序中只能拿到服务器厂商提供的对象,因此就只能采用Decorator设计模式对这些对象进行增强。

Decorator设计模式的实现

1.首先看需要被增强对象继承了什么接口或父类,编写一个类也去继承这些接口或父类。

2.在类中定义一个变量,变量类型即需增强对象的类型。

3.在类中定义一个构造函数,接收需增强的对象。

4.覆盖需增强的方法,编写增强的代码。

Servlet API 中提供了一个request对象的Decorator设计模式的默认实现类HttpServletRequestWrapper , (HttpServletRequestWrapper 类实现了request 接口中的所有方法,但这些方法的内部实现都是仅仅调用了一下所包装的的 request 对象的对应方法)以避免用户在对request对象进行增强时需要实现request接口中的所有方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值