⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 servlet2.3.txt

📁 考取JAVA证件的资料
💻 TXT
📖 第 1 页 / 共 2 页
字号:
在这些类中,这两个方法的默认行为是把调用传递给它们所封装的对象。使用这些类的时候,你一般要派生这些类并覆盖那些感兴趣的方法。对于本文的过滤器,我们必须创建一个应答封装器,记录对addXXXHeader()方法和setXXXHeader()方法的调用。另外,我们还想要捕获对setStatus()、setContentLength()、setContentType()和setLocale()方法的调用。代码如Listing 4所示,它简单地记录了对各个方法的调用。


【Listing 4】应答封装器。下面的代码为过滤器构造了一个应答封装器, 它将记录对addXXXHeader()和setXXXHeader()方法的调用。另外, 它还要捕获对setStatus()、setContentLength()、setContentType()和 setLocale()方法的调用。

class HeaderResponseWrapper extends
HttpServletResponseWrapper {
  ServletContext ctx;

  public HeaderResponseWrapper(
    HttpServletResponse response,
    ServletContext ctx) {
      super(response);
      this.ctx = ctx;
   }

  public void addCookie(Cookie cookie) {
    ctx.log("Set-Cookie: " + cookie.getName() + ":" + cookie.getValue());
    super.addCookie(cookie);
   }

  public void addHeader(String name, String value) {
    ctx.log(name + ": " + value); super.addHeader(name, value);
   }

  public void addIntHeader(String name, int value) {
    ctx.log(name + ": " + value); super.addIntHeader(name, value);
   }

  public void addDateHeader(String name, long value) {
    ctx.log(name + ": " + value); super.addDateHeader(name, value);
   }

  public void setHeader( String name, String value) {
    ctx.log(name + ": " + value); super.setHeader(name, value);
   }

  public void setIntHeader( String name, int value) {
    ctx.log(name + ": " + value); super.setIntHeader(name, value);
   }

  public void setDateHeader( String name, long value) {
    ctx.log(name + ": " + value); super.setDateHeader(name, value);
   }

  public void setStatus(int sc) {
    ctx.log("status: " + sc); super.setStatus(sc);
   }

  public void setStatus( int sc, java.lang.String sm) {
    ctx.log("status: " + sc); super.setStatus(sc, sm);
   }

  public void setContentLength(int len) {
    ctx.log("Content-Length: " + len); super.setContentLength(len);
   }

  public void setContentType(java.lang.String type) {
    ctx.log("Content-Type: " + type); super.setContentType(type);
   }

  public void setLocale(java.util.Locale loc) {
    ctx.log("locale: " + loc); super.setLocale(loc);
   }
} 

在过滤器中,我们按照如下方式使用这个对象:


HttpServletResponse resp = (HttpServletResponse)response;
HeaderResponseWrapper hrespw = new HeaderResponseWrapper(resp, ctx);

System.out.println("********");

chain.doFilter(request, hrespw); 

注意创建好封装器之后chain.doFilter()方法就被调用。

定义好过滤器之后就应该安装它。为此,web.xml中应该定义一个filter元素:


<filter>
<filter-name>
  Headers Filter
</filter-name>
<filter-class>
  DumpHeaders
</filter-class>
<!- optional <init-params> ->
</filter> 

完成这一步之后,你还要把过滤器和你想要过滤的资源关联起来。这时你有两种选择:在web.xml中,把过滤器关联到单个命名的Servlet,或者把过滤器关联到一个URL。如下所示:


<filter-mapping>
<filter-name>
  Headers Filter
</filter-name>
<servlet-name>
AddressBookServlet
</servlet-name>
</filter-mapping> 

或者:


<filter-mapping>
<filter-name>
  Header Filter
</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping> 

输出的请求头如下所示:


GET/AddressBook/Browse.jsp HTTP/1.1
accept: */*
referer: http://localhost/ AddressBook/
accept-language: en-gb
accept-encoding: gzip, deflate
user-agent: Mozilla/4.0 ( compatible; MSIE 5.5; Windows NT 5.0)
host: localhost
connection: Keep-Alive
cookie: JSESSIONID= E0F9646772F4448004C16122020664F1 

输出的应答头如下所示:


Content-Type: text/html;charset=8859_1 Content-Type: text/plain 

如果进行网络跟踪,你会发现这里少了一些东西。例如,状态代码没有显示,这是因为有一些应答头由容器在过滤器链执行之前或之后设置。

过滤器有很多用途,比如验证、转换、加密/解密。但有一点必须注意:你可以把过滤器关联到任意资源,而不仅仅是Servlet。如果你使用的是一个插入到其他Web服务器的Servlet引擎,Web服务器很可能会不依赖于Servlet容器独立地提供服务。在这种情况下,Servlet容器将接收不到所有的请求,所以过滤器也就不会总是被执行。

JSP 1.1中有一个问题涉及到请求分派。如果你有一个页面执行include操作,jsp:include有一个必须设置为true的强制性flush(刷新)属性:


<jsp:include page="somePage" flush="true" /> 

这个属性强制容器把当前缓冲区内容刷新到客户端。这样,JSP页面不能再设置任意HTTP应答头。JSP 1.2规范已经修正这个问题,jsp:include标记中现在已经可以指定flush="false"。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -