フィルター
フィルターはサーバー側のコンポーネントであり、サーバーに送信される要求とサーバーから返される応答をフィルター処理するために使用されます。たとえば、フィルターは、ユーザーがさまざまな操作を実行するためにログインしているかどうか、またはページがないときにエラーメッセージを返すように要求するかどうかを決定します。フィルターはサーバーサービスの開始時に読み込まれ、生成されます。その後、ユーザーとサーバー間の要求と応答はフィルターを通過する必要があります。
1.フィルターを作成する
フィルタークラスを作成するには、Filterインターフェースの3つのメソッドを実装する必要があります。Init()はフィルターの初期化メソッドです。このメソッドは、Webコンテナーがフィルターを作成した後に呼び出され、web.xmlファイルからフィルターパラメーターを読み取ります。doFilter()はフィルタリング操作を完了します。リクエストリクエストがフィルタに到達すると、doFilter()オペレーションを実行してリクエストを処理します:転送、リダイレクト、または次のフィルタへの受け渡し。関連するオペレーションの実行後に返される応答は、ユーザー。destroy()は、Webコンテナーがインスタンスを破棄する前に呼び出され、フィルターが占有しているリソースを解放します。
public class firstFilter implements Filter {
public void init(FilterConfig filterConfig) throws ServletException {
System.out.println("创建第一个过滤器");
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
System.out.println("第一个过滤器执行过滤之前");
filterChain.doFilter(servletRequest,servletResponse);
System.out.println("第一个过滤操作之后");
}
public void destroy() {
System.out.println("销毁第一个过滤器");
}
}
フィルターをweb.xmlファイルに登録します。構成は次のとおりです。
FirstFilterという名前のフィルターを次のように登録します。そのクラスはfilter.myFilterにあり、対応するマッピングを定義してすべてのURLパスをフィルターします。
<filter>
<filter-name>FirstFilter</filter-name>
<filter-class>filter.myFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>FirstFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
アノテーションを使用してフィルターを登録することもできます。web.xmlファイルで手動で構成する必要はありません。アノテーションは、デプロイ時にWebコンテナーによってフィルターとして自動的に構成および登録されます。以下は、アノテーションによる同等のメソッドです
@WebFilter(filterName = "firstFilter",value = {"/*"},dispatcherTypes = {DispatcherType.REQUEST})
public class firstFilter implements Filter {
......
}
WebFilterの一般的なプロパティは次のとおりです。
2.フィルターチェーン
アクセスされたURLで複数のフィルターが定義されている場合、ユーザーリクエストは、web.xmlに登録されている順序で複数のフィルターを通過します。アクセスが完了すると、応答がネストされて返され、最終的にユーザーに返されます。このシーケンスはスタック操作に似ており、最初に出てきます。
たとえば、2つのフィルターのチェーン実行結果を定義します。
3.フィルター分類
フィルターを構成するときに、<dispatcher>オプションを4つ選択できます。
リクエスト、転送、インクルード、エラーなど、さまざまなタイプのページリクエストがフィルタリングされます。異なるタイプのフィルタは、このタイプのリクエストのみをフィルタリングします。
リクエストリクエストは、<dispatcher>のデフォルトのフィルタータイプです。ページのリクエストリクエストをフィルターします。直接リクエストまたはリダイレクトは、どちらもリクエストタイプです。
forwardは、転送ページリクエストをフィルタリングします。forwar()関数または<jsp:forward>アクションを渡すものは、すべて転送操作です。次に示すように、index.jspページでforward()関数を呼び出して、regPage.jspページに転送します。 、regPage.jspページ転送操作のフィルターforwardFilterを定義します。ユーザーが転送操作でregPage.jspページにアクセスすると、このフィルターを通過してコンソールに出力されます。
//在index.jsp页面进行转发到regPage.jsp
servletRequest.getRequestDispatcher("regPage.jsp").forward(servletRequest,servletResponse);
//定义转发过滤器
public class forwardFilter implements Filter {
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
System.out.println("转发过滤器");
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException {
}
}
//注册转发过滤器,针对regPage.jsp页面的转发类型请求进行过滤
<filter>
<filter-name>ForwardFilter</filter-name>
<filter-class>filter.forwardFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ForwardFilter</filter-name>
<url-pattern>/regPage.jsp</url-pattern>
<dispatcher>FORWARD</dispatcher>
</filter-mapping>
同様に、includeはページのinclude動作をフィルターし、getDispatcher()を使用した操作はinclude()または<jsp:include>がinclude動作です。
エラータイプは、ページでエラーが発生した後、指定されたページにジャンプするフィルターを参照します。以下は、404エラーが発生した後、ERRORタイプフィルターerrorFilterを渡す前に、exception.jspページにジャンプするページを定義しています。
<error-page>
<error-code>404</error-code>
<location>/exception.jsp</location>
</error-page>
<filter>
<filter-name>errorFilter</filter-name>
<filter-class>filter.errorFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>errorFilter</filter-name>
<url-pattern>/exception.jsp</url-pattern>
<dispatcher>ERROR</dispatcher>
</filter-mapping>
4.構成情報をロードする
filter init()関数は、<init-param>タグの構成情報をweb.xmlファイルにロードできます。
たとえば、WebサイトフィルターloginFilterがユーザーがログインしているかどうかを判断する必要がある場合、ユーザーがログインした後、情報はセッションに保存され、セッションはフィルターで判断されます。すでにログインしている場合は、引き続き他のページにアクセスできます。それ以外の場合は、ログインしていませんログインするには、login.jspページにジャンプする必要があります。ただし、フィルターは、失敗したログインページのlogin.jspおよびfail.jspページを再度フィルターに掛けるべきではありません。これにより、無限ループが発生します。したがって、フィルタリングする必要のない例外ページは、初期化パラメーターの形式でweb.xmlに保存され、フィルターのinit()関数に読み込まれ、doFilter()を使用して現在のパスが例外であるかどうかを判断し、そうである場合はリクエストが解放されます。
中国語の文字化けを防ぐために、ページでリクエストのエンコード形式を設定する必要がありますが、各ページでリクエストのエンコード形式を設定するのは面倒です。フィルターでリクエストのエンコードを設定すると、フィルター後のページのエンコードが有効になります。エンコード方式は、web.xmlファイルで指定して、フィルターにロードできます。
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>filter.loginFilter</filter-class>
<init-param> <!--设置不需要过滤的路径-->
<param-name>passPath</param-name>
<param-value>login.jsp;fail.jsp</param-value>
</init-param>
<init-param> <!--设置编码方式-->
<param-name>charset</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
public class loginFilter implements Filter {
private FilterConfig config; //设置配置参数变量
public void destroy() {
}
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
//读取配置文件中的编码并设置
String charset = config.getInitParameter("charset");
if (charset != null)
request.setCharacterEncoding(charset);
//判断路径是否属于配置文件中规定的路径,如果是则无需验证,放行请求
String passPath = config.getInitParameter("passPath");
String[] paths = passPath.split(";");
for (String path : paths) {
if (request.getRequestURI().indexOf(path) != -1) {
chain.doFilter(req, resp);
return;
}
}
//检查session是否有用户名信息,有代表已经登录可以访问,否则跳转到登录页面
if (request.getSession().getAttribute("username") != null)
chain.doFilter(req, resp);
else
response.sendRedirect("login.jsp");
}
public void init(FilterConfig config) throws ServletException {
this.config = config; //在初始化时加载配置参数
}
}
リスナー
リスナーは、サーブレットで定義された特別なクラスであり、ServletContext、HttpSession、HttpRequestドメインオブジェクトの作成、属性の変更、破棄などのイベントをリッスンするために使用されます(それぞれ、アプリケーション、セッション、jspのリクエストの3つのフィールドに対応)操作を実行します。リスナーは、クライアントのリクエストやサーバー側の操作(オンラインユーザーのカウント、訪問、初期化情報の読み込みなど)を監視するためによく使用されます。
1.リスナーを作成する
リスナーは基本的にJavaサーブレットクラスですが、サーブレットが作成および破棄されるときの呼び出しに対応するServletContextListenerインターフェイスの初期化されたメソッドや破棄されたメソッドなど、Listernerインターフェイスのいくつかのメソッドを実装します。
public class FirstListener implements ServletContextListener{
// Servlet要求保留无参构造器
public FirstListener() {
}
// web应用servlet部署时调用此方法
public void contextInitialized(ServletContextEvent sce) {
}
// servlet销毁时调用
public void contextDestroyed(ServletContextEvent sce) {
}
}
次に、リスナーパッケージの下のFirstListenerにあるweb.xmlにリスナーを登録する必要があります。
<listener>
<listener-class>listener.FirstListener</listener-class>
</listener>
servlet3.0以降では登録は必要ありませんが、注釈が付けられています。リスナークラス宣言の前に行を追加してください:@WebListener( "Description")
Webアプリケーションはweb.xmlファイルに登録されている順にリスナーを起動し、リスナーが最初に起動され、次にフィルターが起動され、最後にサーブレットが読み込まれます。
2.リスナーの分類
1.リスニングオブジェクトの作成と破棄
監視対象オブジェクトによると、アプリケーション全体、セッション、リクエストの3種類のリスナーに分類されます。対応するインターフェースは、ServletContextListener、HttpSessionListenter、ServletRequestListenerの3つのインターフェースを実装する必要があります。対応するオブジェクトの作成と破棄を監視します。メソッドを介して渡されるパラメータオブジェクトのgetXxx()メソッドは、現在呼び出されているオブジェクトを取得できます。たとえば、se.getSession()は現在のセッションオブジェクトを取得し、リスナーを介してオブジェクトを操作できます。
たとえば、初期化パラメータはサーブレットリスナから取得され、サーブレットのグローバルパラメータとして設定されるため、後でアプリケーション全体でパラメータを取得できます。
<context-param>
<param-name>initParam</param-name>
<param-value>初始化参数</param-value>
</context-param>
@Override //servlet创建时调用
public void contextInitialized(ServletContextEvent sce) {
//获取servlet初始化参数
String initParam =sce.getServletContext().getInitParameter("initParam");
//设置全局servlet参数
sce.getServletContext().setAttribute("init",initParam);
}
@Override //servlet销毁时调用
public void contextDestroyed(ServletContextEvent sce) {
}
以下は、セッションとリクエストリスナーの作成と破棄の監視です。
package listener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
public class FirstListener implements HttpSessionListener, ServletRequestListener {
//servlet要求保留空构造器
public FirstListener() {
}
@Override //创建session时调用
public void sessionCreated(HttpSessionEvent se) {
se.getSession();
}
@Override //session销毁时调用
public void sessionDestroyed(HttpSessionEvent se) {
}
@Override //request对象创建时调用
public void requestDestroyed(ServletRequestEvent sre) {
}
@Override //request销毁时调用
public void requestInitialized(ServletRequestEvent sre) {
}
}
2.監視プロパティの変更
サーブレット、セッション、リクエストのオブジェクト属性がいつ変更されるかを監視するために使用されます。継承されたインターフェースはServletContextAttributeListener、
HttpSessionAttributeListener、ServletRequestAttributeListenerです。3つのインターフェースはすべて、3つのメソッドを実装する必要があります:attributeAdded()、attributeRemoved()、attributeReplaced( )、ただし、渡されるパラメーターオブジェクトが異なります。たとえば、サーブレットに対応するパラメーターオブジェクトはServletContextAttributeEvent scaeです。残りの使用法は似ています。たとえば、次のリクエスト属性リスナーを使用して、属性の作成、変更、削除操作を監視します
package listener;
import javax.servlet.*;
public class AttributeListener implements ServletRequestAttributeListener {
// Public constructor is required by servlet spec
public AttributeListener() {
}
@Override
public void attributeAdded(ServletRequestAttributeEvent srae) {
System.out.println("request添加属性:"+srae.getName());
}
@Override
public void attributeRemoved(ServletRequestAttributeEvent srae) {
System.out.println("request删除属性:"+srae.getName());
}
@Override
public void attributeReplaced(ServletRequestAttributeEvent srae) {
System.out.println("request修改属性:"+srae.getName());
}
}
//--------------------listener.jsp页面创建并修改request属性-----------------
<%
request.setAttribute("request属性","request参数");
request.setAttribute("request属性","request参数2");
%>
セッションバインディングインターフェースHttpSessionBindingListener、パッシベーションインターフェースHttpSessionActivationListenerは、特別なリスナーを作成する必要はありませんが、通常のJavaBeanクラスで継承および実装できます。たとえば、Studentクラスは、Studentオブジェクトがバインドされているときにこれらの2つのインターフェースを実装します。 /セッションにバインドを解除すると、対応するメソッドがトリガーされ、同様にオブジェクトがパッシベーション/アクティブ化されるとトリガーされます。以下はStudentクラスです。
package modules;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionEvent;
public class Student implements HttpSessionBindingListener, HttpSessionActivationListener {
private String name;
private int age;
public Student() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("Session绑定User对象" + event.getName());
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("Session解绑User对象" + event.getName());
}
@Override
public void sessionWillPassivate(HttpSessionEvent se) {
System.out.println("Session钝化对象:" + se.getSource());
}
@Override
public void sessionDidActivate(HttpSessionEvent se) {
System.out.println("Session活化对象:" + se.getSource());
}
}
//-----------------在jsp页面内绑定、解绑Student对象------------------------
<%
Student s1=new Student();
session.setAttribute("student",s1); //输出:Session绑定User对象student
session.removeAttribute("student"); //输出:Session解绑User对象student
%>