In-depth introduction to dynamic content caching technology in JSP 2.0

Source: Internet
Author: User
Tags tld

Content caching is one of the most common optimization technologies in Web applications. For example, you can use a custom JSP tag-we name it -- And Encapsulate each page segment to be cached. Any custom tag can control when it contains parts (that is, pre-encapsulated page fragments) are executed, and dynamic output results can be captured. The tag allows the JSP Container (such as Tomcat) to generate content only once and store each cache segment as the JSP variable within the application scope. Each time a JSP page is executed, the custom tag loads the cached page segment without executing the JSP code again to generate the output result. As a part of the Jakarta project, the development of the tag library uses this technology. When the cached content does not need to be customized by every user or request, it works very well.

This article has improved the technology described above. By using JSP 2.0 Expression Language (EL), JSP pages are allowed to customize cache content for each request and user. Cached page fragments can contain JSP expressions not assigned by JSP containers. When each page is executed, custom tags are used to determine the values of these expressions. Therefore, the creation of dynamic content is optimized, but the cache fragment can contain part of the content produced by each request using the native JSP Expression Language. With the help of JSP 2.0 el api, Java developers can use expression languages to make it possible.

Content cache VS data cache

Content caching is not the only option. For example, data extracted from a database can also be cached. In fact, because the stored information does not contain HTML markup and requires less memory, the data cache may be more efficient. However, in many cases, the memory cache is easier to implement. Assume that in a case, an application occupies important CPU resources by a large number of transaction objects, generates complex data, and uses JSP pages to present the data. Work well until the load on the server suddenly increases one day and an emergency solution is needed. At this time, a cache layer is established between the transaction object and the presentation layer, which is a very good and effective solution. However, you must modify the JSP page that caches dynamic content very quickly and smoothly. Compared with simple JSP page editing, business logic changes of applications usually require more workload and testing. In addition, if a page aggregates information from multiple composite sources, the Web layer has only a few changes. The problem is that when the cache information becomes out of time, the cache space needs to be released, and the transaction object should know when this happens. However, there are many factors to consider when selecting to implement content caching, data caching, or other optimization technologies. Sometimes it is the special requirements of the developed program. Data caching and content caching do not have to be mutually exclusive. They can be used together. For example, in a database-driven application, the data extracted from the database and the HTML that presents the data are cached respectively. This is similar to the template generated in Real Time Using JSP. The el api-based technology discussed in this article describes how to use jsp el to load data into a rendering template.

Use JSP variables to cache dynamic content

Every time a caching mechanism is implemented, a method is required to store cached objects. In this article, a String type object is involved. One option is to use an object-the cache framework structure, or use Java maps to implement a custom cache solution. JSP already has a "scoped attributes" or "JSP variables" to provide ID-object ing, which is exactly what the cache mechanism needs. It makes no sense to use page or request scope. In the application scope, this is a good place to store cached content because it is shared by all users and pages. Session scope can also be used when each user needs to cache it separately, but this is not very efficient. The JSTL tag library can be used with that to cache content. The following example shows how to use JSP variables:

  

  

  

...

  

The cached page fragment outputs the result using the following statement:

$ {ApplicationScope. cachedFragment}

What happens when the cache segment needs to be customized by every request?

For example, if you want to include a counter, You Need To Cache two fragments:

  

  

  

  

  

  

...

  

  

...

  

You can use the following statement to output the cache content:

${CachedFragment1 }$ {counter }$ {cachedFragment2} with the help of a dedicated tag library, it is easy to cache custom page fragments. As mentioned above, the cached content can be started as a tag ( ) And end tags ( . For each customization, you can use another tag ( ) Output a JSP expression ($. Dynamic Content is cached Using JSP expressions and assigned a value each time the cached content is output. In the following section, we can see how this is implemented. Counter. jsp caches a page segment containing a Counter. When every user refreshes this page, the Counter will automatically + 1.

  

  

  

  

   JSP variables are easy to use. For simple Web apps, this is a good content cache solution. However, if the application generates a large amount of dynamic content, it is undoubtedly a problem not to control the cache size. A dedicated cache framework structure can provide a more powerful solution that allows you to monitor the cache, limit the cache size, control the cache policy, and so on ...... Use the JSP 2.0 Expression Language APIJSP container (for example, Tomcat) to assign values to the expressions on the JSP page where el api is applied and can be used by Java code. This allows jsp el development outside the Web page, such as XML files, text-based resources, and custom scripts. El api is also useful when you need to control when to assign values to expressions on Web pages or write related expressions. For example, a cached page segment can contain custom JSP expressions. When each cached content is output, el api assigns values to these expressions or assigns values again. The article provides an example Program (see the resource section at the end of the article). This application contains a Java class (JspUtils) and a class containing a method eval (), this method has three parameters: JSP expression, the expected type of expression, and a JSP context object. The Eval () method obtains the ExpressionEvaluator from the JSP context and calls the evaluate () method to obtain the ExpressionEvaluator through the expression, The expected type of the expression, and a variable obtained from the JSP congtext. The value of the expression returned by the JspUtils. eval () method. Package com. devsphere. articles. jspcache;

...

  

...

 

  

Import javax. servlet. jsp. JspContext;

Import javax. servlet. jsp. JspException;

Import javax. servlet. jsp. PageContext;

Import javax. servlet. jsp. el. ELException;

Import javax. servlet. jsp. el. ExpressionEvaluator;

Import java. io. IOException; public class JspUtils

{

Public static Object eval (String expr, Class type, JspContext jspContext)

Throws JspException

{

Try

{

If (expr. indexOf ("$ {") =-1) return expr;

ExpressionEvaluator evaluator = jspContext. getExpressionEvaluator ();

Return evaluator. evaluate (expr, type,

JspContext. getVariableResolver (), null );

} Catch (ELException e)

{

Throw new JspException (e );

}

}

...

} Note: JspUtils. eval () mainly encapsulates the standard ExpressionEvaluator. If expr does not contain $ {, the jsp el api is not called because there is no JSP expression. Creating a tag library Descriptor (TLD) file JSP tag Library requires a tag library Descriptor (TLD) file to customize tag naming, their attributes, and Java classes that operate on the tag. Jspcache. tld describes two custom tags, There are two attributes: the id of the cached page fragment and the range of content to be stored on the JSP scope-JSP page. There is only one attribute, that is, the JSP expression must be assigned a value when each cache segment is output. The TLD file maps the two custom tags to the CacheTag and DynamicTag classes, as shown below:

TLD files are contained in the Web application descriptor file (web. xml). These five files also contain an initial parameter to indicate whether the cache is available.

Understanding The working mechanism of JSP containers is Tag to create a CacheTag instance. The JSP Container is responsible for calling the setJsp (), setParent (), and setJspBody () methods, which are inherited by the CacheTag class from SimpleTagSupport. JSP Container colleagues also call the setter method for each attribute of the operated tag. The SetId () and setScope () Methods store attribute values to private domains. This value has been initialized using the default value of the CacheTag () constructor. Package com. devsphere. articles. jspcache;

Xmlns: xsi = "http://www.w3.org/2001/XMLSchema-instance"

Xsi: schemaLocation = "http://java.sun.com/xml/ns/j2ee web-app_2_4.xsd"

Version = "2.4">

Com. devsphere. articles. jspcache. enabled

    

  

  

  

  

Import javax. servlet. ServletContext;

Import javax. servlet. jsp. JspContext;

Import javax. servlet. jsp. JspException;

Import javax. servlet. jsp. PageContext;

Import javax. servlet. jsp. tagext. SimpleTagSupport;

Import java. io. IOException; import java. io. StringWriter;

Public class CacheTag extends SimpleTagSupport

{

Public static final String CACHE_ENABLED =

"Com. devsphere. articles. jspcache. enabled ";

Private String id; private int scope;

Private boolean cacheEnabled; public CacheTag ()

{

Id = null; scope = PageContext. APPLICATION_SCOPE;

} Public void setId (String id)

{

This. id = id;

}

Public void setScope (String scope)

{

This. scope = JspUtils. checkScope (scope );

}

...

}

The setScope () method calls JspUtils. checkScope () to verify that

The attribute value of the scope that is converted from String to int type. ... Public class JspUtils {... public static int checkScope (String scope) {if ("page ". equalsIgnoreCase (scope) return PageContext. PAGE_SCOPE; else if ("request ". equalsIgnoreCase (scope) return PageContext. REQUEST_SCOPE; else if ("session ". equalsIgnoreCase (scope) return PageContext. SESSION_SCOPE; else if ("application ". equalsIgnoreCase (scope) return PageContext. APPLICATION_SCOPE; else throw new IllegalArgumentException ("Invalid scope:" + scope) ;}} once the CacheTag instance is ready to operate on tags, the JSP Container calls the doTag () method and uses getJspContext () to obtain the JSP context. This object is modeled as PageContext, so that the getServletContext () method can be called. Servlet context is used to obtain the value of the initialization parameter, which indicates whether the cache mechanism is enabled. If the cache is enabled, doTag () tries to use the id and scope attribute values to obtain the cached page fragment. If the page fragment is not cached, doTag () uses getJspBody (). invoke () to execute And Encapsulated JSP code. The output result generated by the JSP body is buffered in StringWriter and obtained by the toStirng () method. In this way, doTag () calls the setAttribute () method of JSP context to create a JSP variable. This variable control may contain JSP expressions ($ {...}) . Before using jspContext. getOut (). print () to output content, these expressions are assigned a value by JspUtils. eval. These actions occur only when the cache is enabled. Otherwise, doTag () Only executes the JSP body through getJspBody (). invoke (null) and the output result is not cached ....

Public class CacheTag extends SimpleTagSupport

{

...

Public void doTag () throws JspException, IOException

{

JspContext jspContext = getJspContext ();

ServletContext application = (PageContext)

JspContext). getServletContext ();

String cacheEnabledParam = application. getInitParameter (CACHE_ENABLED );

CacheEnabled = cacheEnabledParam! = Null

& CacheEnabledParam. equals ("true ");

If (cacheEnabled)

{

String cachedOutput = (String) jspContext. getAttribute (id, scope );

If (cachedOutput = null)

{

StringWriter buffer = new StringWriter ();

GetJspBody (). invoke (buffer );

CachedOutput = buffer. toString ();

JspContext. setAttribute (id, cachedOutput, scope );

}

String evaluatedOutput = (String)

JspUtils. eval (cachedOutput, String. class, jspContext );

JspContext. getOut (). print (evaluatedOutput );

}

Else getJspBody (). invoke (null );

}

...

} Note that a separate JspUtils. eval () is called to all $ {...} Expression value assignment. Because a large number of $ {...} The text of the structure is also an expression. Each cache segment can be processed as a complex JSP expression. The IsCacheEnabled () method returns the value of cacheEnabled, which has been initialized by doTag. The IsCacheEnabled () method returns the value of cacheEnabled, which has been initialized by doTag.

... Public class CacheTag extends SimpleTagSupport

{

...

Public boolean isCacheEnabled () {return cacheEnabled;

}

} The tag allows the page developer to select the ID of the cached page fragment. This allows the cache of a page segment to be shared by multiple JSP pages. This is useful when JSP code needs to be reused. However, some naming protocols are still needed to avoid possible conflicts. You can avoid this problem by modifying the CacheTag class to include a URL in the automatic ID. Understanding What are you doing? Processed by a DynamicTag instance. The setExpr () method stores the expr property value to a private domain. Create a JSP expression using the DoTag () method, and add the $ {prefix and} suffix to the expr property value. Then, doTag () uses findAncestorWithClass () to find Label element CacheTag handler. If no result is found or the cache is disabled, the JSP expression is assigned a value by JspUtils. eval () and the value is output. Otherwise, doTag () Outputs A non-value expression. Package com. devsphere. articles. jspcache;

Import javax. servlet. jsp. JspException;

Import javax. servlet. jsp. tagext. SimpleTagSupport;

Import java. io. IOException;

Public class DynamicTag extends SimpleTagSupport

{

Private String expr; public void setExpr (String expr)

{

This. expr = expr;

}

Public void doTag () throws JspException, IOException

{

String output = "$ {" + expr + "}";

CacheTag ancestor = (CacheTag) findAncestorWithClass

(This, CacheTag. class );

If (ancestor = null |! Ancestor. isCacheEnabled ())

Output = (String) JspUtils. eval

(Output, String. class, getJspContext ());

GetJspContext (). getOut (). print (output );

}

} After analyzing the above code, you can note that And Cooperation to achieve a solution as efficient as possible. If the cache is available, the page fragment and The JSP expressions generated and assigned value by CacheTag are put together into the buffer. If the cache is disabled, caching becomes meaningless, Execute the JSP body and assign a value to the JSP expression by using DynamicTag. Disabling caching is sometimes necessary, especially when content changes and JSP pages are re-compiled during development. Of course, the cache must be enabled in the developed finished environment. Summary content cache is an easy-to-use method to improve Web application performance. This article focuses on using JSP expressions to customize cache content for each user or request. Throughout the full text, the label library is suitable for small Web apps and can improve the performance of medium applications. For the development of large-scale enterprise-level applications, we should consider using a framework structure that supports better caching mechanisms, not just using JSP variables.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.