Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 113 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
113
Dung lượng
1,83 MB
Nội dung
4. Now map the filter to the page whose access you want to be logged. In this case, HTMLPage (see Figure 12.21). 540 Day 12 F IGURE 12.21 deploytool Filter Mapping. The following deployment descriptor entry shows the AuditFilter mapped to the HTMLPage: <filter-mapping> <filter-name>AuditFilter</filter-name> <servlet-name>HTMLPage</servlet-name> </filter-mapping> 5. Deploy the application. Now, every time the HTMLPage is accessed, the counter will be incremented and logged. The log file will be found in your J2EE installation directory under logs\<machine name>\web. There will probably be a number of log files in this directory; look for the one with the latest date on it. Note At the end of the log file you should see something like the following: HTMLPage: init The number of hits is: 1 The number of hits is: 2 The number of 15 0672323842 CH12 3/20/02 9:34 AM Page 540 Servlets 541 12 Another way to see if the filter is working is to amend the HTMLPage code to output the counter, as shown in Listing 12.10. LISTING 12.10 HTMLPage with Counter Added 1: import java.io.*; 2: import javax.servlet.*; 3: import javax.servlet.http.*; 4: 5: public class HTMLPage extends HttpServlet { 6: 7: public void doGet(HttpServletRequest req, HttpServletResponse res) 8: throws ServletException, IOException { 9: res.setContentType (“image/gif”); 10: PrintWriter out = res.getWriter(); 11: out.println (“<HTML>”); 12: out.println (“<HEAD><TITLE>Filtered Servlet</TITLE></HEAD>”); 13: out.println (“<BODY>”); 14: out.println (“<H1>A Generated HTML Page with a Filter attached</H1>”); 15: Integer counter = ➥(Integer)getServletContext().getAttribute(“Counter”); 16: out.println (“<P>This page has been accessed “ + ➥counter + “ times</P>”); 17: out.println (“</BODY>”); 18: out.println (“</HTML>”); 19: } 20: } This was a very simple example, more sophisticated filters can be used to modify the request or the response. To do this, you must override the request or response methods by wrapping the request or response in an object that extends HttpServletRequestWrapper or HttpServletResponseWrapper. This approach follows the well-known Wrapper or Decorator pattern technique. Patters will be described in detail on Day 18, “Patterns.” Event Listening A servlet can be designated as an event listener. This enables the servlet to be notified when some external event or change has occurred. There are a number of listener interfaces that you can implement in your servlet. All the listener interfaces extend java.util.EventListener. Table 12.6 provides a list of the listener interfaces. 15 0672323842 CH12 3/20/02 9:34 AM Page 541 TABLE 12.6 Servlet Event Listener Interfaces Listener Interface Notification HttpSessionActivationListener When a session is activated or passivated HttpSessionAttributeListener When a session attribute is added, removed, or replaced HttpSessionListener When a session is created or destroyed ServletContextAttributeListener When a servlet context attribute is added, removed, or replaced ServletContextListener About changes to servlet context, such as context initial- ization or the context is to be shut down The listener classes are often used as a way of tracking sessions within a Web applica- tion. For example, it is often useful to know whether a session became invalid because the Web server timed out the session or because a Web component within the application called the invalidate() method. In the filter section, we incremented a counter each time the application was accessed. The servlet filter code had to check that the counter existed before incrementing it. The following ServletContextListener (see Listing 12.11) sets up the counter when the context is initialized before any request is processed. The ServletContextListener interface has two methods: • contextInitialized() This receives notification that the application is ready to process requests. • contextDestroyed() This is notified that the context is about to be shut down. LISTING 12.11 Servlet Listener to Initialize Counter 1: import javax.servlet.*; 2: import javax.servlet.http.*; 3: 4: public class Listener extends HttpServlet ➥implements ServletContextListener { 5: 6: private ServletContext context = null; 7: 8: public void contextInitialized(ServletContextEvent event) { 9: context = event.getServletContext(); 10: 11: Integer counter = new Integer(0); 12: context.setAttribute(“Counter”, counter); 13: context.log(“Created Counter”); 14: } 15: 542 Day 12 15 0672323842 CH12 3/20/02 9:34 AM Page 542 Servlets 543 12 16: public void contextDestroyed(ServletContextEvent event) { 17: event.getServletContext().removeAttribute(“Counter”); 18: } 19: } Deploying the Listener Go through the following steps to deploy the listener class in the Servlets application. 1. Add a new Web component to the Servlets application. On the component page, check the Event Listeners box to indicate that this is an event listener class (see Figure 12.22). As with a filter, there is no need to give the listener servlet a compo- nent alias because it is not called directly. LISTING 12.11 Continued FIGURE 12.22 deploytool Choose Component Type— Event Listeners. 2. With the Servlets application highlighted in the left window, select the Event Listeners tab (see Figure 12.23). 3. Add the Listener class to the event listeners (see Figure 12.24). The following will then be added to the Servlets deployment descriptor: <listener> <listener-class>Listener</listener-class> </listener> 15 0672323842 CH12 3/20/02 9:34 AM Page 543 4. Deploy the application. Because the listener initializes the counter to 0, and this is guaranteed to be called before any servlet code, you can now simplify the AuditFilter code and remove the check for a null counter (see Listing 12.12). 544 Day 12 F IGURE 12.23 deploytool Event Listeners. FIGURE 12.24 deploytool Event Listeners. 15 0672323842 CH12 3/20/02 9:34 AM Page 544 Servlets 545 12 LISTING 12.12 Amended AuditFilter Code Showing New doFilter() Method 1: public void doFilter(ServletRequest req, ServletResponse res, ➥FilterChain chain) throws IOException, ServletException { 2: if (filterConfig == null) 3: return; 4: StringBuffer buf = new StringBuffer(); 5: buf.append (“The number of hits is: “); 6: synchronized (this) { 7: Integer counter = ➥(Integer)filterConfig.getServletContext().getAttribute(“Counter”); 8: counter = new Integer(counter.intValue() + 1); 9: buf.append (counter.toString()); 10: filterConfig.getServletContext().log(buf.toString()); 11: filterConfig.getServletContext().setAttribute(“Counter”, counter); 12: } 13: chain.doFilter(req, res); 14: } Servlet Threads In the AuditFilter example, several lines of code were encased in a synchronize block. This was done to ensure that the counter would be correctly incremented if more than one access is made to the page at the same time. Without the synchronize block, it is pos- sible for two (or possibly more) servlet threads to obtain the counter value before it has been incremented, thereby losing one of the increments. In this case, failing to count one page hit is not a significant problem. There are other situations where it might be. Shared resources, such as files and databases, can also present concurrency issues when accessed by more than one servlet at a time. To avoid concurrency issues, a servlet can implement the single-thread model. The servlet init() method is only called once, so concurrency is not a prob- lem here. Note The servlet API specifies that a servlet container must guarantee that no two threads of a servlet that implements the javax.servlet.SingleThreadModel interface are run con- currently. This means the container must maintain a pool of servlet instances and dis- patch each new request to a free servlet; otherwise, only one request at a time can be handled. 15 0672323842 CH12 3/20/02 9:34 AM Page 545 If you want to make your servlet single threaded to prevent concurrency problems, sim- ply add the SingleThreadModel interface to the class signature. public class HTMLPage extends HttpServlet implements SingleThreadModel { Security and the Servlet Sandbox A servlet runs within the Web server and, if allowed, can access the file system and net- work or could even call System.exit() to shutdown the Web server. Giving a servlet this level of trust is not advisable, and most Web servers run servlets in a sandbox, which restricts the damage a rogue servlet could potentially cause. A servlet sandbox is an area where servlets are given restricted access to the server. Servlets running in the sandbox can be constrained from accessing the file system and network. This is similar to how Web browsers control applets. The implementation of the sandbox is server dependent, but a servlet in a sandbox is unlikely to be able to • Access server files • Access the network • Run commands on the server Agency Case Study You will now add a servlet to the Agency case study. The servlet sends the contents of the agency database tables to be displayed by a browser. The rows of the tables are for- matted as an HTML table. The servlet first outputs an HTML form on which the user selects the name of a table from a pull-down list (see Figure 12.25). After the user clicks the Submit Query button, the servlet displays the contents of this table on the same page. AgencyTable Servlet Code The AgencyTable servlet overrides the init() method to obtain the servlet context along with the JNDI context for the Agency EJB. The Agency EJB select() method is used in the doGet() method to obtain the rows of table data from the Agency database. public void init(){ context = getServletContext(); try { InitialContext ic = new InitialContext(); Object lookup = ic.lookup(“java:comp/env/ejb/Agency”); 546 Day 12 15 0672323842 CH12 3/20/02 9:34 AM Page 546 Servlets 547 12 AgencyHome home = (AgencyHome)PortableRemoteObject.narrow(lookup, ➥AgencyHome.class); agency = home.create(); } } FIGURE 12.25 AgencyTable form. The AgencyTable HTML page is generated in the following code. private final String tables = “<OPTION>Applicant<OPTION>ApplicantSkill ➥<OPTION>Customer<OPTION>Job<OPTION>JobSkill ➥<OPTION>Location<OPTION>Matched<OPTION>Skill”; out.println (“<HTML>”); out.println (“<HEAD><TITLE>” + agencyName + “ List Tables</TITLE></HEAD>”); out.println (“<BODY><FONT FACE=ARIAL COLOR=DARKBLUE”); out.println (“<H1><FONT SIZE=+3>” + agencyName + “ List Tables</FONT></H1>”); out.println (“<P>Select a table from the list to display the contents</P>”); out.println (“<FORM>”); out.println (“<SELECT NAME=\”tableList\” SIZE=1>” + tables + “</SELECT>”); out.println (“<INPUT TYPE=submit>”); out.println (“</FORM>”); out.println (“</FONT></BODY>”); out.println (“</HTML>”); The String variable tables contains the names of the database tables encoded in a HTML <OPTION> list. 15 0672323842 CH12 3/20/02 9:34 AM Page 547 The <SELECT> tag defines a parameter called tableList. This parameter is used to pass the name of the selected table from the form to the servlet. The following code checks to see if the parameter has been set. If it has, the outputTable() method is called. tableName = req.getParameter(“tableList”); if (tableName != null) { outputTable(out, tableName, res); In the outputTable() method, it is the agency.select bean that actually does the work. It returns a list of all the rows in the table. java.util.List query; // list of String[], first row = column names query = agency.select(tableName); The rows of the table are displayed as an HTML table so the columns line up correctly. The attributes to the HTML TABLE tag set the border and background colors, and the cell padding is increased to improve readability. Rows in a table are separated by <TR> </TR> tags. out.println (“<TABLE BORDER=1 BORDERCOLOR=SILVER BGCOLOR=IVORY ➥CELLPADDING=5><TR>”); The first item in the list is an array containing the names of the columns in the table. This is output as HTML table header cells. String[] headerRow = (String[])query.get(0); for (int i = 0; i < headerRow.length; i++) { out.println (“<TH ALIGN=LEFT>” + headerRow[i] + “</TH>”); } out.println (“</TR>”); The remainder of the rows of the table are output as HTML table data cells. for (int i = 1; i < query.size(); i++) { out.println (“<TR>”); String[] row = (String[])query.get(i); for (int r = 0; r < row.length; r++) { out.println (“<TD>” + row[r] + “</TD>”); } out.println (“</TR>”); } out.println (“</TABLE>”); Deploying the AgencyTable Servlet Use deploytool to add the AgencyTable Servlet as a servlet Web component in the Agency application. You will need to map the JNDI names used in the code, as shown in Figure 12.26. 548 Day 12 15 0672323842 CH12 3/20/02 9:34 AM Page 548 Servlets 549 12 Figure 12.27 shows the output. F IGURE 12.26 deploytool EJB Refs. FIGURE 12.27 AgencyTable servlet output. 15 0672323842 CH12 3/20/02 9:34 AM Page 549 [...]... out.println (“”); 59: String[] row = (String[])query.get(i); 60 : for (int r = 0; r < row.length; r++) { 61 : out.println (“” + row[r] + “”); 62 : } 63 : out.println (“”); 64 : } 65 : out.println (“”); 66 : } 67 : 68 : public void doGet(HttpServletRequest req, HttpServletResponse res) 69 : throws IOException { 70: try { 71: String agencyName = agency.getAgencyName(); 72: String tableName = null;... the JSP 13 16 067 2323842 CH13 3/20/02 9:27 AM Page 566 566 Day 13 FIGURE 13 .6 Browser showing JSP translation error The error in Figure 13 .6 shows a parse error defining an unterminated “ . < row.length; r++) { 61 : out.println (“<TD>” + row[r] + “</TD>”); 62 : } 63 : out.println (“</TR>”); 64 : } 65 : out.println (“</TABLE>”); 66 : } 67 : 68 : public void doGet(HttpServletRequest. “</TH>”); 54: } 55: out.println (“</TR>”); 56: 57: for (int i = 1; i < query.size(); i++) { 58: out.println (“<TR>”); 59: String[] row = (String[])query.get(i); 60 : for (int r = 0; r <. lot of HTML formatting information from within Java. Servlets can be described as large amounts of boring HTML println() statements inter- spersed with small amounts of interesting Java code. Servlets