Tomcat 阀简介
1.Tomcat 阀
Tomcat阀(Valve)组件能对Catalina容器接收到的HTTP请求进行预处理。Tomcat阀是Tomcat专有,不能用于Tomcat以外的其它Servlet容器。而过滤器是在Java Servlet规范中提出了的,因此适用于所有的Servlet容器 。
1.1 Tomcat阀简介
Tomcat阀可以加入到3种Catalina容器中,它们是Engine、Host和Context。作用范围如下表:
| 容器 | 描述 |
|---|---|
| Engine | 可以预处理该Engine接收到的所有HTTP请求 |
| Host | 可以预处理该Host接收到的所有HTTP请求 |
| Context | 可以预处理该Context接收到的所有HTTP请求 |
所有的Tomcat阀都实现了org.apache.Catalina.Valve接口或扩展了org.apache.Catalina.valves.ValveBase类。Tomcat阀包括以下几种:
- 客户访问日志阀(Access Log Valve)
- 远程地址过滤阀(Remote Address Valve)
- 远程主机过滤阀(Remote Host Valve)
- 错误报告阀(Error Report Valve)
Tomcat阀用<Valve>元素来配置,它的形式为:
<Valve className="实现这种阀的类的完整名字" ...其它属性.../>
如果把Tomcat阀加入到Context中,则需要在Tomcat的conf/server.xml文件的相应<Context>元素中加入<Valve>元素,或者在相应 Web应用的 META-INF/context.xml 文件的<Context>元素中加入<Valve>元素;但加入到Engine或Host中时,只能修改server.xml文件。
Tomcat中自带了关于Tomcat阀的参考文档:
<CATALINA_HOME>/webapps/docs/config/valve.html
1.2 客户访问日志阀
客户访问日志阀(Access Log Valve)能够将客户的请求信息写到日志文件中。这些日志可以记录网页的访问次数、访问时间、用户的会话活动和用户的安全验证信息等。

客户访问日志阀的<Valve>元素的属性描述见下表:
| 属性 | 描述 |
|---|---|
| className | 指定阀的实现类。如org.apache.Catalina.valves.AccessLogValve |
| directory | 设定存放日志文件的绝对或相对于<CATALINA_HOME>的相对目录。该属性的默认值为<CATALINA_HOME>/logs |
| pattern | 设定日志的格式和内容。默认值为 common。 |
| prefix | 设定日志文件名前缀。默认为 access_log |
| resolveHosts | 如果设为true,表示把远程IP地址解析为主机名,如果为false,表示直接记录远程IP地址。默认值为false。 |
| suffix | 设定日志文件的扩展名,默认值为""。 |
pattern 属性可以设置成common或者combined,这两个值集成了一些显示方式,也可以自己设置显示格式,支持如下的编码:
| 属性 | 描述 |
|---|---|
| %a | 远程访问者IP地址 |
| %A | 本地服务器IP地址 |
| %b | 发送信息的字节数,不包括http header,如果为0显示为“-” |
| %B | 发送信息的字节数,不包括http header |
| %h | 这个就是服务器名称了,如果resolveHosts为false就是IP地址了 |
| %H | 访问者使用的协议 |
| %l | 远程逻辑用户名,目前总是返回“-” |
| %m | 访问者请求使用的方法(GET、POST等) |
| %p | 接受访问者请求的本地服务器端口 |
| %q | 请求中的查询字符串,即HTTP请求的第一行的URI部分的“?”后面的内容 |
| %r | 请求的第一行内容(包括请求方法、请求URI以及HTTP协议版本) |
| %s | 服务器响应结果中的HTTP响应的状态码 |
| %S | 用户的session ID |
| %t | 日期和时间,使用Common Log的格式 |
| %u | 经过安全认证的访问者,不存在时为"-" |
| %U | 请求的URL路径 |
| %v | 本地服务器名 |
| %D | 处理请求花费的时间,以毫秒为单位 |
| %T | 处理请求花费的时间,以秒为单位 |
common的值:%h %l %u %t %r %s %b
combined的值:%h %l %u %t %r %s %b %{Referer}i %{User-Agent}I
例如在helloapp应用的context.xml文件的<Context>元素中加入如下<Valve>元素:
<Valve className="org.apache.catalina.valves.AccessLogValve"
directory="logs"
prefix="helloapp_access_log."
suffix=".txt"
pattern="%h %l %u %t %r %s %b"
resolveHosts="true" />
启动Tomcat,访问helloapp应用,此时在<CATALINA_HOME>/logs目录下会生成一个 helloapp_access_log.2018-10-18.text文件。
1.3 远程地址过滤阀
远程地址过滤阀(Remote Address Valve)可以根据远程客户的IP地址来决定是否接受客户的请求。在远程地址过滤阀中,事先保存了一份被拒绝的IP地址清单和允许访问的IP地址清单。如果客户的IP地址在拒绝清单中,那么这个客户的请求不会被 Catalina容器响应;如果在允许访问清单中,那么可以被响应。
远程地址过滤阀的<Valve>元素的属性描述见下表:
| 属性 | 描述 |
|---|---|
| className | 指定阀的实现类。如org.apache.Catalina.valves.RemoteAddrValve |
| allow | 指定允许访问的客户IP地址。如果此项没有设定,表示只要客户IP地址不在 deny清单中,就允许访问。多个IP地址以 “|” 隔开。 |
| deny | 指定不允许访问的客户IP地址,多个IP地址以 “|“ 隔开。 |
| denyStatus | 设定当拒绝客户请求时,服务器端返回的响应状态代码。该属性的默认值是403。 |
| addConnectorPort | 设定是否在deny或allow属性中加入端口号。该属性的默认值是false。当该属性的取值为true,那么在deny或allow属性中应该以 ”ADDRESS;PORT“ 的形式来设定地址,例如:allow=“.*;8009”,表示只接受来自端口号为8009的客户的请求。 |
例如在Tomcat的conf/server.xml文件中的 localhost的<Host>元素中加入如下<Valve>元素:
<Valve className="org.apache.Catalina.valves.RemoteAddrValve"
deny="127.* | 222.*" />
以上代码表明,所有IP地址以 127或222 开头的客户都会被拒绝访问 localhost虚拟主机中的所有Web应用。
IP地址分为 IPv4格式和 IPv6格式。例如 “127.0.0.1” 是IPv4格式的本地主机的地址。当前网络上更流行使用IPv6格式的地址,“::1” 或者 “0:0:0:0:0:0:0:1” 就是IPv6格式的本地主机的地址。例如以下配置代码表明只有本地主机上的客户才允许访问相关的Web应用:
<Valve className="org.apache.Catalina.valves.RemoteAddrValve"
allow="127\.\d+\.\d+\.\d+ | ::1 | 0:0:0:0:0:0:0:1" />
当<Valve>元素的allow属性和deny属性配置的IP地址清单中存在相同的IP地址时,则deny属性设置的IP地址有效。
1.4 远程主机过滤阀
远程主机过滤阀(Remote Host Valve)可以根据远程客户的主机名来决定是否接受客户的请求。在远程主机过滤阀中,事先保存了一份被拒绝的主机名清单和允许访问的主机名清单。如果客户的主机名在拒绝清单中,那么这个客户的请求就不会被 Catalina容器响应;如果在允许访问清单中,则可以被响应。
远程主机过滤阀的<Valve>元素的属性描述见下表:
| 属性 | 描述 |
|---|---|
| className | 指定阀的实现类。如org.apache.Catalina.valves.RemoteHostValve |
| allow | 指定允许访问的客户主机名。如果此项没有设定,表示只要客户主机名不在 deny清单中,就允许访问。多个主机名以 “|” 隔开。 |
| deny | 指定不允许访问的客户主机名,多个主机名以 “|“ 隔开。 |
| denyStatus | 设定当拒绝客户请求时,服务器端返回的响应状态代码。该属性的默认值是403。 |
| addConnectorPort | 设定是否在deny或allow属性中加入端口号。该属性的默认值是false。当该属性的取值为true,那么在deny或allow属性中应该以 ”HOSTNAME;PORT“ 的形式来设定地址,例如:allow=“*;8009”,表示只接受来自端口号为8009的客户的请求。 |
例如在Tomcat的conf/server.xml文件中的 localhost的<Host>元素中加入如下<Valve>元素:
<Valve className="org.apache.Catalina.valves.RemoteHostValve"
deny="monster*" />
以上代码表明,所有主机名中包含monster字符串的客户都被拒绝访问 localhost虚拟主机中的所有Web应用
1.5 错误报告阀
错误报告阀(Error Report Valve)能够向客户端输出HTTP响应错误信息。配置和使用错误报告阀的步骤如下。
-
在Tomcat的安装根目录<CATALINA_HOME>下创建一个自定义的目录,例如为 error_report目录,然后在该目录下创建一个报告特定HTTP响应错误的网页,例如为 error404.htm,他采用“UTF-8”编码,他的内容如下:
<html> <head> <meta charset="UTF-8"> <title>Error Page</title> </head> <body> <p> The page you request does not exist. </p> </body> </html> -
在Tomcat的conf/server.xml文件中的 localhost的<Host>元素中加入如下<Valve>元素:
<Valve className="org.apache.Catalina.valves.ErrorReportValve" errorCode.404="/error_report/error404.htm" />以上<Valve>元素的errorCode.404属性设定了与HTTP响应错误状态代码为404对应的错误报告网页,他的取值为 “/error_report/error404.htm”,这是相对于 Tomcat根目录的相对路径。
-
启动 Tomcat服务器,从浏览器端访问一个服务端不存在的文件资源,这时服务器端会产生响应状态代码为404的错误,错过报告阀把响应的 error404.htm网页返回到客户端。