サーブレットフィルターの動きをサンプルプログラムで確かめてみました。Servletの実行前後で処理をフィルターに任せることができるため、いくつかのServletで前処理、後処理が共通である場合はフィルターに集約することができます。
サーブレットフィルターの実行環境です。
Java: OpenJDK 1.8
Tomcat: ver 9.0.65
フィルターを適用するにはTomcatの web.xml に記載をします。
filterのurl-patternにアスタリスクを使うことで、TestServlet1、TestServlet2が動くときにTestFilterが動くようにしています。
TestFilterのソースコードです。
FilterインターフェイスのdoFilterメソッドに処理を記載しています。FilterChainのdoFilterメソッドで処理をServletに渡します。Servletの処理が終わったらフィルターに処理が戻ってきます。
ややこしいのは(Filterインターフェイスの)doFilterメソッドを実装した中で(FilterChainの)doFilterメソッドを呼ぶことです。なお、initとdestroyのメソッドは処理がないのでオーバーライドしているだけです。
TestServlet1のソースコードです。
TestServlet2のソースコードです。
TestServlet1とTestServlet2はprintlnで出力する文言が違うだけです。
TestServlet1を実行したときのものです。
TestServlet2を実行したときです。
どちらもフィルターの処理が動いていることがわかります。
フィルターは複数設定することもできます。その場合は web.xml に複数のフィルターを記載します。フィルターが実行される順番は記載した順(上から下)となります。
前処理と後処理のタイミングですが以下のようになります。①〜⑤が処理順を示します。
フィルターに処理が戻るときは web.xml に記載した下の方のフィルターから処理がされます。そのため、前処理と後処理ではフィルターの実行順序が逆になります。
使用したソースを載せておきます。
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<servlet>
<servlet-name>servlet1</servlet-name>
<servlet-class>sample5.TestServlet1</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet1</servlet-name>
<url-pattern>/sample5/servlet1</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>servlet2</servlet-name>
<servlet-class>sample5.TestServlet2</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servlet2</servlet-name>
<url-pattern>/sample5/servlet2</url-pattern>
</servlet-mapping>
<filter>
<filter-name>filter</filter-name>
<filter-class>sample5.TestFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>filter</filter-name>
<url-pattern>/sample5/*</url-pattern>
</filter-mapping>
</web-app>
TestFilter.java
package sample5;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
public class TestFilter implements Filter {
public void doFilter(
ServletRequest request, ServletResponse response,
FilterChain chain
) throws IOException, ServletException {
//Filterの前処理
response.setContentType("text/html; charset=UTF-8");
PrintWriter out = response.getWriter();
out.println("<!DOCTYPE html>");
out.println("<html>");
out.println("<head>");
out.println("<meta charset='UTF-8'>");
out.println("<title>Filter Servlet</title>");
out.println("</head>");
out.println("<body>");
out.println("Filterの前処理<br>");
request.setAttribute("out", out);
//Servletの処理
chain.doFilter(request, response);
//Filterの後処理
out.println("Filterの後処理<br>");
out.println("</body>");
out.println("</html>");
}
public void init(FilterConfig filterConfig) { }
public void destroy() { }
}
TestServlet1.java
package sample5;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet1 extends HttpServlet {
public void doGet (
HttpServletRequest request, HttpServletResponse response
) throws ServletException, IOException {
PrintWriter out = (PrintWriter)request.getAttribute("out");
out.println("Servlet(1)の処理<br>");
}
}
TestServlet2.java
package sample5;
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class TestServlet2 extends HttpServlet {
public void doGet (
HttpServletRequest request, HttpServletResponse response
) throws ServletException, IOException {
PrintWriter out = (PrintWriter)request.getAttribute("out");
out.println("Servlet(2)の処理<br>");
}
}