Creating a Simple Filter


A lot of filter technology is needed to build WebLogger, so to get familiar with that, let's take a look at an example. WebLogger works with both the request object holding the data sent from the browser and the response object sending data back to the browser. So how do you work with, for example, the response object to send data back to the browser? Say that you want to filter access to a JSP page named simple.jsp and that you want a filter to add some text to the output of this JSP sent back to the browser. Here's what that JSP page looks likeas it stands, all this page does is to display the text "Using a filter" in an <H1> HTML header:

 <HTML>     <HEAD>         <TITLE>Using a filter</TITLE>     </HEAD>     <BODY>         <H1>Using a filter</H1>         <BR>     </BODY> </HTML> 

Because you have access to the data sent to and from this JSP page in a filter, you can display your own text in the web page, as you can see in Figure 6.2. In this figure, a filter attached to simple.jsp wrote the text "The filter wrote this," just as WebLogger added the warning about logging user access shown at the bottom of Figure 6.1. Note that the URL still points to simple.jsp; there's nothing to indicate that the page is being filtered. Very cool.

Figure 6.2. Adding text to a web page with a filter.


Writing the Code

So how do you create the filter to make this work? The filter here will be called Simple.java, and it will implement the Filter interface:

 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Simple implements Filter {         .         .         . } 

To implement this interface, you need the doFilter, init, and destroy methods:

 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Simple implements Filter {   public void doFilter(ServletRequest request, ServletResponse response,     FilterChain chain)     throws IOException, ServletException   {     .     .     .   }   public void destroy()   {     .     .     .   }   public void init(FilterConfig filterConfig)   {     .     .     .   } } 

The init method is called when the filter is first initialized, and the destroy method is called when it's destroyed. The doFilter method is where the real action is; when the user is trying to access the web resource you're filtering, this is the method that will be called.

The doFilter method is passed the request and response objects that Java uses to work with web resources; the request object holds the data sent to the web resource by the browser, and the response object holds the data the web resource sends back to the browser.

These objects are of the ServletRequest class (not the HttpServletRequest class you saw in Chapter 5, "Chatting on the Internet with the Chat Room") and the ServletResponse class, respectively, and you can see the significant methods of these classes in Table 6.2 and 6.3.

Table 6.2. Significant Methods of the javax.servlet.http.ServletRequest Class

Method

Does This

java.lang.Object getAttribute(java.lang.String name)

Returns the value of the named attribute

java.util.Enumeration getAttributeNames()

Returns a Java Enumeration holding the names of the attributes in the request

java.lang.String getCharacterEncoding()

Returns the character encoding used in the request's body

int getContentLength()

Returns the length of the request body. Returns -1 if the length is not known

java.lang.String getContentType()

Returns the MIME type of the body of the request

java.util.Locale getLocale()

Returns the locale of the client browser

java.util.Enumeration getLocales()

Returns a Java Enumeration of Locale objects giving the preferred locales of the client

int getLocalPort()

Returns the IP port number where the request was received

java.lang.String getParameter(java.lang.String name)

Returns the value of a request parameter, such as the contents of an HTML control

java.util.Enumeration getParameterNames()

Returns a Java Enumeration holding the names of the parameters contained in this request.

java.lang.String[] getParameterValues(java.lang.String name)

Returns an array of strings holding the values in the specified request parameter

java.io.BufferedReader getReader()

Returns the body of the request using a BufferedReader

java.lang.String getRemoteAddr()

Returns the IP address of the client that sent the request

java.lang.String getRemoteHost()

Returns the name of the client that sent the request

int getRemotePort()

Returns the IP port of the client that sent the request

java.lang.String getScheme()

Returns the name of the Internet scheme of this request, such as HTTP, HTTPS, or FTP

java.lang.String getServerName()

Returns the name of the server where the request was sent

int getServerPort()

Returns the port number where the request was sent

boolean isSecure()

Returns TRue if this request was made using a secure channel, such as HTTPS

void removeAttribute(java.lang.String name) void setAttribute(java.lang.String name, java.lang.Object o)

Removes an attribute from this request Stores an attribute in this request


Table 6.3. Significant Methods of the javax.servlet.http.ServletResponse Class

Method

Does This

void flushBuffer()

Flushes any content in the buffer so it is written to the client browser

int getBufferSize()

Returns the buffer size used for the response, in bytes

java.lang.String getCharacterEncoding()

Returns the name of the encoding used in the body of this response

java.lang.String getContentType()

Returns the content type used for the MIME body sent in this response

java.util.Locale getLocale()

Returns the locale given for this response

ServletOutputStream getOutputStream()

Returns a ServletOutputStream you can use for writing binary data to the client

java.io.PrintWriter getWriter()

Returns a PrintWriter object you can use to send text to the client

void reset()

Resets any data in the buffer, including the status code and headers

void resetBuffer()

Resets the data in the buffer, without resetting the status code and headers

void setBufferSize(int size)

Sets the preferred buffer size for the response

void setCharacterEncoding(java.lang.String charset)

Sets the character encoding of the response, such as UTF-8

void setContentLength(int len)

Sets the length of the content in the response

void setContentType(java.lang.String type)

Sets the content type

void setLocale(java.util.Locale loc)

Sets the locale of the response


Besides the request and response objects, you're also passed a FilterChain object in doFilter. This object provides you with access to the filtered resourceor to other filters that have been added between the current filter and the filtered resource.

In Java-enabled web servers, you can stack filters in a filter chain, where control goes to the first filter, then the next, and the next, and so on, all the way to the filtered resource, such as a JSP page, servlet, or an HTML page. You don't have to know about any other possible filters, though; you can simply call the doFilter method of the FilterChain object passed to you. You pass this method both the request and response objects that were passed to you, as shown here:

 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Simple implements Filter {   public void doFilter(ServletRequest request, ServletResponse response,     FilterChain chain)     throws IOException, ServletException   {       chain.doFilter(request, response);         .         .         .   }   public void destroy()   {   }   public void init(FilterConfig filterConfig)   {   } } 

When you call the FilterChain object's doFilter method, the next filter, if there is one, is called, followed by any other filters, and then the filtered resource itself. Control returns in the reverse order back to your filter, where you get your hands on the response object again. And that lets you write text in the response sent back to the browser, as WebLogger does. To start, you configure the MIME type of text you're going to send to the browser, setting it to "text/html":

 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Simple implements Filter {   public void doFilter(ServletRequest request, ServletResponse response,     FilterChain chain)     throws IOException, ServletException   {       chain.doFilter(request, response);       response.setContentType("text/html");         .         .         .   }   public void destroy()   {   }   public void init(FilterConfig filterConfig)   {   } } 

Now you can add your own text to the web page being sent back to the browser, using the response object. In particular, you use the getWriter method to get a PrintWriter object, and then you can use the println method of that object to send the message "The filter wrote this.":

 import java.io.*; import javax.servlet.*; import javax.servlet.http.*; public class Simple implements Filter {   public void doFilter(ServletRequest request, ServletResponse response,     FilterChain chain)     throws IOException, ServletException   {       chain.doFilter(request, response);       response.setContentType("text/html");       PrintWriter out = response.getWriter();       out.println("The filter wrote this.");   }   public void destroy()   {   }   public void init(FilterConfig filterConfig)   {   } } 

Configuring the Web Server

That completes the code for this filter. To compile this file, add a new directory named logger for this chapter's project to Tomcat's webapps directory, then add a directory named WEB-INF under logger, and two empty directories, classes and lib, under WEB-INF:

 webapps | | -logger     |     | -WEB-INF         |         | -classes         | -lib 

Place simple.jsp (the resource to be filtered) in the logger directory, and place Simple.java (the filter) in the classes directory. Next, copy jsp-api.jar and servlet-api.jar, the needed JAR files for this project, from the Tomcat common\lib directory to the classes directory and add them to the classpath:

 %set classpath=jsp-api.jar;servlet-api.jar;. 

Then compile Simple.java (add the necessary path to javac.exe if needed):

 %javac Simple.java 

This creates Simple.class, the compiled filter, ready to be used.

Next, you have to connect the filter to the resource you want to filter, which you do with the deployment descriptor file, web.xml. This file connects the filtered resource to the filter you want to use, and you store this file in the WEB-INF directory.

Because it's an XML document, web.xml starts with an XML declaration, followed by a <!DOCTYPE> element that indicates where software can find the syntax used in web.xml files to check what you've written. This part is standard, and it starts all web.xml files:

 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"     "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd">         .         .         . 

To group the filter together with the resource it filters, you use a <web-app> element in web.xml:

 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"     "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"> <web-app>         .         .         . </web-app> 

In the <web-app> element, you install a filter with the <filter> element, which encloses two other elements, <filter-name> and <filter-class>:

 <filter>   <filter-name>   <filter-class> </filter> 

The <filter-name> element holds the name you want to give to the filter ("Simple Filter" in this example) and connects that name to the Java .class file for the filter, Simple.class, in the <filter-class> element. It all looks like this in web.xml:

 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"     "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"> <web-app>   <filter>     <filter-name>Simple Filter</filter-name>     <filter-class>Simple</filter-class>   </filter>         .         .         . </web-app> 

Having told the web server which Java class to use for the filter, you have to tell it which web resource you want to filter access to. That's simple.jsp here, and you connect this newly declared filter, "Simple Filter," to simple.jps using a <filter-mapping> element, which encloses these elements:

 <filter-mapping>   <filter-name>   <url-pattern> </filter-mapping> 

Here, <filter-name> is the name of a filter you've declared in a <filter> element (the <filter> element must come before the <filter-mapping> element), and <url-pattern> is the URL of the resource you want to filter:

 <?xml version="1.0" encoding="ISO-8859-1"?> <!DOCTYPE web-app     PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"     "http://java.sun.com/j2ee/dtds/web-app_2_3.dtd"> <web-app>   <filter>     <filter-name>Simple Filter</filter-name>     <filter-class>Simple</filter-class>   </filter>   <filter-mapping>     <filter-name>Simple Filter</filter-name>     <url-pattern>/simple.jsp</url-pattern>   </filter-mapping> </web-app> 

Note especially that the URL in <url-pattern> can use the * wildcard, so you can filter multiple pages with the same filter. For example, <url-pattern>/*</url-pattern> will filter all the web resources in the logger directory.

That's all you need. Because you've changed web.xml and created a new .class file in the webapps directory, you need to restart Tomcat before it'll be able to use simple.jsp and apply your new filter. After you restart Tomcat, navigate to http://localhost:8080/logger/simple.jsp. You should see the results displayed in Figure 6.2. After testing a filter like this, you can install it on any Java-enabled web server, ready for use by users around the world.



    Java After Hours(c) 10 Projects You'll Never Do at Work
    Java After Hours: 10 Projects Youll Never Do at Work
    ISBN: 0672327473
    EAN: 2147483647
    Year: 2006
    Pages: 128

    Similar book on Amazon

    flylib.com © 2008-2017.
    If you may any questions please contact us: flylib@qtcs.net