Revised Section 4.3
The Java Servlet 2.3 specification provides servlet filtering which replaces
the servlet chaining of Section 4.3. JavaServer Pages (Section 4.6) may be
used instead of server-side includes. To use servlet filtering we install the
Tomcat servlet engine, obtained from jakarta.apache.org. It is the reference
implementation for the Java servlet specification. Tomcat 4.0 implements
the 2.3 specification. It may be used for all the examples in Chapter 4.
Installing Tomcat
Download Tomcat from
http://jakarta.apache.org/builds/jakarta-tomcat-4.0/nightly/
Set an envirnonment variable, CATALINA_HOME, to the path of the directory in
which Tomcat is installed. Start Tomcat using the command
%CATALINA_HOME%\bin\startup
Stop Tomcat using the command
%CATALINA_HOME%\bin\shutdown
To test, enter http://localhost:8080/ in the browser. The Tomcat homepage
should appear.
ServletFilters
A servlet filter can intercept a request, processing it before it
reaches the servlet. It can also process the servlet's response. We show an
example of each.
The Filter interface has three methods.
void init(FilterConfig config)
Called when the filter is placed in service.
void destroy()
Called when the filter is removed from service.
void doFilter(ServletRequest req, ServletResponse resp,
FilterChain chain)
Performs the filtering.
Filters use a FilterChain to invoke the next filter in the chain. The
FilterChain interface provides the method
void doFilter(ServletRequest req, ServletResponse resp)
The FilterConfig interface represents an object that can be used to pass
information to a filter during initialization.
Filtering a Request
In RequestFilter.java, we check if the request provides an Accept header.
If it does not, we refuse the request, otherwise we pass it on to the servlet.
package request;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class RequestFilter implements Filter {
private FilterConfig fc = null;
public void init(FilterConfig f) {
fc = f;
}
public void destroy() {
fc = null;
}
public void doFilter(ServletRequest req,
ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
if (((HttpServletRequest)req).getHeader("Accept") == null) {
PrintWriter pw = resp.getWriter();
pw.println("Can't help you today");
return;
}
chain.doFilter(req, resp);
}
}
Deploying a Filter
Create a directory named "request" in
%catalina-home%\webapps\examples\WEB-INF\classes
Compile RequestFilter.java using
javac -classpath %catalina_home%\common\lib\servlet.jar
request\RequestFilter.java
Edit the configuration file web.xml in the examples\WEB-INF directory to
include
RequestFilter
request.RequestFilter
in the section with the other tags. Include
RequestFilter
/*
in the section with the other tags. The URL pattern "/*"
means that the filter will apply to all requested URLs.
Restart Tomcat after changing web.xml.
Using RequestFilter
To test RequestFilter we first deploy the Welcome servlet of Example 4.1
by copying Welcome.class to
%catalina-home%\webapps\examples\WEB-INF\classes
Entering
http://localhost:8080/examples/servlet/Welcome
in a browser will produce the message of Figure 4.1.
However using the VerySimpleBrowser of Example 2.8
java VerySimpleBrowser localhost 8080
/examples/servlet/Welcome
produces
Connected to host localhost/127.0.0.1
Can't help you today
because VerySimpleBrowser does not send an Accept header.
Filtering a Response
We redo the servlet chaining example using a servlet filter. The
LuckyWelcome servlet of Example 4.6 uses a non-standard tag. Using
servlet chaining, the LuckyTag servlet of Example 4.7 processes the repsonse
of Example 4.6 to interpret the tag. Here we use a servlet filter for
that purpose.
Because we are not using a MIME filter, we change Example 4.6 to set the
content type to text/html instead of custom/lucky. We place it in a package
named lucky, creating a directory by that name in examples\WEB-INF\classes.
The filter simply wraps the servlet response and passes it to the next
filter, if any, in the chain.
package lucky;
import java.io.*;
import javax.servlet.*;
public class LuckyFilter implements Filter {
private FilterConfig fc = null;
public void init(FilterConfig f) {
fc = f;
}
public void destroy() {
fc = null;
}
public void doFilter(ServletRequest req,
ServletResponse resp, FilterChain chain)
throws ServletException, IOException {
LuckyWrapper luckyWrap = new LuckyWrapper(resp);
chain.doFilter(req, luckyWrap);
}
}
The LuckyWrapper class extends HttpServletResponseWrapper to be able to
transform the response. It overrides the getWriter method to return a
LuckyWriter rather than the default Writer associated with the response.
package lucky;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class LuckyWrapper extends HttpServletResponseWrapper {
private PrintWriter luckyWriter;
public LuckyWrapper(ServletResponse resp) {
super((HttpServletResponse)resp);
try {
luckyWriter = new LuckyWriter(resp.getWriter());
}catch(IOException e) {
e.printStackTrace();
}
}
public PrintWriter getWriter() throws IOException {
return luckyWriter;
}
}
The LuckyWriter class overides the println method to intercept the
tag and replace it by six lucky numbers, which will be sent to the client.
package lucky;
import java.io.*;
public class LuckyWriter extends PrintWriter {
public LuckyWriter(OutputStream o) {
super(o);
}
public LuckyWriter(PrintWriter p) {
super(p);
}
public void println(String line) {
int index = line.toUpperCase().indexOf("");
if(index == -1)
super.println(line);
else {
super.println("Your lucky numbers are:
");
for(int i=0; i<6; i++)
super.println((int)(51*Math.random()+1)+ " ");
super.println("
");
}
}
}
Deploying LuckyFilter
Create a directory named "lucky" in
%catalina-home%\webapps\examples\WEB-INF\classes
Compile LuckyFilter.java, LuckyWrapper.jav, LuckyWriter.java, and
LuckyWelcome.java using
javac -classpath %catalina_home%\common\lib\servlet.jar lucky\Lucky*.java
Edit the configuration file web.xml in the examples\WEB-INF directory to
include
LuckyFilter
lucky.LuckyFilter
in the section with the other tags. Include
LuckyFilter
/lucky/*
in the section with the other tags. The URL pattern
"/lucky/*" means that the filter will apply to all requested URLs which
include "lucky" before the servlet requested. In this way we can isolate the
servlets that use the tag and not waste time using the filter on
other servlets. Restart Tomcat after changing web.xml.
We want to use the LuckyWelcome servlet with the /lucky prefix so the
request will trigger the filter. To do that we modify web.xml to include
LuckyWelcome
lucky.LuckyWelcome
in the section and
LuckyWelcome
/lucky/welcome
in the section.
Entering
http://localhost:8080/examples/lucky/welcome
in the browser will produce output like that shown in Figure 4.14.