JavaWeb-Tomcat阀

前言

Filter的功能之一就是预处理客户请求,而Tomcat阀是对Catalina容器接收到的HTTP请求进行预处理.

过滤器实在Servlet规范中提出来的,因此适用于所有的Servlet容器,而Tomcat阀是Tomcat转悠的,不能用于Tomcat以外的其他Servlet容器.

简介

阀可以加入到3种容器中:<Engine>/<Host><Context>.

所有的阀都实现了org.apache.catalina.Valve,它有如下几个方法:

    public Valve getNext();
    public void setNext(Valve valve);
    public void backgroundProcess();
	public void invoke(Request request, Response response)
        throws IOException, ServletException;
    public boolean isAsyncSupported();

其中最重要的是invoke(),它的官方JavaDoc描述如下:

根据该阀门的要求执行请求处理。

单个Valve可以按指定顺序执行以下操作:

  1. 检查或修改指定的请求和响应的属性。

  2. 检查指定Request的属性,完全生成相应的Response,并将控制权返回给调用者。

  3. 检查指定的请求和响应的属性,包装这两个对象中的一个或两个,以补充其功能,然后将其传递。

  4. 如果未生成相应的Response(并且未返回控件),请通过执行getNext()invoke()来调用管道中的下一个Valve(如果存在):

    getNext().invoke(request, response);
    
  5. 检查但不修改最终响应的属性(该响应是由随后调用的ValveContainer创建的)。

阀门绝对不能做以下任何事情:

  1. 更改已经用于指导此请求的处理控制流程的请求属性(例如,尝试更改标准实施中应从连接到主机或上下文的管道将请求发送到的虚拟主机)。
  2. 创建完成的响应并将此请求和响应传递到管道中的下一个阀门。
  3. 除非与请求完全相关联,否则请消耗与请求相关联的输入流中的字节,除非它完全生成了响应,或者在传递请求之前将其包装。
  4. getNext()invoke()方法返回后,修改Response包含的HTTP标头。
  5. getNext()invoke()方法返回后,对与指定的Response关联的输出流执行任何操作。

属性

<Valve>的基本表示形式是:

<Valve className="实现了Valve接口的类" ...其他属性.../>

这里所列的其他属性根据具体的Valve实现类而定,它定义了哪些成员变量这里就可以对应设置属性,不过都是简单类型,比如字符串或数字等.

内置阀

内置阀有很多,不过常用的也就几种,具体参考官网,这里给出的是9.0版本链接,不同版本在URL中替换即可.

常用内置阀:

  • 客户访问日志阀,这个是默认开启的,在server.xml/<Server><Context>中,会生成访问日志,位置在$CATALINA_HOME/logs文件夹下
  • 远程地址过滤器, 定义哪些地址可以访问,哪些予以禁止
  • 远程主机过滤器, 定义哪些主机可以访问,哪些予以禁止
  • 客户请求记录器

位置

若要使得阀门生效,需要将其放在合适的位置上.不同的位置代表不同的作用域.根据作用范围从大到小排列:

  1. 放在server.xmlEngine元素下
  2. 放在server.xml<Host>元素下
  3. 放在context中,关于context的位置不唯一的情况,这里推荐$project_base_dir/src/main/META-INF/context.xml,具体原因见JavaWeb-Tomcat_Context

最常见的是第3种情况,可以根据项目需要自定义阀.

其次是第2种情况,比如默认开启的客户访问日志阀(``AccessLogValve`)就定义在这个位置.

第1种不太常用,不过视情况而定.

自定义

自定义阀需要满足几个条件:

  1. 实现类的包名必须是org.apache.catalina.valves
  2. 必须将自定义阀所在jar包放在$CATALINA_HOME/lib路径下,这两条是由TomcatClassLoader决定的.否则会报错ClassNotFoundException.
  3. 实现org.apache.catalina.Valve接口,一般是继承org.apache.catalina.valves.ValveBase类并重写invoke方法即可.

问题记录

  1. 默认开启了访问日志阀,为什么确始终看不见相应的日志文件?

    刚开始接触Valve,查看了server.xml中的确开启了客户访问日志的阀,可是始终看不到logs目录下出现相应的日志文件,经过研究发现是调用命令的问题,因为我用的是IDEA中的集成方式启动和部署war项目到Tomcat,而这种方式调用的是catalina.sh run命令,这种模式导致日志被重定向到控制台,所以需要部署后自行调用catalina.sh startstartup.sh就可以了.

posted @ 2020-04-12 00:23  舒山  阅读(287)  评论(0编辑  收藏  举报