Detailed explanation of Jasper for Tomcat

Table of contents

One: Introduction to Jasper

Two: JSP compilation method

1. Runtime compilation

①: Compilation process

2. Compilation results

②: Precompile

Three: JSP compilation principle

1. Code Analysis

2. Compilation process


One: Introduction to Jasper

For JSP -                  based web applications, we can directly write Java code in JSP pages , add third-party tag libraries, and use EL expressions. But no matter what form of processing, the final output to the client is a standard HTML page (including js , css... ), and does not contain any java- related syntax. In other words, we can regard jsp as a script running on the server side. So how does the server convert the JSP page into an HTML page?

               The Jasper module is Tomcat 's JSP core engine, we know that JSP is essentially a Servlet . Tomcat uses Jasper to analyze JSP syntax, generate Servlet and generate Class bytecode, when users access jsp , they will access Servlet , and finally respond directly to the browser with the access result. In addition, when running, Jasper will also detect whether the JSP file is modified, and if it is modified, it will recompile the JSP file.

 

Two: JSP compilation method

1.  Runtime compilation

                    Tomcat does not automatically compile JSP files when starting a web application , but only compiles the JSP files that need to be accessed when the client requests for the first time .
                   Create a web project and write JSP code :
<%@ page import="java.text.DateFormat" %>
<%@ page import="java.text.SimpleDateFormat" %>
<%@ page import="java.util.Date" %>
<%@ page contentType="text/html;charset=UTF‐8" language="java" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<%
DateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd
HH:mm:ss");
String format = dateFormat.format(new Date());
%>
Hello , Java Server Page 。。。。
<br/>
<%= format %>
</body>
</html>

①: Compilation process

             Tomcat configures a org.apache.jasper.servlet.JspServlet in the default web.xml to handle all requests ending in .jsp or .jspx . This Servlet implementation is the entry point for runtime compilation.

JspServlet processing flow chart: 

 

2. Compilation results

1 ) If the parameter scratchdir is configured in tomcat/conf/web.xml , the result of jsp compilation will be stored in this directory.

2 ) If this option is not configured, the compiled result will be stored in work/Catalina(Engine name )/localhost(Host name )/Context name under the Tomcat installation directory . Suppose the project name is jsp_demo01.
3 ) If you use the IDEA development tool to integrate Tomcat to access the jsp in the web project , the compiled result is stored in:
C:\Users\Administrator\.IntelliJIdea2019.1\system\tomcat\_project_tomcat\w
ork\Catalina\localhost\jsp_demo_01_war_exploded\org\apache\jsp

②: Precompile

                        In addition to compiling at runtime, we can also compile all the JSP pages in the Web application at one time directly when the Web application starts . In this case, during the running of the Web application, real-time translation is not necessary, but the Servlet corresponding to the JSP page is directly invoked to complete request processing, thereby improving system performance.
                       Tomcat provides a shell program JspC to support JSP precompilation, and provides a catalina-tasks.xml file in the Tomcat installation directory to declare the Ant tasks supported by Tomcat , so we can easily use Ant to execute JSP precompilation compile. (To use this method, you must ensure that Apache Ant has been downloaded and installed before ).

Three: JSP compilation principle

1. Code Analysis

Compiled .class bytecode file and source code :
public final class index_jsp extends
org.apache.jasper.runtime.HttpJspBase
implements
org.apache.jasper.runtime.JspSourceDependent,org.apache.jasper.runtime.Js
pSourceImports {
private static final javax.servlet.jsp.JspFactory _jspxFactory =
javax.servlet.jsp.JspFactory.getDefaultFactory();
private static java.util.Map<java.lang.String,java.lang.Long>
_jspx_dependants;
static {
_jspx_dependants = new
java.util.HashMap<java.lang.String,java.lang.Long>(2);
_jspx_dependants.put("jar:file:/D:/DevelopProgramFile/apache‐tomcat‐
8.5.42‐windows‐x64/apache‐tomcat‐8.5.42/webapps/jsp_demo_01/WEB‐
INF/lib/standard.jar!/META‐INF/c.tld", Long.valueOf(1098682290000L));
_jspx_dependants.put("/WEB‐INF/lib/standard.jar",
Long.valueOf(1490343635913L));
}
private static final java.util.Set<java.lang.String>
_jspx_imports_packages;
private static final java.util.Set<java.lang.String>
_jspx_imports_classes;
static {
_jspx_imports_packages = new java.util.HashSet<>();
_jspx_imports_packages.add("javax.servlet");
_jspx_imports_packages.add("javax.servlet.http");
_jspx_imports_packages.add("javax.servlet.jsp");
_jspx_imports_classes = new java.util.HashSet<>();
_jspx_imports_classes.add("java.util.Date");
_jspx_imports_classes.add("java.text.SimpleDateFormat");
_jspx_imports_classes.add("java.text.DateFormat");
}
private volatile javax.el.ExpressionFactory _el_expressionfactory;
private volatile org.apache.tomcat.InstanceManager
_jsp_instancemanager;
public java.util.Map<java.lang.String,java.lang.Long> getDependants() {
return _jspx_dependants;
}
public java.util.Set<java.lang.String> getPackageImports() {
return _jspx_imports_packages;
}
public java.util.Set<java.lang.String> getClassImports() {
return _jspx_imports_classes;
}
public javax.el.ExpressionFactory _jsp_getExpressionFactory() {
if (_el_expressionfactory == null) {
synchronized (this) {
if (_el_expressionfactory == null) {
_el_expressionfactory =
_jspxFactory.getJspApplicationContext(getServletConfig().getServletContex
t()).getExpressionFactory();
}
}
}
return _el_expressionfactory;
}
public org.apache.tomcat.InstanceManager _jsp_getInstanceManager() {
if (_jsp_instancemanager == null) {
synchronized (this) {
if (_jsp_instancemanager == null) {
_jsp_instancemanager =
org.apache.jasper.runtime.InstanceManagerFactory.getInstanceManager(getSe
rvletConfig());
}
}
}
return _jsp_instancemanager;
}
public void _jspInit() {
}
public void _jspDestroy() {
}
public void _jspService(final javax.servlet.http.HttpServletRequest
request, final javax.servlet.http.HttpServletResponse response)
throws java.io.IOException, javax.servlet.ServletException {
final java.lang.String _jspx_method = request.getMethod();
if (!"GET".equals(_jspx_method) && !"POST".equals(_jspx_method) &&
!"HEAD".equals(_jspx_method) &&
!javax.servlet.DispatcherType.ERROR.equals(request.getDispatcherType()))
{
response.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "JSPs
only permit GET POST or HEAD");
return;
}
final javax.servlet.jsp.PageContext pageContext;
javax.servlet.http.HttpSession session = null;
final javax.servlet.ServletContext application;
final javax.servlet.ServletConfig config;
javax.servlet.jsp.JspWriter out = null;
final java.lang.Object page = this;
javax.servlet.jsp.JspWriter _jspx_out = null;
javax.servlet.jsp.PageContext _jspx_page_context = null;
try {
response.setContentType("text/html;charset=UTF‐8");
pageContext = _jspxFactory.getPageContext(this, request, response,
null, true, 8192, true);
_jspx_page_context = pageContext;
application = pageContext.getServletContext();
config = pageContext.getServletConfig();
session = pageContext.getSession();
out = pageContext.getOut();
_jspx_out = out;
out.write("\n");
out.write("\n");
out.write("\n");
out.write("\n");
out.write("\n");
out.write("<html>\n");
out.write(" <head>\n");
out.write(" <title>$Title$</title>\n");
out.write(" </head>\n");
out.write(" <body>\n");
out.write(" ");
DateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd
HH:mm:ss");
String format = dateFormat.format(new Date());
out.write("\n");
out.write(" Hello , Java Server Page 。。。。\n");
out.write("\n");
out.write(" <br/>\n");
out.write("\n");
out.write(" ");
out.print( format );
out.write("\n");
out.write("\n");
out.write(" </body>\n");
out.write("</html>\n");
} catch (java.lang.Throwable t) {
if (!(t instanceof javax.servlet.jsp.SkipPageException)){
out = _jspx_out;
if (out != null && out.getBufferSize() != 0)
try {
if (response.isCommitted()) {
out.flush();
} else {
out.clearBuffer();
}
} catch (java.io.IOException e) {}
if (_jspx_page_context != null)
_jspx_page_context.handlePageException(t);
else throw new ServletException(t);
}
} finally {
_jspxFactory.releasePageContext(_jspx_page_context);
}
}
}
From the compiled source code interpretation, the following points can be analyzed:
1 ) Its class name is index_jsp , inherited from org.apache.jasper.runtime.HttpJspBase , which is a subclass of HttpServlet, so jsp is essentially a Servlet .
2 ) The resources that the current JSP page depends on are saved through the attribute _jspx_dependants , including the imported external JSP pages, imported tags, jar packages where the tags are located, etc., which are convenient for use in subsequent processing (such as recompilation detection, so it is in the form of a Map saves the last modification time of each resource).
3 ) The imported java package is stored through the attribute _jspx_imports_packages , and javax.servlet is imported by default ,
javax.servlet.http, javax.servlet.jsp
4 ) The imported classes are stored through the attribute _jspx_imports_classes , and the DateFormat, SimpleDateFormat and Date imported through the import command will be included in this collection. The _jspx_imports_packages and _jspx_imports_classes properties are mainly used to configure the EL engine context.
5 ) The request processing is completed by the method _jspService , and the service method in the parent class HttpJspBase calls the _jspService method of the subclass through the template method mode.

6 ) Several important local variables are defined in the _jspService method: pageContext , Session , application, config , out , page . Since the output of the entire page is completed by the _jspService method, these variables and parameters will take effect on the entire JSP page. This is why we can use these variables in JSP pages.
7 ) The instruction specifying the document type ( page ) is finally transformed into a response.setContentType() method call.
8 ) For each line of static content ( HTML ), call out.write to output.
9 ) For the java code in <% ... %> , it will be directly converted to the code in the Servlet class. If a static file is embedded in the Java code, call out.write to output as well.

2. Compilation process

The JSP compilation process is as follows:

Compiler compilation work mainly includes two parts: code generation and compilation:
code generation
1 ) Compiler saves various configurations during JSP page compilation through a PageInfo object , which can be
It may come from the initialization parameters of the Web application, and may also come from the instruction configuration (such as page , include) of the JSP page .
2 ) Call ParserController to parse the instruction node, verify whether it is legal, and save the configuration information to PageInfo to control code generation.
3 ) Call ParserController to parse the entire page. Since JSP is parsed line by line, a specific Node object will be created for each line. Such as static text (TemplateText), Java code (
Scriptlet ), custom tags (CustomTag ), Include instructions (IncludeDirective).
4 ) Verify the legality of all nodes except instructions, such as scripts, custom tags, EL expressions, etc.
5 ) Collect page configuration information of other nodes except instructions.
6 ) Compile and load the tags that the current JSP page depends on
7 ) For the EL expression of the JSP page , generate the corresponding mapping function.
8 ) Generate the source code of the Servlet class corresponding to the JSP page
compile
After the code generation is complete, Compiler will also generate SMAP information. If configured to generate SMAP information,
The Compiler will write the SMAP information to the class file during the compilation phase.
In the compilation phase, the two implementations of Compiler , AntCompiler and JDTCompiler , respectively call the
API for source code compilation.
For AntCompiler , the task of constructing an Ant javac completes the compilation.
For JDTCompiler , call org.eclipse.jdt.internal.compiler.Compiler to complete the compilation.

Guess you like

Origin blog.csdn.net/qq_61313896/article/details/128897991