可以偷偷利用 LoggingFilter 作為攔截的手段。
首先要利用 LogginFilter 之前,需要先寫一個自定義的 Filter,這裡就仿照 [1] 的網友 markthegrea 提供的範例:
package example; import java.util.Calendar; import com.sun.jersey.api.container.filter.LoggingFilter; import com.sun.jersey.spi.container.ContainerRequest; import com.sun.jersey.spi.container.ContainerRequestFilter; import com.sun.jersey.spi.container.ContainerResponse; public class RequestLogger extends LoggingFilter implements ContainerRequestFilter { private static ThreadLocal<Long> EXECUTION_TIME = new ThreadLocal<Long>(); @Override public ContainerRequest filter(ContainerRequest request) { EXECUTION_TIME.set(Calendar.getInstance().getTimeInMillis()); System.out.println("Request is started at " + EXECUTION_TIME.get().longValue()); return request; } @Override public ContainerResponse filter(ContainerRequest request, ContainerResponse response) { StringBuilder sb = new StringBuilder(); sb.append("User:").append((request.getUserPrincipal() == null ? "unknown" : request.getUserPrincipal().getName())); sb.append(" - Path:").append(request.getRequestUri().getPath()); sb.append(" - ").append(Calendar.getInstance().getTimeInMillis() - EXECUTION_TIME.get().longValue()); System.out.println(sb.toString()); return response; } }
以上的程式碼有兩個覆寫 filter() 的方法,其實兩個方法分別對應的是不同的事件
上面的 filter(ContainerRequest) 是攔截 Request 收到的時間
而下面的 filter(ContainerRequest, ContainerResponse) 則是攔截 Response 送出的時間。
另外簡單說明一下,第一個攔截 Request 的 filter,做的事情就是在 console 中印出收到 Request 的時間。
而第二個攔截 Response 的 filter 則是依照收到 Request 的時間,去計算出這次 Request 總共花費的時間。
在定義好 LoggingFilter 之後,必須在 web.xml 上宣告 Request 和 Response 的 filter,伺服器在啟動時才知道要去哪裡執行攔截的動作。
<servlet> <servlet-name>ServletAdaptor</servlet-name> <servlet-class>com.sun.jersey.server.impl.container.servlet.ServletAdaptor</servlet-class> <init-param> <param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name> <param-value>example.RequestLogger</param-value> </init-param> <init-param> <param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name> <param-value>example.RequestLogger</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet>
上面的 XML 只包含關鍵的片段 XML,第 2 行開始是宣告 Jersey 的 Servlet。
其中 4~7 行是宣告 Request 的 filter、8~11 行是宣告 Response 的 filter
因為前面把 Request 和 Response 的 filter 都寫在同一個類別裡,所以這裡的 param-value 都指向同一個 class。
最後執行任意一個 RESTful 服務時,會看到以下的 console 訊息。
Request is started at 1377443204176 User:unknown - Path:/Jersey/web/test/test - 5其中 Path 那段出現的字串裡,Jersey 是我這次放的專案名稱,web 是我在 web.xml 上定義的 Jersey 的 URL
test/test 則是我測試時呼叫的 RESTful 服務。
參考資料:
1、How does one intercept a request during the Jersey lifecycle?
沒有留言:
張貼留言