ホームページ  >  記事  >  Java  >  Java のフィルター、サーブレット、リスナーの詳細な紹介

Java のフィルター、サーブレット、リスナーの詳細な紹介

黄舟
黄舟オリジナル
2017-07-30 13:18:361406ブラウズ

この記事では主にフィルター、サーブレット、リスナーの学習教材を詳しく紹介します。興味のある方はぜひ参考にしてください。

気に入っていただければ幸いです。

1. フィルター関数


フィルター関数。ユーザーはリクエストを変更し、レスポンスを変更できます。フィルターはサーブレットではありませんが、サーブレットに到達する前にリクエストを前処理することもできます。言い換えると、フィルターは実際には「サーブレットチェーン」(サーブレットチェーン) です:


1)、サーブレットが呼び出される前にインターセプトされます。サーブレットが呼び出される前のサーブレット リクエスト。

3)、必要に応じてリクエスト ヘッダーとリクエスト データを変更します。

4)、必要に応じて応答ヘッダーと応答データを変更します。
5)、サーブレットが呼び出された後にインターセプトします。


サーバー setFilterConfig メソッドはフィルター処理の準備のために毎回 1 回だけ呼び出されますが、doFilter メソッドはさまざまなリクエストを処理するために複数回呼び出されます。FilterConfig インターフェースにはフィルター名と初期化パラメーター情報を検索するメソッドがあります。サーバーは FilterConfig を次のように設定できます。空の場合は、フィルタが終了したことを示します。
各フィルターは doFilter() メソッドから現在のリクエストとレスポンスを取得します。このメソッドでは、リクエストとレスポンスに対するあらゆる操作を実行できます (データの収集、データのパッケージ化など)。 ) メソッドは制御を次のフィルターに渡します。フィルターは doFilter() メソッドで終了します。フィルターがリクエスト処理を停止して応答を完全に制御したい場合は、次のフィルターを呼び出す必要はありません。まず新しいフィルターを作成します。フィルター


/** 
 * 
 */ 
package com.ee.filter; 
 
import java.io.IOException; 
 
import javax.servlet.Filter; 
import javax.servlet.FilterChain; 
import javax.servlet.FilterConfig; 
import javax.servlet.ServletException; 
import javax.servlet.ServletRequest; 
import javax.servlet.ServletResponse; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class LogFilter implements Filter { 
 private FilterConfig filterConfig; 
 
 public FilterConfig getFilterConfig() { 
  System.err.println("...getFilterConfig..."); 
  return filterConfig; 
 } 
 
 public void setFilterConfig(FilterConfig filterConfig) { 
  System.err.println("...setFilterConfig..."); 
  this.filterConfig = filterConfig; 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#destroy() 
  */ 
 @Override 
 public void destroy() { 
  System.err.println("...filter destroy..."); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) 
  */ 
 @Override 
 public void doFilter(ServletRequest request, ServletResponse response, 
   FilterChain chain) throws IOException, ServletException { 
  System.err.println("...doFilter..."); 
  chain.doFilter(request, response);//看到这没,这只要是传递下一个Filter 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.Filter#init(javax.servlet.FilterConfig) 
  */ 
 @Override 
 public void init(FilterConfig filterConfig) throws ServletException { 
  System.err.println("...init Filter..."); 
  this.filterConfig = filterConfig; 
 } 
 
}

がWebで設定されており、...doFilter...が印刷されていることがわかります。


2. サーブレット関数


1)。サーブレットとは何ですか?

サーブレットは、Java Servlet アプリケーション プログラミング インターフェイス (API) と関連するクラスとメソッドを使用する Java プログラムです。 Java サーブレット API に加えて、サーブレットは API を拡張して API に追加する Java クラス パッケージを使用することもできます。サーブレットは、Java 対応の Web サーバーまたはアプリケーション サーバー上で実行され、そのサーバーの機能を拡張します。 Web サーバーにとっての Java サーブレットは、Web ブラウザにとっての Java アプレットと同様です。サーブレットは Web サーバーにロードされ、Web サーバー内で実行されます。一方、アプレットは Web ブラウザにロードされ、Web ブラウザ内で実行されます。 Java サーブレット API は、サーブレットと Java 対応サーバー間の標準インターフェイスを定義し、サーブレットをクロスサーバー プラットフォームにします。

サーブレットは、Web 上でリクエストとレスポンスのサービスを提供するフレームワークを作成することで、サーバーの機能を拡張します。クライアントがサーバーにリクエストを送信すると、サーバーはリクエスト情報をサーブレットに送信し、サーバーがクライアントに返す応答をサーブレットに構築させることができます。 サーブレットは、Web サーバーの起動時、またはクライアントが初めてサービスを要求したときに自動的にロードできます。ロード後、サーブレットは他のクライアントがリクエストを行うまで実行を続けます。サーブレットには幅広い機能があります。たとえば、サーブレットは次の機能を実行できます。 (1) 顧客のリクエストの性質に基づいて、動的コンテンツを含む完全な HTML ページを作成して返します。 (2) 既存のHTMLページに埋め込むことができるHTMLページの一部(HTMLフラグメント)を作成します。
(3) 他のサーバーリソース(データベースやJavaベースのアプリケーションを含む)と通信します。
(4) 複数のクライアントを使用して接続を処理し、複数のクライアントから入力を受け取り、結果を複数のクライアントにブロードキャストします。たとえば、サーブレットは複数参加者のゲーム サーバーである可能性があります。
(5) 単一接続モードでデータ送信が許可されている場合、ブラウザ上でサーバーからアプレットへの新しい接続を開き、接続を開いたままにします。アプレットはクライアントのブラウザとサーバー間の接続を開始することもできるため、クライアントとサーバーは簡単かつ効率的にセッションを実行できます。通信は、カスタム プロトコルまたは IIOP などの標準を介して行うことができます。

(6) 画像変換やサーバーサイドインクルード(SSI)などの特殊な処理には、MIMEタイプのフィルタリングデータを使用します。

(7) すべてのサーバーの標準ルーチンにカスタマイズされた処理を提供します。たとえば、サーブレットはユーザーの認証方法を変更できます。
2)。サーブレットのライフサイクル

サーブレットのライフサイクルは、サーブレットがWebサーバーのメモリにロードされたときに始まり、サーブレットが終了または再ロードされたときに終了します。


(1) 初期化

以下のタイミングでサーブレットをロードします:
autoload オプションが設定されている場合、サーバーの起動時に自動的にロードされます

クライアントが初めてサーブレットにリクエストを行ったときにリロードしますサーバーが起動します

サーブレットがロードされると、サーバーはサーブレット インスタンスを作成し、サーブレットの init() メソッドを呼び出します。初期化フェーズ中に、サーブレット初期化パラメータがサーブレット構成オブジェクトに渡されます。

(2)リクエスト処理
サーバーに到着したクライアントリクエストに対して、サーバーはリクエスト固有の「リクエスト」オブジェクトと「レスポンス」オブジェクトを作成します。サーバーはサーブレットの service() メソッドを呼び出します。このメソッドは、「リクエスト」オブジェクトと「応答」オブジェクトを渡すために使用されます。 service() メソッドは、「リクエスト」オブジェクトからリクエスト情報を取得し、リクエストを処理し、「応答」オブジェクトのメソッドを使用して応答をクライアントに返します。 service() メソッドは、doGet()、doPost() などの他のメソッドを呼び出してリクエストを処理できます。

(3) 終了
サーバーがサーブレットを必要としなくなったとき、またはサーブレットの新しいインスタンスをリロードするとき、サーバーはサーブレットの destroy() メソッドを呼び出します。

3). Java Servlet API
Java Servlet Development Tool (JSDK) は、サーブレットを作成する際に必要となる複数のソフトウェア パッケージを提供します。これらには、すべてのサーブレット用の 2 つの基本パッケージ、javax.servlet と javax.servlet.http が含まれます。 Java サーブレット開発ツールは、Sun の Web サイトからダウンロードできます。 以下では、javax.servlet.http が提供する HTTP サーブレット アプリケーション プログラミング インターフェイスを主に紹介します。
HTTP サーブレットは、HTML フォームを使用してデータを送受信します。 HTTP サーブレットを作成するには、HTML テーブルを処理する特殊なメソッドを使用する GenericServlet のサブクラスである HttpServlet クラスを拡張します。 HTML フォームは 632555444b46edf0af44e58213a0ac8c タグと 67c47c2f4e2e39e829bbcfb43fc3cadb によって定義されます。通常、フォームには入力フィールド (テキスト入力フィールド、チェック ボックス、ラジオ ボタン、選択リストなど) とデータを送信するためのボタンが含まれています。情報を送信するときは、サーバーが実行するサーブレット (または他のプログラム) も指定します。 HttpServlet クラスには、init()、destroy()、service() およびその他のメソッドが含まれます。 init() メソッドと destroy() メソッドは継承されます。

(1) init()メソッド

サーブレットのライフサイクルにおいて、init()メソッドは一度だけ実行されます。これは、サーバーがサーブレットをロードするときに実行されます。 サーバーの起動時、またはクライアントが初めてサーブレットにアクセスしたときにサーブレットをロードするようにサーバーを構成できます。 サーブレットにアクセスするクライアントの数に関係なく、init() が繰り返し実行されることはありません。
デフォルトの init() メソッドは通常、要件を満たしていますが、通常はサーバー側のリソースを管理するために、カスタムの init() メソッドでオーバーライドすることもできます。 たとえば、GIF 画像を 1 回だけロードするカスタム init() を作成すると、GIF 画像を返し、複数のクライアント要求を含むサーブレットのパフォーマンスが向上します。別の例は、データベース接続の初期化です。デフォルトの init() メソッドはサーブレットの初期化パラメータを設定し、その ServletConfig オブジェクト パラメータを使用して構成を開始するため、init() メソッドをオーバーライドするすべてのサーブレットは super.init() を呼び出して、これらのタスクが確実に実行されるようにする必要があります。 service() メソッドを呼び出す前に、init() メソッドが完了していることを確認する必要があります。

(2)service()メソッド
service()メソッドはServletの中核です。クライアントが HttpServlet オブジェクトを要求するたびに、オブジェクトの service() メソッドが呼び出され、「要求」 (ServletRequest) オブジェクトと「応答」 (ServletResponse) オブジェクトがパラメータとしてこのメ​​ソッドに渡されます。 service() メソッドは HttpServlet にすでに存在します。デフォルトのサービス関数は、HTTP リクエストのメソッドに対応する do 関数を呼び出します。たとえば、HTTP リクエスト メソッドが GET の場合、デフォルトで doGet() が呼び出されます。サーブレットは、サーブレットがサポートする HTTP メソッドの do 機能をオーバーライドする必要があります。 HttpServlet.service() メソッドは、リクエスト メソッドが適切なハンドラーを呼び出すかどうかをチェックするため、service() メソッドをオーバーライドする必要はありません。対応する do メソッドをオーバーライドするだけで完了です。
クライアントが HTML フォームを通じて HTTP POST リクエストを行うと、 doPost() メソッドが呼び出されます。 POST リクエストに関連付けられたパラメータは、別の HTTP リクエストとしてブラウザからサーバーに送信されます。サーバー側のデータを変更する必要がある場合は、doPost() メソッドを使用する必要があります。
クライアントが HTML フォームを通じて HTTP GET リクエストを行うか、URL を直接リクエストすると、 doGet() メソッドが呼び出されます。 GET リクエストに関連するパラメータは URL の末尾に追加され、このリクエストとともに送信されます。 doGet() メソッドは、サーバー側のデータが変更されない場合に使用する必要があります。
サーブレットの応答には次のタイプがあります:
出力ストリーム。ブラウザはコンテンツ タイプ (テキスト/HTML など) に従って解釈します。
HTTP エラー応答。別の URL、サーブレット、JSP にリダイレクトされます。

(3) destroy() 方法
  destroy() 方法仅执行一次,即在服务器停止且卸装Servlet 时执行该方法。典型的,将 Servlet 作为服务器进程的一部分来关闭。缺省的 destroy() 方法通常是符合要求的,但也可以覆盖它,典型的是管理服务器端资源。例如,如果 Servlet 在运行时会累计统计数据,则可以编写一个 destroy() 方法,该方法用于在未装入 Servlet 时将统计数字保存在文件中。另一个示例是关闭数据库连接。
当服务器卸装 Servlet 时,将在所有 service() 方法调用完成后,或在指定的时间间隔过后调用 destroy() 方法。一个Servlet 在运行service() 方法时可能会产生其它的线程,因此请确认在调用 destroy() 方法时,这些线程已终止或完成。

(4) GetServletConfig()方法
  GetServletConfig()方法返回一个 ServletConfig 对象,该对象用来返回初始化参数和  ServletContext。ServletContext 接口提供有关servlet 的环境信息。

(5) GetServletInfo()方法
  GetServletInfo()方法是一个可选的方法,它提供有关servlet 的信息,如作者、版本、版权。
  当服务器调用sevlet 的Service()、doGet()和doPost()这三个方法时,均需要 “请求”和“响应”对象作为参数。“请求”对象提供有关请求的信息,而“响应”对象提供了一个将响应信息返回给浏览器的一个通信途径。javax.servlet 软件包中的相关类为ServletResponse和ServletRequest,而javax.servlet.http 软件包中的相关类为HttpServletRequest 和 HttpServletResponse。Servlet 通过这些对象与服务器通信并最终与客户机通信。Servlet 能通过调用“请求”对象的方法获知客户机环境,服务器环境的信息和所有由客户机提供的信息。Servlet 可以调用“响应”对象的方法发送响应,该响应是准备发回客户机的。 

例子:
创建一个servlet


/** 
 * 
 */ 
package com.ee.servlet; 
 
import java.io.IOException; 
 
import javax.servlet.ServletException; 
import javax.servlet.http.HttpServlet; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class LogServlet extends HttpServlet { 
 
 /** 
  * 
  */ 
 private static final long serialVersionUID = 1L; 
 
 @Override 
 protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
   throws ServletException, IOException { 
  doPost(req, resp); 
 } 
  
 @Override 
 protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
   throws ServletException, IOException { 
  System.err.println("...doPost(req, resp)..."); 
 } 
}

在web.xml中的配置:


<servlet> 
 <servlet-name>LogServlet</servlet-name> 
 <servlet-class>com.ee.servlet.LogServlet</servlet-class> 
</servlet> 
 
<servlet-mapping> 
 <servlet-name>LogServlet</servlet-name> 
 <url-pattern>/*</url-pattern><!-- 看到此没有,这个拦截所有路径 --> 
</servlet-mapping>

它的拦截规则:

当一个请求发送到servlet容器的时候,容器先会将请求的url减去当前应用上下文的路径作为servlet的映射url,比如我访问的是http://localhost/test/aaa.html,我的应用上下文是test,容器会将http://localhost/test去掉,剩下的/aaa.html部分拿来做servlet的映射匹配。这个映射匹配过程是有顺序的,而且当有一个servlet匹配成功以后,就不会去理会剩下的servlet了(filter不同,后文会提到)。其匹配规则和顺序如下:
1.精确路径匹配。例子:比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先 进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了。
2.最长路径匹配。例子:servletA的url-pattern为/test/*,而servletB的url-pattern为/test/a/*,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB。
3.扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet。例子:servletA的url-pattern:*.action
4.如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源。如果应用定义了一个default servlet,则容器会将请求丢给default servlet 

3、Listener功能

它是基于观察者模式设计的,Listener 的设计对开发 Servlet 应用程序提供了一种快捷的手段,能够方便的从另一个纵向维度控制程序和数据。目前 Servlet 中提供了 5 种两类事件的观察者接口,它们分别是:4 个 EventListeners 类型的,ServletContextAttributeListener、ServletRequestAttributeListener、ServletRequestListener、HttpSessionAttributeListener 和 2 个 LifecycleListeners 类型的,ServletContextListener、HttpSessionListener。如下图所示: 

Listener是Servlet的监听器,它可以监听客户端的请求、服务端的操作等。通过监听器,可以自动激发一些操作,比如监听在线的用户的数量。当增加一个HttpSession时,就激发sessionCreated(HttpSessionEvent se)方法,这样就可以给在线人数加1。常用的监听接口有以下几个:

ServletContextAttributeListener监听对ServletContext属性的操作,比如增加、删除、修改属性。
ServletContextListener监听ServletContext。当创建ServletContext时,激发contextInitialized(ServletContextEvent sce)方法;当销毁ServletContext时,激发contextDestroyed(ServletContextEvent sce)方法。
HttpSessionListener监听HttpSession的操作。当创建一个Session时,激发session Created(HttpSessionEvent se)方法;当销毁一个Session时,激发sessionDestroyed (HttpSessionEvent se)方法。
HttpSessionAttributeListener监听HttpSession中的属性的操作。当在Session增加一个属性时,激发attributeAdded(HttpSessionBindingEvent se) 方法;当在Session删除一个属性时,激发attributeRemoved(HttpSessionBindingEvent se)方法;当在Session属性被重新设置时,激发attributeReplaced(HttpSessionBindingEvent se) 方法。

下面我们开发一个具体的例子,这个监听器能够统计在线的人数。在ServletContext初始化和销毁时,在服务器控制台打印对应的信息。当ServletContext里的属性增加、改变、删除时,在服务器控制台打印对应的信息。
要获得以上的功能,监听器必须实现以下3个接口:

HttpSessionListener
ServletContextListener
ServletContextAttributeListener 

例子:


/** 
 * 
 */ 
package com.ee.listener; 
 
import javax.servlet.ServletContextAttributeEvent; 
import javax.servlet.ServletContextAttributeListener; 
import javax.servlet.ServletContextEvent; 
import javax.servlet.ServletContextListener; 
import javax.servlet.http.HttpSessionEvent; 
import javax.servlet.http.HttpSessionListener; 
 
/** 
 * @author Administrator 
 * 
 */ 
public class OnlineUserListener implements HttpSessionListener, 
  ServletContextListener, ServletContextAttributeListener { 
 private long onlineUserCount = 0; 
 
 public long getOnlineUserCount() { 
  return onlineUserCount; 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeAdded(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeAdded(ServletContextAttributeEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeRemoved(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeRemoved(ServletContextAttributeEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextAttributeListener#attributeReplaced(javax.servlet.ServletContextAttributeEvent) 
  */ 
 @Override 
 public void attributeReplaced(ServletContextAttributeEvent attributeEvent) { 
  System.err.println("...attributeReplaced..."); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextListener#contextDestroyed(javax.servlet.ServletContextEvent) 
  */ 
 @Override 
 public void contextDestroyed(ServletContextEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.ServletContextListener#contextInitialized(javax.servlet.ServletContextEvent) 
  */ 
 @Override 
 public void contextInitialized(ServletContextEvent arg0) { 
 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.http.HttpSessionListener#sessionCreated(javax.servlet.http.HttpSessionEvent) 
  */ 
 @Override 
 public void sessionCreated(HttpSessionEvent httpSessionEvent) { 
  onlineUserCount ++; 
  toUpdateCount(httpSessionEvent); 
 } 
 
 /* (non-Javadoc) 
  * @see javax.servlet.http.HttpSessionListener#sessionDestroyed(javax.servlet.http.HttpSessionEvent) 
  */ 
 @Override 
 public void sessionDestroyed(HttpSessionEvent httpSessionEvent) { 
  onlineUserCount --; 
  toUpdateCount(httpSessionEvent); 
 } 
 
 private void toUpdateCount(HttpSessionEvent httpSessionEvent){ 
  httpSessionEvent.getSession().setAttribute("onlineUserCount", onlineUserCount); 
 } 
}

 Web.xml


<listener> 
 <listener-class>com.ee.listener.OnlineUserListener</listener-class> 
</listener>

 JSP页面:


<%@ page language="java" contentType="text/html; charset=UTF-8" 
 pageEncoding="UTF-8"%> 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> 
<html> 
<head> 
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> 
<title>主页</title> 
</head> 
<body> 
 <h4>你好!</h4> 
 在线人数:<h1><%=request.getSession().getAttribute("onlineUserCount") %></h1> 
</body> 
</html>

以上がJava のフィルター、サーブレット、リスナーの詳細な紹介の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。