[ Team LiB ] |
Recipe 11.11 Using a Filter to Monitor Session AttributesProblemYou want to use a filter to check a session attribute prior to the request reaching a servlet. SolutionCreate a Java class that implements javax.servlet.Filter, write session-related code in the class's doFilter( ) method, then configure the filter in your deployment descriptor. DiscussionFilters, as their name suggests, are semipermeable barriers through which requests to your web application must pass before they reach servlets, JSPs, or even static content. Filters are technically Java classes that implement the javax.servlet.Filter interface. A filter can have a look at the ServletRequest and ServletResponse objects before these objects find their way to a servlet's service methods (which include service( ), doGet( ), and doPost( )). Filters can initiate authentication, logging, encryption, database actions, caching, and just about any other task that passes through request and response objects. Filters are configured in web.xml. In Example 11-18, a filter checks a logged-in HttpSession attribute, and logs its activities by calling the ServletContext object's log( ) method. This filter is mapped to a servlet registered in web.xml as MyServlet. Any requests to the MyServlet servlet cause the SessionFilter.doFilter( ) method to be called. Example 11-17 shows the relevant entries in web.xml. Example 11-17. Configuring a filter in web.xml<!-- the beginning of web.xml goes here --> <filter> <filter-name>SessionFilter</filter-name> <filter-class>com.jspservletcookbook.SessionFilter</filter-class> </filter> <filter-mapping> <filter-name>SessionFilter</filter-name> <servlet-name>MyServlet</servlet-name> </filter-mapping> <!-- more filters or listener classes added here --> <servlet> <servlet-name>MyServlet</servlet-name> <servlet-class>com.jspservletcookbook.MyServlet</servlet-class> </servlet> <!-- deployment descriptor continues ...--> The filter element specifies the filter's registered name and its fully qualified Java class. You package the filter class with the rest of the web application by placing the class in WEB-INF/classes or in a JAR file in WEB-INF/lib. The filter-mapping element maps the filter to the servlet registered in the deployment descriptor as MyServlet. Filters can also be mapped to URL patterns (Chapter 20 explains this syntax in detail). Example 11-18 is the source code for com.jspservletcookbook.SessionFilter. Example 11-18. A filter that snoops on session informationpackage com.jspservletcookbook;
import javax.servlet.*;
import javax.servlet.http.*;
public class SessionFilter implements Filter {
private FilterConfig config;
//Creates new SessionFilter
public SessionFilter( ) {}
public void init(FilterConfig filterConfig) throws ServletException{
System.out.println("Instance created of "+getClass( ).getName( ));
this.config = filterConfig;
}
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws java.io.IOException, ServletException {
HttpSession session = ((HttpServletRequest) request).getSession( );
ServletContext context = config.getServletContext( );
/* use the ServletContext.log method to log
filter messages */
context.log("doFilter called in: " + config.getFilterName( ) +
" on " + (new java.util.Date( )));
// log the session ID
context.log("session ID: " + session.getId( ));
// Find out whether the logged-in session attribute is set
String logged = (String) session.getAttribute("logged-in");
if (logged == null)
session.setAttribute("logged-in","no");
//log a message about the log-in status
context.log("log-in status: "+
(String)session.getAttribute("logged-in"));
context.log("");
chain.doFilter(request,response);
}
public void destroy( ){
/*called before the Filter instance is removed
from service by the web container*/
}
}
The init( ) method displays a console message when its instance is created by the web container. The javax.servlet.FilterConfig object is used to get the ServletContext object for this filter (by calling FilterConfig.getServletContext( )). The ServletContext.log( ) method is used to log messages from the filter. These messages can then be read in the server logs. In Tomcat, look in the <Tomcat-install-directory>/logs directory for log files with names such as localhost_home_log.2003-01-24.txt. Here is an example of the log entries for this filter: 2003-01-24 11:56:09 doFilter called in: SessionFilter on Fri Jan 24 11:56:09 EST 2003 2003-01-24 11:56:09 session ID: E04DE93D9B88A974ED2350BCF7945F34 2003-01-24 11:56:09 log-in status: no The filter gets access to the session with this code: HttpSession session = ((HttpServletRequest) request).getSession( ); Since the doFilter( ) method has a ServletRequest parameter type, and not a HttpServletRequest type, the request parameter has to be cast to the latter type so that the code can call the request.getSession( ) method.
Once the filter has access to the session object, it looks for a certain session attribute (logged-in). If session.getAttribute("logged-in") returns null, this attribute is added to the session with the value "no". The code then calls chain.doFilter(request,response) inside of the filter's doFilter( ) method. This method call on the FilterChain object ensures that the request and response are passed along to the next filter on the chain, or, in the absence of any more mapped filters, to the targeted web resource. Example 11-19 shows the doGet( ) method of the MyServlet servlet that the filter in Example 11-18 is mapped to. Example 11-19. doGet method of a servlet to which a filter is mappedpublic void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { response.setContentType("text/html"); java.io.PrintWriter out = response.getWriter( ); HttpSession session = request.getSession( ); String logged = (String) session.getAttribute("logged-in"); out.println("<html>"); out.println("<head>"); out.println("<title>Filter Servlet</title>"); out.println("</head>"); out.println("<body>"); out.println("<h2>Session Logged in Info</h2>"); out.println("logged in : " + logged+ "<br><br>"); out.println("</body>"); out.println("</html>"); } This servlet checks the logged-in session attribute and displays its value, as shown in Figure 11-7.
Figure 11-7. Checking a session object after a filter has altered itA filter can take a number of actions with a session object before it reaches a servlet or JSP that does session tracking, such as add, remove, or change session attributes. It can also alter the session's timeout period (with the HttpSession.setMaxInactiveInterval(int seconds) method) based on an attribute of the session or request. See AlsoChapter 19 on using filters; Recipe 11.4 on checking the validity of a session; Chapter 1 on web.xml; Chapter 7 of the Servlet v2.3 and 2.4 specifications on sessions; the javax.servlet.http.HttpSession API at http://java.sun.com/j2ee/sdk_1.3/techdocs/api/javax/servlet/http/HttpSession.html; Chapter 1 on web.xml; Chapter 6 of the Servlet v 2.3 and 2.4 specifications on filtering. |
[ Team LiB ] |