1 processing of static files foreword analysis
Have you recently tried to figure out Springmvc's handling strategy for static resources, such as what is the difference between it and a normal request?
Some might say that there are some static resources that are not given to these frameworks for processing, but are delivered directly to the container, which is more efficient. What I'm trying to say is that, although this is the case, dealing with static resources is the function that the MVC framework should provide, rather than relying on the outside world.
Here is an example of the SPRINGMVC project in the Tomcat container. Access to the entire static resource, as follows:
Can be divided into the following 2 large processes
- The process by which Tomcat chooses the servlet based on Url-pattern
- SPRINGMVC the process of static resources (this is left to the next article to detailed source code description)
2 Tomcat's processing strategy
Here to see the source of Tomcat, so the pom to add the corresponding dependency, so that when the debug can locate the source file, currently I use the Tomcat version is 7.0.55, if you use different versions, then change the corresponding dependent version of the line
<dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-catalina</artifactId> <version>7.0.55</version> <scope>provided</scope></dependency><dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-coyote</artifactId> <version>7.0.55</version> <scope>provided</scope></dependency><dependency> <groupId>org.apache.tomcat</groupId> <artifactId>tomcat-jasper</artifactId> <version>7.0.55</version> <scope>provided</scope></dependency>
2.1 Tomcat Default-registered Servlet
Tomcat is registered by default, mapping the Defaultservlet of the '/' path, mapping . JSP and . Jspx Jspservlet, which are configured in the Tomcat Conf/web.xml file as follows:
<servlet> <servlet-name>default</servlet-name> <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class></servlet><servlet> <servlet-name>jsp</servlet-name> <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class></servlet><servlet-mapping> <servlet-name>default</servlet-name> <url-pattern>/</url-pattern></servlet-mapping><servlet-mapping> <servlet-name>jsp</servlet-name> <url-pattern>*.jsp</url-pattern> <url-pattern>*.jspx</url-pattern></servlet-mapping>
- Defaultservlet can be used to process tomcat some resource files
- Jspservlet is used to process some JSP files, some translation of these JSP files
We can modify this configuration file to add or remove some of the default servlet configurations.
Here's what the Url-pattern rules of these servlets look like.
Rules of the Url-pattern of the 2.2 servlet
For the servlet Url-pattern rules, there is also a corresponding source analysis article Tomcat Url-pattern source code analysis.
Several concepts in the 2.2.1 Tomcat source code
Before the analysis, simply look at several concepts in Tomcat source, context, Wrapper, Servlet:
The Servlet is very clear, that is, inherit the HttpServlet, the user uses its service method to process the request
Wrapper is a combination of servlets and mappings, specifically the servlet information that is configured in Web. xml
<servlet> <servlet-name>mvc</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup></servlet><servlet-mapping> <servlet-name>mvc</servlet-name> <url-pattern>/*</url-pattern></servlet-mapping>
The Context represents an application that contains all the information configured in Web. XML, so when a request arrives, it is responsible for locating the servlet and then invoking the Servlet's service method to execute the business logic we wrote.
The context of the above map-based search servlet package to a Org.apache.tomcat.util.http.mapper.Mapper class to complete, so the request matching rules are in this mapper to complete.
So this mapper did 2 things.
When initializing Web. XML, mapper needs to collect the servlet and its mapping information and handle it, storing it in Mapper's internal class Contextversion
When the request arrives, it can select the corresponding servlet and other information according to the request address, for use
The mapper internal class Contextversion stores the servlet corresponding to the mappings as follows:
protected static final class ContextVersion extends MapElement { public String[] welcomeResources = new String[0]; public Wrapper defaultWrapper = null; public Wrapper[] exactWrappers = new Wrapper[0]; public Wrapper[] wildcardWrappers = new Wrapper[0]; public Wrapper[] extensionWrappers = new Wrapper[0]; //略}
The total is divided into 5 kinds, namely
The Welcomeresources Welcome page, which is what you can configure in Web. XML, will be described in detail as a case study
<welcome-file-list> <welcome-file>index.html</welcome-file> <welcome-file>index.htm</welcome-file></welcome-file-list>
Defaultwrapper for storing the default servlet information
Exactwrappers for exact matching, i.e. the requirements must be identical
Wildcardwrappers for wildcard matching such as/*,/abc/*
Extensionwrappers is used for extension matching, i.e. . JSP,. HTML, etc.
Let's take a look at how mapper is classified.
2.2.2 Mapper collation processing servlet and mapping information
protected void Addwrapper (contextversion context, String path, Object Wrapper, Boolean Jspwildcard, Boolean RESOURC Eonly) {synchronized (context) {if (Path.endswith ("/*")) {//Wildcard wrapper String NA me = path.substring (0, Path.length ()-2); Wrapper newwrapper = new Wrapper (name, Wrapper, Jspwildcard, resourceonly); wrapper[] Oldwrappers = context.wildcardwrappers; wrapper[] Newwrappers = new Wrapper[oldwrappers.length + 1]; if (Insertmap (Oldwrappers, Newwrappers, Newwrapper)) {context.wildcardwrappers = newwrappers; int slashcount = Slashcount (newwrapper.name); if (Slashcount > context.nesting) {context.nesting = Slashcount; }}} and Else if (Path.startswith ("*.")) {//Extension wrapper String name = Path.substring (2); Wrapper NewwraPper = new Wrapper (name, Wrapper, Jspwildcard, resourceonly); wrapper[] Oldwrappers = context.extensionwrappers; wrapper[] Newwrappers = new Wrapper[oldwrappers.length + 1]; if (Insertmap (Oldwrappers, Newwrappers, Newwrapper)) {context.extensionwrappers = newwrappers; }} else if (Path.equals ("/")) {//Default wrapper wrapper newwrapper = new Wrapper ("", WRA Pper, Jspwildcard, resourceonly); Context.defaultwrapper = Newwrapper; } else {//Exact wrapper final String name; if (path.length () = = 0) {//special case for the Context Root mapping which is//treated a s an exact match name = "/"; } else {name = path; } Wrapper newwrapper = new Wrapper (name, Wrapper, Jspwildcard, resourceonly); wrapper[] Oldwrappers = context.exactwrappers; wrapper[] Newwrappers = new Wrapper[oldwrappers.length + 1]; if (Insertmap (Oldwrappers, Newwrappers, Newwrapper)) {context.exactwrappers = newwrappers; } } }}
The above-mentioned if else statements are explained very clearly
The wildcard matches are included in the wildcardwrappers of the contextversion, ending with/*
Start with *., all included in the extension match, stored in the contextversion extensionwrappers
/, as default, is stored in the defaultwrapper of Contextversion
All the others, as exact matches, are stored in the Contextversion exactwrappers.
At this point, we may think that the URL in a variety of forms, it is not just these kinds of it. such as/a/*.jsp, that is, not with/* end, nor with *. At first, it seems that it can only be assigned to the exact match, which is not very reasonable. In fact, Tomcat restricts the URL form to death, and it checks accordingly, as follows
private boolean validateURLPattern(String urlPattern) { if (urlPattern == null) return (false); if (urlPattern.indexOf(‘\n‘) >= 0 || urlPattern.indexOf(‘\r‘) >= 0) { return (false); } if (urlPattern.equals("")) { return true; } if (urlPattern.startsWith("*.")) { if (urlPattern.indexOf(‘/‘) < 0) { checkUnusualURLPattern(urlPattern); return (true); } else return (false); } if ( (urlPattern.startsWith("/")) && (urlPattern.indexOf("*.") < 0)) { checkUnusualURLPattern(urlPattern); return (true); } else return (false);}
Obviously, Urlpattern can be "", others must be in *. or/start, and both cannot exist at the same time. /A/*.JSP does not meet the last condition, direct error, Tomcat failed to start, so we do not have to worry too much about the complexity of the url-pattern in the servlet tag.
Once the initialization collation is complete, when the request arrives, it needs to match the sorted data to find the appropriate servlet to respond to
2.2.3 Mapper match request corresponding servlet
In the Internalmapwrapper method of Mapper, there is a matching rule, as follows
Private final void Internalmapwrapper (contextversion contextversion, Charchunk Path, Mappingdata mappingdata) throws Exception {//slightly//Rule 1--Exact Match wrapper[] Exactwrappers = contextversion.exactwrappers; Internalmapexactwrapper (exactwrappers, Path, mappingdata); Rule 2--Prefix Match Boolean checkjspwelcomefiles = false; wrapper[] Wildcardwrappers = contextversion.wildcardwrappers; if (Mappingdata.wrapper = = null) {Internalmapwildcardwrapper (wildcardwrappers, contextversion.nesting, Path, mappingdata); bit}/////Rule 3--Extension Match wrapper[] extensionwrappers = contextversion.extensionwrappers; if (Mappingdata.wrapper = = null &&!checkjspwelcomefiles) {internalmapextensionwrapper (extensionwrappers, Path, Mappingdata, true); }//Rule 4--Welcome Resources Processing for Servlets if (mappingdata.wrapper = = = null) {Boolean checkwelcomefiles = Checkjspwelcomefiles; bit}/////Rule 7--Default servlet if (mappingdata.wrapper = = null &&!checkjspwelcomefiles) { if (contextversion.defaultwrapper! = null) {mappingdata.wrapper = ContextVersion.defaultWrapper.object; MappingData.requestPath.setChars (Path.getbuffer (), Path.getstart (), path.getlength ()); MappingData.wrapperPath.setChars (Path.getbuffer (), Path.getstart (), path.getlength ()); }//slightly}//slightly}
Long matching rules, interested can go to the careful study, for the welcome resources matching, the following will give 2 examples to analyze their rules in detail, the other we just understand the approximate matching order is possible, the matching sequence is as follows:
(1) First precision matching
(2) then a wildcard match
(3) then the extension matches
(4) Then the Welcome page match (here again a lot of rules are broken down, the following case analysis will be explained in detail)
(5) Finally, the default match
3 Case study (combined with source code)
Before you explain the case, you need to make the Tomcat information in eclipse clear, and sometimes modifying the Tomcat configuration doesn't work because the place you're modifying is not causing the
3.1 Premise: Configuration information for Tomcat in eclipse
- The new Tomcat server, which replicates the configuration of your installed Tomcat, resides under the server project of the current Eclipse workspace path, as follows:
So in the future to modify the Tomcat information used, directly under the project to modify, or directly to the project path, directly modify the corresponding configuration file
- The new Tomcat server is not running under the WebApps directory of the Tomcat you installed, but is under the. metadata file for the current Eclipse workspace, as follows:. metadata\.plugins\ Org.eclipse.wst.server.core, there will be one or more TMP directories in this directory, each TMP directory corresponds to a tomcat's real running environment, and then find the TMP directory you use, you will see the following information
The Wtwebapps here is the Tomcat default publishing root directory, which is not fixed, configurable.
3.2 JSP Access case
A simple example: There is a a.jsp file under the root path of Tomcat, which is the root directory of the above Tomcat release, in which we put a JSP file with the following file contents:
<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
By default, Jspservlet exists, access HTTP://LOCALHOST:8080/A.JSP?NAME=LG, the results are as follows:
If you modify the default configuration of Tomcat and remove Jspservlet, the same access to HTTP://LOCALHOST:8080/A.JSP?NAME=LG, the results are as follows
At this point, without the jspservlet, do not do the corresponding translation work, but use Defaultservlet directly to return the contents of the file.
Because Tomcat is configured by default, maps/Defaultservlet and maps *.jsp Jspservlet. When initializing Web. XML, the Mapper class described above follows the collation rules, Defaultservlet as the default Servlet,jspservlet as the servlet with the extension, which is higher than the defaultservlet level, performs an extension match, so returns the The content of the translated JSP. When the Jspservlet is removed, the defaultservlet is used, the default match is performed, and the JSP file is simply a generic resource file, returning the original content of the JSP.
3.3 Welcome-file-list CaseIt has two functions, as the main page of the project and as a jump ladder, the following first introduced two cases, and then based on the source analysis of its reasons.
Note: I use the project's root directory as a directory for Tomcat publishing, so access to http://localhost:8080/no longer joins the project name
3.3.1 as the homepage of the project
Case 1: Under the root path of the project, place a a.html file, Firstservlet intercept/first/, Secondservlet intercept . Action,web.xml is the following configuration
<servlet> <servlet-name>first</servlet-name> <servlet-class>com.lg.servlet.FirstServlet</servlet-class> <load-on-startup>1</load-on-startup></servlet><servlet-mapping> <servlet-name>first</servlet-name> <url-pattern>/first/*</url-pattern></servlet-mapping><servlet> <servlet-name>second</servlet-name> <servlet-class>com.lg.servlet.SecondServlet</servlet-class> <load-on-startup>1</load-on-startup></servlet><servlet-mapping> <servlet-name>second</servlet-name> <url-pattern>*.action</url-pattern></servlet-mapping> <welcome-file-list> <welcome-file>a.html</welcome-file></welcome-file-list>
At this point, we visit http://localhost:8080/to access the project's home page, you can access the content of a.html, as follows:
Case 2: Slightly modify the welcome-file-list, the other unchanged, as follows
<welcome-file-list> <welcome-file>a.jsp</welcome-file></welcome-file-list>
In the root directory, store a a.jsp file as follows:
<%@page contentType="text/html"%><%@page pageEncoding="UTF-8"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
The access http://localhost:8080/results are returned
It can be concluded that Tomcat uses the appropriate servlet to parse the file according to the different extensions, and then returns
3.3.2 as a jumping ladder
Case 3: Modify the Welcome-file-list again as follows, other unchanged:
<welcome-file-list> <welcome-file>a.action</welcome-file></welcome-file-list>
There are 2 cases here, that is, whether there is a a.action in the root directory, but in either case, access to http://localhost:8080/, in this case, will return the contents of the Secondservlet configured above (but their execution logic is not the same) , the return content is as follows:
Case 4: Similarly, modify Welcome-file-list as follows, access http://localhost:8080/to access the contents of the Firstservlet configured above:
<welcome-file-list> <welcome-file>first/abc</welcome-file></welcome-file-list>
3.3.3 Source InterpretationBelow we will be based on the analysis of the source code to analyze the entire process, this part of the detailed source code is as follows:
Rule 4--Welcome resources processing for servletsif (Mappingdata.wrapper = = null) {Boolean checkwelcomefiles = ch Eckjspwelcomefiles; if (!checkwelcomefiles) {char[] buf = Path.getbuffer (); Checkwelcomefiles = (Buf[pathend-1] = = '/'); } if (Checkwelcomefiles) {for (int i = 0; (I < ContextVersion.welcomeResources.length) && (mappingdata.wrapper = = null); i++) {path.setoffset (pathoffset); Path.setend (Pathend); Path.append (Contextversion.welcomeresources[i], 0, Contextversion.welcomeresources[i].length ()); Path.setoffset (Servletpath); Rule 4a--Welcome resources processing for exact macth internalmapexactwrapper (exactwrappers, PATH, mapping Data); Rule 4b--Welcome resources processing for prefix match if (mappingdata.wrapper = = null) {i Nternalmapwildcardwrapper (WildcardwrAppers, contextversion.nesting, Path, mappingdata); }//Rule 4c--Welcome resources processing//For physical folder if (Mappin Gdata.wrapper = = NULL && contextversion.resources! = null) {Object file = null; String pathstr = path.tostring (); try {file = ContextVersion.resources.lookup (PATHSTR); } catch (Namingexception NEX) {//Swallow not found, since this is normal} if (file! = NULL &&!) ( File instanceof DirContext) {internalmapextensionwrapper (extensionwrappers, Path, Mappingdata, True); if (Mappingdata.wrapper = = NULL && Contextversion.defaultwrapper! = null) { Mappingdata.wrapper = ContextVersion.defaultWrapper.object; MappingData.requestPath.setChars (Path.getbuffer (), Path.getstart (), Path.getlength ()); MappingData.wrapperPath.setChars (Path.getbuffer (), Path.getstart (), Path.getlength ()); MappingData.requestPath.setString (PATHSTR); MappingData.wrapperPath.setString (PATHSTR); }}}} Path.setoffset (Servletpath); Path.setend (Pathend); }}//Rule 4d--I call it rule 4d (source does not write) if (Mappingdata.wrapper = = null) {Boolean checkwelcomefiles = Checkjspwelcomefi Les if (!checkwelcomefiles) {char[] buf = Path.getbuffer (); Checkwelcomefiles = (Buf[pathend-1] = = '/'); } if (Checkwelcomefiles) {for (int i = 0; (I < ContextVersion.welcomeResources.length) && (Mappingdata.wrapper = = null); i++) {path.setoffset (pathoffset); Path.setend (Pathend); Path.append (Contextversion.welcomeresources[i], 0, Contextversion.welcomeresources[i].length ()); Path.setoffset (Servletpath); Internalmapextensionwrapper (extensionwrappers, Path, Mappingdata, false); } path.setoffset (Servletpath); Path.setend (Pathend); }}
As can be seen from the above, where path is no longer the original path, but our access to the path configured in Path+welcome-file, as a new path, for the welcome resources, but also broken down 4 rules, respectively, as follows:
4a: Precise matching of new paths
4b: Wildcard matching for a new path
4c: Depending on the new path, find out if there is a corresponding file, if there is a corresponding file, you need to return the file. Before returning we need to further confirm that this file is not the source of the file content to return, or like a JSP file, do some processing and then return, so you have to confirm the file extension is what
- 4C1: Try to find a servlet that can handle the file extension, that is, to match the extension and, if found, use the corresponding servlet
- 4C2: If not found, the default is to use Defaultwrapper, that is defaultservlet (it will only return the file content source, do not do any processing)
4d: The new path to the extension match (with the purpose of 4c, the main purpose of 4c is to return the contents of a file, before the return of the content related to the extension match, so 4c is the premise of the existence of the corresponding path of the file)
With the above rules, let's take a closer look at the 4 cases above which is the rule
Case 1:A.HTML,4A, 4b did not match to 4c time, found the file, and then try to match the extension, to decide whether to go 4c1 or 4c2, because. html does not have a corresponding servlet to handle, it uses the default Defaultservlet
Case 2:a.jsp, Ibid., when walking to 4c, found the processing. JSP corresponding to the servlet, so went 4c1
Case 3:a.action, If the root directory has a a.action file, then go to 4c1, the extension matches, matching to Secondservlet, that is, go 4c1, use Secondservlet to process the request, if there is no A.action file in the root directory, then went to 4d, the extension matches, the same match to Secondservlet, which goes 4d, also uses Secondservlet to process requests
Case 4:FIRST/ABC, when executing 4b, matches to Firstservlet, so use Firstservlet to process the request
At this point, the welcome-file-list thoroughly clear, have any questions and questions, welcome to ask questions
4 concluding remarksAfter learning about Tomcat's Url-pattern rules, the next article will explain how SPRINGMVC handles static resources and their comprehensive analysis.
The source analysis of Tomcat's Url-pattern