为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

java JDBC 外文翻译 外文文献 英文文献

2017-09-30 34页 doc 137KB 291阅读

用户头像

is_215732

暂无简介

举报
java JDBC 外文翻译 外文文献 英文文献java JDBC 外文翻译 外文文献 英文文献 原文一: Java Programming with Oracle JDBC:Performance Performance is usually considered an issue at the end of a development cycle when it should really be considered from the start.Often, a task called "performance tuning" is done after the...
java JDBC 外文翻译 外文文献 英文文献
java JDBC 外文翻译 外文文献 英文文献 原文一: Java Programming with Oracle JDBC:Performance Performance is usually considered an issue at the end of a development cycle when it should really be considered from the start.Often, a task called "performance tuning" is done after the coding is complete, and the end user of a program complains about how long it takes the program to complete a particular task.The net result of waiting until the end of the development cycle to consider performance includes the expense of the additional time required to recode a program to improve its performance.It's my opinion that performance is something that is best considered at the start of a project. When it comes to performance issues concerning JDBC programming there are two major factors to consider. The first is the performance of the database structure and the SQL statements used against it. The second is the relative efficiency of the different ways you can use the JDBC interfaces to manipulate a database. In terms of the database's efficiency, you can use the EXPLAIN PLAN facility to explain how the database's optimizer plans to execute your SQL statements. Armed with this knowledge, you may determine that additional indexes are needed, or that you require an alternative means of selecting the data you desire. On the other hand, when it comes to using JDBC, you need to know ahead of time the relative strengths and weaknesses of using auto-commit, SQL92 syntax, and a Statement versus a PreparedStatement versus a CallableStatement object. In this chapter, we'll examine the relative performance of various JDBC objects using example programs that report the amount of time it takes to accomplish a given task. We'll first look at auto-commit. Next, we'll look at the impact of the SQL92 syntax parser. Then we'll start a series of comparisons of the Statement object versus the PreparedStatement object versus the CallableStatement object. At the same time we'll also examine the performance of the OCI versus the Thin driver in each situation to see if, as Oracle's claims, there is a significant enough performance gain with the OCI driver that you should use it instead of the Thin driver. For the most part, our discussions will be based on timing data for 1,000 inserts into the test performance table TESTXXXPERF. There are separate programs for performing these 1,000 inserts using the OCI driver and the Thin driver. The performance test programs themselves are very simple and are available online with the rest of the examples in this book. However, for brevity, I'll not show the code for the examples in this chapter. I'll only talk about them. Although the actual timing values change from system to system, their relative values, or ratios from one system to another, remain consistent. The timings used in this chapter were gathered using Windows 2000. Using objective data from these programs allows us to come to factual conclusions on which factors improve performance, rather than relying on hearsay. I'm sure you'll be surprised at the reality of performance for these objects, and I hope you'll use this knowledge to your advantage. Let's get started with a look at the testing framework used in this chapter. A Testing Framework For the most part, the test programs in this chapter report the timings for inserting data into a table. I picked an INSERT statement because it eliminates the performance gain of the database block buffers that may skew timings for an UPDATE, DELETE, or SELECT . The test table used in the example programs in this chapter is a simple relational table. I wanted it to have a NUMBER, a small VARCHAR2, a large VARCHAR2, and a DATE column. Table TESTXXXPERF is defined as: create table TestXXXPerf ( id number, code varchar2(30), descr varchar2(80), insert_user varchar2(30), insert_date date ) tablespace users pctfree 20 storage( initial 1 M next 1 M pctincrease 0 ); alter table TestXXXPerf add constraint TestXXXPerf_Pk primary key ( id ) using index tablespace users pctfree 20 storage( initial 1 M next 1 M pctincrease 0 ); The initial extent size used for the table makes it unlikely that the database will need to take the time to allocate another extent during the execution of one of the test programs. Therefore, extent allocation will not impact the timings. Given this background, you should have a context to understand what is done in each section by each test program. Auto-Commit By default, JDBC's auto-commit feature is on, which means that each SQL statement is committed as it is executed. If more than one SQL statement is executed by your program, then a small performance increase can be achieved by turning off auto-commit. Let's take a look at some numbers. Table 19-1 shows the average time, in milliseconds, needed to insert 1,000 rows into the TESTXXXPERF table using a Statement object. The timings represent the average from three runs of the program. Both drivers experience approximately a one-second loss as overhead for committing between each SQL statement. When you divide that one second by 1,000 inserts, you can see that turning off auto-commit saves approximately 0.001 seconds (1 millisecond) per SQL statement. While that's not interesting enough to write home about, it does demonstrate how auto-commit can impact performance. Table 19-1: Auto-commit timings (in milliseconds) Auto-commit OCI Thin On 3,712 3,675 Off 2,613 2,594 Clearly, it's more important to turn off auto-commit for managing multistep transactions than for gaining performance. But on a heavily loaded system where many users are committing transactions, the amount of time it takes to perform commits can become quite significant. So my recommendation is to turn off auto-commit and manage your transactions manually. The rest of the tests in this chapter are performed with auto-commit turned off. SQL92 Token Parsing Like auto-commit, SQL92 escape syntax token parsing is on by default. In case you don't recall, SQL92 token parsing allows you to embed SQL92 escape syntax in your SQL statements (see "Oracle and SQL92 Escape Syntax" in Chapter 9). These standards-based snippets of syntax are parsed by a JDBC driver transforming the SQL statement into its native syntax for the target database. SQL92 escape syntax allows you to make your code more portable--but does this portability come with a cost in terms of performance? Table 19-2 shows the number of milliseconds needed to insert 1,000 rows into the TESTXXXPERF table. Timings are shown with the SQL92 escape syntax parser on and off for both the OCI and Thin drivers. As before, these timings represent the result of three program runs averaged together. Table 19-2: SQL92 token parser timings (in milliseconds) SQL92 parser OCI Thin On 2,567 2,514 Off 2,744 2,550 Notice from Table 19-2 that with the OCI driver we lose 177 milliseconds when escape syntax parsing is turned off, and we lose only 37 milliseconds when the parser is turned off with the Thin driver. These results are the opposite of what you might intuitively expect. It appears that both drivers have been optimized for SQL92 parsing, so you should leave it on for best performance. Now that you know you never have to worry about turning the SQL92 parser off, let's move on to something that has some potential for providing a substantial performance improvement. Statement Versus PreparedStatement There's a popular belief that using a PreparedStatement object is faster than using a Statement object. After all, a prepared statement has to verify its metadata against the database only once, while a statement has to do it every time. So how could it be any other way? Well, the truth of the matter is that it takes about 65 iterations of a prepared statement before its total time for execution catches up with a statement. When it comes to which SQL statement object performs better under typical use, a Statement or a PreparedStatement, the truth is that the Statement object yields the best performance. When you consider how SQL statements are typically used in an application--1 or 2 here, maybe 10-20 (rarely more) per transaction--you realize that a Statement object will perform them in less time than a PreparedStatement object. In the next two sections, we'll look at this performance issue with respect to both the OCI driver and the Thin driver. The OCI Driver Table 19-3 shows the timings in milliseconds for 1 insert and 1,000 inserts in the TESTXXXPERF table. The inserts are done first using a Statement object and then a PreparedStatement object. If you look at the results for 1,000 inserts, you may think that a prepared statement performs better. After all, at 1,000 inserts, the PreparedStatement object is almost twice as fast as the Statement object, but if you examine Figure 19-1, you'll see a different story. Table 19-3: OCI driver timings (in milliseconds) Inserts Statement PreparedStatement 1 10 113 1,000 2,804 1,412 Figure 19-1 is a graph of the timings needed to insert varying numbers of rows using both a Statement object and a PreparedStatement object. The number of inserts begins at 1 and climbs in intervals of 10 up to a maximum of 150 inserts. For this graph and for those that follow, the lines themselves are polynomial trend lines with a factor of 2. I chose polynomial lines instead of straight trend lines so you can better see a change in the performance as the number of inserts increases. I chose a factor of 2 so the lines have only one curve in them. The important thing to notice about the graph is that it's not until about 65 inserts that the PreparedStatement object outperforms the Statement object. 65 inserts! Clearly, the Statement object is more efficient under typical use when using the OCI driver. Figure 19-1 The Thin Driver If you examine Table 19-4 (which shows the same timings as for Table 19-3, but for the Thin driver) and Figure 19-2 (which shows the data incrementally), you'll see that the Thin driver follows the same behavior as the OCI driver. However, since the Statement object starts out performing better than the PreparedStatement object, it takes about 125 inserts for the PreparedStatement to outperform Statement. Table 19-4: Thin driver timings (in milliseconds) Inserts Statement PreparedStatement 1 10 113 1,000 2,583 1,739 Figure 19-2 When you consider typical SQL statement usage, even with the Thin driver, you'll get better performance if you execute your SQL statements using a Statement object instead of a PreparedStatement object. Given that, you may ask: why use a PreparedStatement at all? It turns out that there are some reasons why you might use a PreparedStatement object to execute SQL statements. First, there are several types of operations that you simply can't perform without PreparedStatement object.For example,you must use a PreparedStatement object if you want to use large objects like BLOBs or CLOBs or if you wish to use object SQL. Essentially, you trade some loss of performance for the added functionality ofusing these object technologies.A second reason to use a PreparedStatement is its support for batching. Batching As you saw in the previous section, PreparedStatement objects eventually become more efficient than their Statement counterparts after 65-125 executions of the same statement. If you're going to execute a given SQL statement a large number of times, it makes sense from a performance standpoint to use a PreparedStatement object. But if you're really going to do that many executions of a statement, or perhaps more than 50, you should consider batching. Batching is more efficient because it sends multiple SQL statements to the server at one time. Although JDBC defines batching capability for Statement objects, Oracle supports batching only when Prepared-Statement objects are used. This makes some sense. A SQL statement in a PreparedStatement object is parsed once and can be reused many times. This naturally lends itself to batching. The OCI Driver Table 19-5 lists Statement and batched PreparedStatement timings, in milliseconds, for 1 insert and for 1,000 inserts. At the low end, one insert, you take a small performance hit for supporting batching. At the high end, 1,000 inserts, you've gained 75% throughput. Table 19-5: OCI driver timings (in milliseconds) Inserts Statement Batched 1 10 117 1,000 2,804 691 If you examine Figure 19-3, a trend line analysis of the Statement object versus the batched PreparedStatement object, you'll see that this time, the batched Prepared-Statement object becomes more efficient than the Statement object at about 50 inserts. This is an improvement over the prepared statement without batching. Figure 19-3 WARNING: There's a catch here. The 8.1.6 OCI driver has a defect by which it does not support standard Java batching, so the numbers reported here were derived using Oracle's proprietary batching. Now, let's take a look at batching in conjunction with the Thin driver. The Thin Driver The Thin driver is even more efficient than the OCI driver when it comes to using batched prepared statements. Table 19-6 shows the timings for the Thin driver using a Statement object versus a batched PreparedStatement object in milliseconds for the specified number of inserts. Table 19-6: Thin driver timings (in milliseconds) Inserts Statement Batched 1 10 117 1,000 2,583 367 The Thin driver takes the same performance hit on the low end, one insert, but gains a whopping 86% improvement on the high end. Yes, 1,000 inserts in less than a second! If you examine Figure 19-4, you'll see that with the Thin driver, the use of a batched PreparedStatement object becomes more efficient than a Statement object more quickly than with the OCI driver--at about 40 inserts. Figure 19-4 If you intend to perform many iterations of the same SQL statement against a database, you should consider batching with a PreparedStatement object. We've finished looking at improving the performance of inserts, updates, and deletes. Now let's see what we can do to squeak out a little performance while selecting data. Predefined SELECT Statements Every time you execute a SELECT statement, the JDBC driver makes two round trips to the database. On the first round trip, it retrieves the metadata for the columns you are selecting. On the second round trip, it retrieves the actual data you selected. With this in mind, you can improve the performance of a SELECT statement by 50% if you predefine the Selecstatement by using Oracle's defineColumnType()method with an OracleStatement object (see "Defining Columns" in Chapter 9). When you predefine a SELECT statement, you provide the JDBC driver with the column metadata using the defineColumnType() method, obviating the need for the driver to make a round trip to the database for that information. Hence, for a singleton SELECT, you eliminate half the work when you predefine the statement. Table 19-7 shows the timings in milliseconds required to select a single row from the TESTXXXPERF table. Timings are shown for when the column type has been predefined and when it has not been predefined. Timings are shown for both the OCI and Thin drivers. Although the defineColumnType() method shows little improvement with either driver in my test, on a loaded network, you'll see a differentiation in the timings of about 50%. Given a situation in which you need to make several tight calls to the database using a Statement, a predefined SELECT statement can save you a significant amount of time. Table 19-7: Select timings (in milliseconds) Driver Statement defineColumnType( ) OCI 13 10 Thin 13 10 Now that we've looked at auto-commit, SQL92 parsing, prepared statements, and a predefined SELECT, let's take a look at the performance of callable statements. CallableStatements As you may recall, CallableStatement objects are used to execute database stored procedures. I've saved CallableStatement objects until last, because they are the slowest performers of all the JDBC SQL execution interfaces. This may sound counterintuitive, because it's commonly believed that calling stored procedures is faster than using SQL, but that's simply not true. Given a simple SQL statement, and a stored procedure call that accomplishes the same task, the simple SQL statement will always execute faster. Why? Because with the stored procedure, you not only have the time needed to execute the SQL statement but also the time needed to deal with the overhead of the procedure call itself. Table 19-8 lists the relative time, in milliseconds, needed to call the stored procedure TESTXXXPERF$.SETTESTXXXPERF(). This stored procedure inserts one row into the table TESTXXXPERF. Timings are provided for both the OCI and Thin drivers. Notice that both drivers are slower when inserting a row this way than when using either a statement or a batched prepared statement (refer to Tables 19-3 through 19-6). Common sense will tell you why. The SETTESTXXXPERF()procedure inserts a row into the database. It does exactly the same thing that the other JDBC objects did but with the added overhead of a round trip for executing the remote procedure call. Table 19-8: Stored procedure call timings (in milliseconds) Inserts OCI Thin 1 113 117 1,000 1,723 1,752 Stored procedures do have their uses. If you have a complex task that requires several SQL statements to complete, and you encapsulate those SQL statements into a stored procedure that you then call only once, you'll get better performance than if you executed each SQL statement separately from your program. This performance gain is the result of your program not having to move all the related data back and forth over the network, which is often the slowest part of the data manipulation process. This is how stored procedures are supposed to be used with Oracle--not as a substitute for SQL, but as a means to perform work where it can be done most efficiently. OCI Versus Thin Drivers Oracle's documentation states that you should use the OCI driver for maximum performance and the Thin driver for maximum portability. However, I recommend using the Thin driver all the time. Let's take a look at some numbers from Windows 2000. Table 19-9 lists all the statistics we've covered in this chapter. Table 19-9: OCI versus Thin driver timings (in milliseconds) Metric OCI Thin 1,000 inserts with auto-commit 3,712 3,675 1,000 inserts with manual commit 2,613 2,594 1 insert with Statement 10 10 1,000 inserts with Statement 2,804 2,583 1 insert with PreparedStatement 113 113 1,000 inserts batched 1,482 367 SELECT 10 10 Predefined SELECT 10 10 1 insert with CallableStatement 113 117 1,000 inserts with CallableStatement 1,723 1,752 Totals 12,590 11,231 As you can see from Table 19-9, the Thin driver clearly outperforms the OCI driver for every type of operation except executions of CallableStatement objects. On a Unix platform, my experience has been that the CallableStatement numbers are tilted even more in favor of the OCI driver. Nonetheless, you can feel completely comfortable using the Thin driver in almost any setting. The Thin driver has been well-tuned by Oracle's JDBC development team to perform better than its OCI counterpart. 原文二: Extending Struts Introduction I have seen lot of projects where the developers implemented a proprietary MVC framework, not because they wanted to do something fundamentally different from Struts, but because they were not aware of how to extend Struts. You can get total control by developing your own MVC framework, but it also means you have to commit a lot of resources to it, something that may not be possible in projects with tight schedules. Struts is not only a very powerful framework, but also very extensible. You can extend Struts in three ways. PlugIn: Create your own PlugIn class if you want to execute some business logic at application startup or shutdown. RequestProcessor: Create your own RequestProcessor if you want to execute some business logic at a particular point during the request-processing phase. For example, you might extend RequestProcessor to check that the user is logged in and he has one of the roles to execute a particular action before executing every request. ActionServlet: You can extend the ActionServlet class if you want to execute your business logic at either application startup or shutdown, or during request processing. But you should use it only in cases where neither PlugIn nor RequestProcessor is able to fulfill your requirement. In this article, we will use a sample Struts application to demonstrate how to extend Struts using each of these three approaches. Downloadable sample code for each is available below in the Resources section at the end of this article. Two of the most successful examples of Struts extensions are the Struts Validation framework and the Tiles framework. I assume that you are already familiar with the Struts framework and know how to create simple applications using it. Please see the Resources section if you want to know more about Struts. PlugIn According to the Struts documentation "A plugin is a configuration wrapper for a module-specific resource or service that needs to be notified about application startup and shutdown events." What this means is that you can create a class implementing the PlugIn interface to do something at application startup or shutdown. Say I am creating a web application where I am using Hibernate as the persistence mechanism, and I want to initialize Hibernate as soon as the application starts up, so that by the time my web application receives the first request, Hibernate is already configured and ready to use. We also want to close down Hibernate when the application is shutting down. We can implement this requirement with a Hibernate PlugIn by following two simple steps. Create a class implementing the PlugIn interface, like this: public class HibernatePlugIn implements PlugIn{ private String configFile; // This method will be called at application shutdown time public void destroy() { System.out.println("Entering HibernatePlugIn.destroy()"); //Put hibernate cleanup code here System.out.println("Exiting HibernatePlugIn.destroy()"); } //This method will be called at application startup time public void init(ActionServlet actionServlet, ModuleConfig config) throws ServletException { System.out.println("Entering HibernatePlugIn.init()"); System.out.println("Value of init parameter " + getConfigFile()); System.out.println("Exiting HibernatePlugIn.init()"); } public String getConfigFile() { return name; } public void setConfigFile(String string) { configFile = string; } } The class implementing PlugIn interface must implement two methods: init() and destroy(). init() is called when the application starts up, and destroy() is called at shutdown. Struts allows you to pass init parameters to your PlugIn class. For passing parameters, you have to create JavaBean-type setter methods in your PlugIn class for every parameter. In our HibernatePlugIn class, I wanted to pass the name of the configFile instead of hard-coding it in the application. Inform Struts about the new PlugIn by adding these lines to struts-config.xml: The className attribute is the fully qualified name of the class implementing the PlugIn interface. Add a element for every initialization parameter which you want to pass to your PlugIn class. In our example, I wanted to pass the name of the config file, so I added the element with the value of config file path. Both the Tiles and Validator frameworks use PlugIns for initialization by reading configuration files. Two more things which you can do in your PlugIn class are: If your application depends on some configuration files, then you can check their availability in the PlugIn class and throw a ServletException if the configuration file is not available. This will result in ActionServlet becoming unavailable. The PlugIn interface's init() method is your last chance if you want to change something in ModuleConfig, which is a collection of static configuration information that describes a Struts-based module. Struts will freeze ModuleConfig once all PlugIns are processed. How a Request is Processed ActionServlet is the only servlet in Struts framework, and is responsible for handling all of the requests. Whenever it receives a request, it first tries to find a sub-application for the current request. Once a sub-application is found, it creates a RequestProcessor object for that sub-application and calls its process() method by passing it HttpServletRequest and HttpServletResponse objects. The RequestProcessor.process() is where most of the request processing takes place. The process() method is implemented using the Template Method design pattern, in which there is a separate method for performing each step of request processing, and all of those methods are called in sequence from the process() method. For example, there are separate methods for finding the ActionForm class associated with the current request, and checking if the current user has one of the required roles to execute action mapping. This gives us tremendous flexibility. The RequestProcessor class in the Struts distribution provides a default implementation for each of the request-processing steps. That means you can override only the methods that interest you, and use default implementations for rest of the methods. For example, by default Struts calls request.isUserInRole() to find out if the user has one of the roles required to execute the current ActionMapping, but if you want to query a database for this, then then all you have to do is override the processRoles() method and return true or false, based whether the user has the required role or not. First we will see how the process() method is implemented by default, and then I will explain what each method in the default RequestProcessor class does, so that you can decide what parts of request processing you want to change. public void process(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { // Wrap multipart requests with a special wrapper request = processMultipart(request); // Identify the path component we will // use to select a mapping String path = processPath(request, response); if (path == null) { return; } if (log.isDebugEnabled()) { log.debug("Processing a '" + request.getMethod() + "' for path '" + path + "'"); } // Select a Locale for the current user if requested processLocale(request, response); // Set the content type and no-caching headers // if requested processContent(request, response); processNoCache(request, response); // General purpose preprocessing hook if (!processPreprocess(request, response)) { return; } // Identify the mapping for this request ActionMapping mapping = processMapping(request, response, path); if (mapping == null) { return; } // Check for any role required to perform this action if (!processRoles(request, response, mapping)) { return; } // Process any ActionForm bean related to this request ActionForm form = processActionForm(request, response, mapping); processPopulate(request, response, form, mapping); if (!processValidate(request, response, form, mapping)) { return; } // Process a forward or include specified by this mapping if (!processForward(request, response, mapping)) { return; } if (!processInclude(request, response, mapping)) { return; } // Create or acquire the Action instance to // process this request Action action = processActionCreate(request, response, mapping); if (action == null) { return; } // Call the Action instance itself ActionForward forward = processActionPerform(request, response, action, form, mapping); // Process the returned ActionForward instance processForwardConfig(request, response, forward); } processMultipart(): In this method, Struts will read the request to find out if its contentType is multipart/form-data. If so, it will parse it and wrap it in a wrapper implementing HttpServletRequest. When you are creating an HTML FORM for posting data, the contentType of the request is application/x-www-form-urlencoded by default. But if your form is using FILE-type input to allow the user to upload files, then you have to change the contentType of the form to multipart/form-data. But by doing that, you can no longer read form values submitted user the getParameter() method of HttpServletRequest; you have to read the request as an InputStream and parse it to get the values. processPath(): In this method, Struts will read request URI to determine the path element that should be used for getting the ActionMapping element. processLocale(): In this method, Struts will get the Locale for the current request and, if configured, it save it inHttpSession as the value of the org.apache.struts.action.LOCALE attribute. HttpSession would be created as a side effect of this method. If you don't want that to happen, then you can set the locale property to false in ControllerConfig by adding these lines to your struts-config.xml file: processContent():Sets contentType for by calling response.setContentType(). This method first tries to get the contentType as configured in struts-config.xml. It will use text/html by default. To override that, use the following: processNoCache(): Struts will set the following three headers for every response, if configured for no-cache: requested in struts config.xml response.setHeader("Pragma", "No-cache"); response.setHeader("Cache-Control", "no-cache"); response.setDateHeader("Expires", 1); If you want to set the no-cache header, add these lines to struts-config.xml: processPreprocess(): This is a general purpose, pre-processing hook that can be overridden by subclasses. Its implementation in RequestProcessor does nothing and always returns true. Returning false from this method will abort request processing. processMapping(): This will use path information to get an ActionMapping object. The ActionMapping object represents the element in your struts-config.xml file. The ActionMapping element contains information like the name of the Action class and ActionForm used in processing this request.It has information about ActionForwards configured for the current ActionMapping. processRoles(): Struts web application security just provides an authorization scheme. What that means is once user is logged into the container, Struts' processRoles() method can check if he has one of the required roles for executing a given ActionMapping by calling request.isUserInRole(). Say you have AddUserAction and you want only the administrator to be able to add a new user. What you can do is to add a role attribute with the value administrator in your AddUserAction action element. So before executing AddUserAction, it will always make sure that the user has the administrator role. processActionForm(): Every ActionMapping has a ActionForm class associated with it. When Struts is processing an ActionMapping, it will find the name of the associated ActionForm class from the value of the name attribute in the element. it will first check to see if an object of the org.apache.struts.action.DynaActionForm class is present in request scope. If so, it will use it; otherwise, it will create a new object and set it in the request scope. processPopulate(): In this method, Struts will populate the ActionForm class instance variables with values of matching request parameters. processValidate(): Struts will call the validate() method of your ActionForm class. If you return ActionErrors from the validate() method, it will redirect the user to the page indicated by the input attribute of the element. processForward() and processInclude(): In these functions, Struts will check the value of the forward or include attributes of the element and, if found, put the forward or include request in the configured page. You can guess difference in these functions from their names. processForward() ends upcallingRequestDispatcher.forward(),andprocessInclude()calls RequestDispatcher.include(). If you configure both forward and include attributes, it will always call forward, as it is processed first. processActionCreate(): This function gets the name of the Action class from the type attribute of the element and create and return instances of it. In our case it will create an instance of the com.sample.NewContactAction class. processActionPerform(): This function calls the execute() method of your Action class, which is where you should write your business logic. processForwardConfig(): The execute()method of your Action class will return an object of type ActionForward, indicating which page should be displayed to the user. So Struts will create RequestDispatcher for that page and call the RequestDispatcher.forward() method. The above list explains what the default implementation of RequestProcessor does at every stage of request processing and the sequence in which various steps are executed. As you can see, RequestProcessor is very flexible and it allows you to configure it by setting properties in the element. For example, if your application is going to generate XML content instead of HTML, then you can inform Struts about this by setting a property of the controller element. Creating Your own RequestProcessor Above, we saw how the default implementation of RequestProcessor works. Now we will present a example how to customize it by creating our own custom RequestProcessor. To demonstrate creating a custom RequestProcessor, we will change our sample application to implement these two business requirements: We want to create a ContactImageAction class that will generate images instead of a regular HTML page. Before processing every request, we want to check that user is logged in by checking for userName attribute of the session. If that attribute is not found, we will redirect the user to the login page. We will change our sample application in two steps to implement these business requirements. Create own CustomRequestProcessor class, which will extend the RequestProcessor class, like this: public class CustomRequestProcessor extends RequestProcessor { protected boolean processPreprocess ( HttpServletRequest request, HttpServletResponse response) { HttpSession session = request.getSession(false); //If user is trying to access login page // then don't check if( request.getServletPath().equals("/loginInput.do") || request.getServletPath().equals("/login.do") ) return true; //Check if userName attribute is there is session. //If so, it means user has allready logged in if( session != null && session.getAttribute("userName") != null) return true; else{ try{ //If no redirect user to login Page request.getRequestDispatcher ("/Login.jsp").forward(request,response); }catch(Exception ex){ } } return false; } protected void processContent(HttpServletRequest request, HttpServletResponse response) { //Check if user is requesting ContactImageAction // if yes then set image/gif as content type if( request.getServletPath().equals("/contactimage.do")){ response.setContentType("image/gif"); return; } super.processContent(request, response); } } In the processPreprocess method of our CustomRequestProcessor class, we are checking for the userName attribute of the session and if it's not found, redirect the user to the login page. For our requirement of generating images as output from the and first check if the request is for the /contactimage path. If so, we set the contentType to image/gif; otherwise, it's text/html. Add these lines to your struts-config.xml file after the element to inform Struts that CustomRequestProcessor should be used as the RequestProcessor class: Please note that overriding processContent() is OK if you have very few Action classes where you want to generate output whose contentType is something other than text/html. If that is not the case, you should create a Struts sub-application for handling requests for image-generating Actions and set image/gif as the contentType for it. The Tiles framework uses its own RequestProcessor for decorating output generated by Struts. ActionServlet If you look into the web.xml file of your Struts web application, it looks like this: action= org.apache.struts.action.ActionServlet action *.do That means ActionServlet is responsible for handling all of your requests to Struts. You can create a sub-class of the ActionServlet class if you want to do something at application startup or shutdown or on every request, but you should try creating a PlugIn or RequestProcessor before extending the ActionServlet class. Before Servlet 1.1, the Tiles framework was based on extending the ActionServlet class to decorate a generated response. But from 1.1 on, it's used the TilesRequestProcessor class. Conclusion Deciding to develop your own MVC framework is a very big decision--you should think about the time and resources it will take to develop and maintain that code. Struts is a very powerful and stable framework and you can change it to accommodate most of your business requirements. On the other hand, the decision to extend Struts should not be taken lightly. If you put some low-performance code in your RequestProcessor class, it will execute on every request and can reduce the performance of your whole application. And there will be situations where it will better for you to create your own MVC framework than extend Struts.
/
本文档为【java JDBC 外文翻译 外文文献 英文文献】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索