Servlet 2.3 Filter Programming
Find the servlet filter you can use today
Summary
Jason Hunter discusses in-depth discussion of new servlet filter models through research on some freedom and practical filters. You will know how these filters work and what you can do with them. Finally, Jason introduced his own multiple request filters that he was uploaded to the simplified file.
In "Servlet 2.3: New Features Exposed," I introduced the changes in Servlet API 2.3 and give a simple servlet filter model. In subsequent articles, I will explore the servlet filter, and these servlet filters you see can be downloaded from the Web. For each filter, I will see what it is doing, how to work, and where you can get it.
You can use this article in both cases: learning the functions of the filter, or as auxiliary when you write the filter. I will start from a few simple examples and continue more advanced filters. Finally, I will introduce you to the upload filter that I write in order to support multiple requests.
Servlet filter
Maybe you are still unfamiliar, one filter is an object that can transmit requests or modify the response. The filter is not a servlet, they don't actually create a request. They are the request to reach a pre-procedure before a servlet, and / or respond to the post-handler after leaving the servlet. Just as you will see in the following example, a filter can:
· Intercept the call before a servlet is called
· Check the request before a servlet is called
· Modify request head and request data for customizable request objects in actual requests
· Modify the response header and response data for customizable response in the actual response
· Intercepted this call after a servlet is called
You can filter one or more servlets with a filter for one or a set of servlets, zero or more filters. One filter implements the java.servlet.filter interface and defines the three methods of it:
1. Void Init (FilterConfig Config) THROWS ServletException: Call before the filter is executed to set the filter configuration object.
2. Void Destroy (); called it after the filter is executed.
3. Void Dofilter (ServletRequest Req, ServletResponse Res, Filterchain Chain "throws ioException, servletexception; performs actual filtering.
The server calls init (filterConfig) to prepare a filter for the service, and then call DOFILTER () at any time requested to use a filter. The FilterConfig interface retrieves the filter name, initialization parameters, and the active servlet context. The server calls Destory () to indicate that the filter has ended the service. The life cycle of the filter is very similar to the lifecycle of the serverT - recently changed in the Servlet API 2.3 final release. Previously, use the setfilterconfig (filter) method to set the lifecycle.
In the DOFILTER () method, each filter accepts the current request and response, while filter filters containing filters must still be processed. In the DOFILTER () method, the filter can do everything it wants to do for the request and response. (Just as I discussed later, collect data by calling them, or add new behaviors to the object.) Filter call
Chain.dofilter () transmits the control to the next filter. When this call returns, the filter can do other work in its DOFILTER () method; for example, it can log responsive information. If the filter wants to terminate the request or complete control of the response, he may not call the next filter. Step by step
If you want to really understand the filter, you should look at them in the actual application. The first filter we will see is simple and useful, which records the duration of all requests. Named an ExampleFilter in Tomcat 4.0 release. code show as below:
Import java.io. *;
Import javax.servlet. *;
Import javax.servlet.http. *;
Public class timerfilter implements filter {
PRIVATE FILTERCONFIG CONFIG = NULL;
Public void init (filterconfig config) throws servletexception {
THIS.CONFIG = Config;
}
Public void destroy () {
CONFIG = NULL;
}
Public Void Dofilter (ServletRequest Request, ServletResponse Response,
Filterchain chain) throws oException, servletexception {
Long before = system.currenttimemillis ();
Chain.dofilter (Request, Response);
LongAfter = system.currenttimemillis ();
String name = ""
IF (Request InstanceOf HttpServletRequest) {
Name = (httpservletRequest) Request .getRequesturi ();
}
Config.getServletContext (). log (name ": (after - before) " ms ");
}
}
When the server calls init (), the filter saves the configuration class with a CONFIG variable, which will be used in the later DOFILTER () method to change servletContext. When dofilter () is called, the filter calculation request occurs when the request is executed. The filter is well demonstrated before and after the request. Note that the parameters for the DOFILTER () method are not HTTP objects, so you must convert the request to the httpservletRequest type when calling the HTTP-specific GetRequesturi () method.
With this filter, you must also deploy it with the
filter>
This will notify the server A filter called Timerfiter is implemented from the Timerfiter class. You can register a filter using the determined URL schema or servelT named using the
This configuration makes the filter all the request (static or dynamic) of the server, is the timing filter we need. If you connect a simple page, the record output may be as follows:
2001-05-25 00:14:11 /timer/index.html: 10ms
In Tomcat 4.0 Beta 5, you can find the record file in Server_Root / logs /.
This filter's WAR file is downloaded from this:
http://www.javaworld.com/jw-06-2001/filters/timer.war
Who is on your website? what are they doing?
Our next filter is a Clickstream filter written by OpenSymphony members. This filter tracks user requests (such as: click) and request queues (such as: clicking on flow) to display the network administrator on her website and each user is accessing that page. This is an open source library using LGPL.
In the Clickstream package, you will find a ClickstreamFilter class that captures request information, a Clickstream class like an operation structure to save data, and a ClickstreamLogger class that saves sessions and context events to combine all things together. There is also a Botchecker class to determine if the client is a robot (simple logic, like "whether they are requests from robots.txt?"). A Clickstreams.jsp summary page is provided in this package and a ViewStream.jsp detailed page to view the data.
Let's take a look at the Clickstreamfilter class. All these examples have made some slight modifications to format and modify some portability issues, which will be later.
Import java.io.ioException;
Import javax.servlet. *;
Import javax.servlet.http. *;
Public Class ClickStreamfilter Implements Filter {
Protected filterconfig filter;
PRIVATE FINAL STATIC STRING FILTER_APPLIED = "_Clickstream_filter_Applied";
Public void init (filterconfig config) throws servletexception {
THIS.FILTERCONFIG = FilterConfig;
}
Public Void Dofilter (ServletRequest Request, ServletResponse Response,
Filterchain chain) throws oException, servletexception {
/ / Make sure the filter is only used once in each request.
IF (Request.GetaTribute (Filter_Applied) == NULL) {
Request.setttribute (Filter_Applied, Boolean.true);
HttpSession session = (httpservletRequest) Request .getSession ();
ClickStream Stream = (Clickstream) Session.GetaTribute ("ClickStream");
Stream.addRequest ((httpservletRequest);
}
// Pass request
Chain.dofilter (Request, Response);
Public void destroy () {}
}
The DOFILTER () method obtains the user's session, gets Clickstream from it, and adds the current request data to the Clickstream. Among them uses a special filter_Applied tag property to label whether this filter has been used by the current request (may occur in request schedule) and ignore all other filter behavior. You may be confused with how to know Clickstream properties in the current session. That is because ClickStreamLogger has set it when the session is at the beginning. ClickStreamLogger code:
Import java.util. *;
Import javax.servlet. *;
Import javax.servlet.http. *;
Public Class ClickStreamlogger Implements ServletContextListener,
HttpSessionListener {
Map clickstreams = new hashmap ();
Public ClickStreamLogger () {}
Public void contextinitialized (servletContextevent SCE) {
Sce.getServletContext (). SetAttribute ("Clickstreams", Clickstreams;
}
Public void contextdestroyed (servletContextEvent SCE) {
Sce.getServletContext (). SetAttribute ("ClickStreams", NULL;
}
Public void sessioncreated (httpsessioneverent hse) {
HttpSession session = hse.getsession ();
Clickstream ClickStream = new clickstream ();
Session.setttribute ("Clickstream", clickstream);
ClickStreams.Put (session.getid (), clickstream);
}
Public void sessionDestroyed (httpsessioneverent hse) {
HttpSession session = hse.getsession ();
ClickStream Stream = (Clickstream) Session.GetaTribute ("ClickStream");
ClickStreams.Remove (session.getid ());
}
}
Logger (Recorder) Gets the application event and will use them to help everything. When Context is created, Logger places a shared stream MAP in Context. This makes the Clickstream.jsp page know which stream is currently active. In Context destruction, Logger removes this MAP. When a new visitor creates a new session, Logger places a new ClickStream instance into this session and adds this Clickstream into the center stream Map. When the session is destroyed, the stream is removed from the central map from the central map.
The following Web.xml Deployment Description Clip Writes all things on a piece:
filter-mapping>
filter-mapping>
listener>
This registers the request for Clickstreamfilter and sets it handles * .jsp and * .html. This also registers ClickstreamLogger as a listener to accept them when applying events.
Two JSP pages take Clickstream data from the session and the Context object and use the HTML interface to display the current state. The following ClickStream.jsp file shows the probably:
<% @ Page Import = "java.util. *"%>
<% @ Page Import = "ClickStream"%>
<%
Map clickstreams = (map) Application.getaTRibute ("ClickStreams");
String showbots = "false";
IF (Request.GetParameter ("Showbots")! = null) {
IF (Request.getParameter ("Showbots"). Equals ("True"))
Showbots = "True";
Else IF ("Showbots"). Equals ("Both"))
Showbots = "Both";
}
%>
no bots |
all Bots |
<% IF (clickstreams.keyset (). size () == 0) {%>
No Clickstreams in Progress
<%}%>
<%
Iterator it = clickstreams.keyset (). Itrator ();
INT count = 0;
While (it.hasnext ()) {
String Key = (String) it.next (); ClickStream Stream = (Clickstream) ClickStreams.get (key);
IF (Showbots.equals ("False") && stream.isbot ()) {
CONTINUE;
}
Else IF (Showbots.equals ("True" &&! stream.isbot ()) {
CONTINUE;
}
COUNT ;
Try {
%>
<% = count%>.
stream.gethostname (): "stream")%> b>
<%
}
Catch (Exception E) {
%>
An Error Occurred - <% = E%>
<%
}
}
%>
This package is easy to download and install from OpenSymphony. Compile the Java file and put it
Under WEB-INF / CLASSES, place the JSP file into the web application path and press to help modify the web.xml file. In order to prevent arguments before these work, you can
Http://www.javaworld.com/jw-06-2001/filters/clickstream.war Find the WAR file of the package.
In order to make this filter work in Tomcat 4.0 Beta 5, I found that I have to do some slight changes. What I did showed some errors that are often easily made in the portability of servlet and filters, so I will listed them below:
· I have to add an additional import statement in JSP: <% @ page import = "Clickstream"%>. In Java, you don't need to import classes under the same package, and in the server, JSP is compiled into the default package, you don't need this to import. But on servers like Tomcat, JSP is compiled into a custom package, you have to import classes from the default package.
· I have to move
· I have to change the mapping in Web.xml from /*.html and /*.jsp to the correct * .html and * .jsp. Some servers will ignore the beginning of the beginning /, but Tomcat is tough, and there is no /.
· Finally, I have to upgrade the ClickstreamFilter class to the latest lifecycle API, change setFilterConfig () into a new init () and Destory () method.
The downloadable WAR file already contains these modifications and can run outside the package through the server, although I don't have a wide range of testing.
Compression response
The third filter is an automatic compression response output stream to improve bandwidth utilization and provide an example of a good packaging response object. This filter is written by Amy Roh from Sun, contributes to Tomcat 4.0's "Examples" web program. You will find the original code from WebApps / Examples / WEB-INF / CLASS / COMPRESSIONFILTERS. The example code here and the WAR have been edited more clearly and simpler. The policy of the CompressionFilter class is to check the request head to determine if the client supports compression. If support, the response object is packaged with a custom response, its getOutputStream () and getWriter () methods have been defined as the compressed Output stream. Use filters to allow such simple and efficient solutions.
We will start from init ():
Public void init (filterconfig filterconfig) {
CONFIG = FilterConfig;
CompressionthReshold = 0;
IF (FilterConfig! = NULL) {
String str = filterconfig.getinitParameter ("compressionthreshold");
IF (str! = null) {
Compressionthreshold = integer.parseint (STR);
}
Else {
CompressionthReshold = 0;
}
}
}
Note that the request must be converted to httpservletRequest before retrieving the request header, just want to be in the first example. Filter uses Wrapper COMPRESSRESPONSEWRAPPER, one from
The HTTPSERVLETRESPONSEWRAPPER class inherits the custom class. This Wrapper's code is relatively simple:
Public class compressionResponseWrapper Extends httpservletResponsewrapper {
Protected servletOutputStream Stream = NULL;
Protected printwriter write = null;
protected int threshold = 0;
protected httpservletResponse origismponse = null;
Public CompressionResponseWrapper (httpservletResponse response) {
Super (response);
OrigResponse = response;
}
Public void setcompressionthreshold (int threeshold) {
THIS.THRESHOLD = Threshold;
}
Public servletOutputStream CreateOutputStream () throws ioException {
Return (New CompressionResponsestream (OrigResponse);
}
Public servletoutputstream getOutputStream () throws oException {
IF (writer! = null) {
Throw new IllegalStateException ("GetWriter () Has Already Been"
"Called for this response");
}
IF (stream == null) {
stream = createoutputStream ();
}
(CompressionResponsestream) stream .SetCommit (TRUE);
(CompressionResponsestream) stream .SetBuffer (Threshold);
Return stream;
}
Public PrintWriter getWriter () throws oException {
IF (writer! = null) {
Return Writer;
}
IF (stream! = null) {
Throw new IllegalStateException ("GetOutputStream () Has Already"
"Been Called for this Response");
}
stream = createoutputStream ();
(CompressionResponsestream) stream .SetCommit (TRUE);
(CompressionResponsestream) stream .SetBuffer (Threshold);
Writer = New PrintWriter (stream);
Return Writer;
}
}
All call getOutputStream () or getWriter () returns a use
The object of the CompressResponseSstream class. The CompressionResponseSTRTEAM class is not displayed in this example because it is inherited in servletOutputStream and compresses the stream using the Java.util.zip.gzipOutputStream class.
This compressed filter has been pre-configured in advance in the "Examples" web program of Tomcat. Example Servlet Response / CompressionTestURL (determined the previous path is / examples). Use the useful WAR files I made, you can use / servlet / compressiontest to access this test servlet. You can use the following web.xml fragment to configure this test:
init-param>
filter>
filter-mapping>
CompressionTest
servlet-name>
CompressionTestServlet
servlet-class>
servlet>
CompressionTestServlet (not shown here) Output compression is available, if available, the output compression response is successful! // ~~~~~~~~~~ 9CBS How many words limit is there?
Please have an ax :)