A "/" when comes to servlet mapping means default servlet.
How do you interpret this when comes to a URL pattern embedded inside a web-resource-collection element as below:
<security-constraint>
<web-resource-collection>
<web-resource-name>fixmyhome</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>*</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
What about "/*'? This URL pattern is not a servlet mapping since it's enclosed by tag web-resource-collection.
I also noticed using http://localhost:8081/fixmyhome/main.jsp using both URL pattern "/" and "/*" gives the same results- which is it gives me the main.jsp page. I thought "/" might not work since there's no wildcard.
The <url-pattern> is looking for an Ant pattern. The patterns available are ?, *, and **; which match 1 character, 0 or more characters, and 0 or more directories respectively.
In your case of http://localhost:8081/fixmyhome/main.jsp, both / and /* are working the same because the * is not a requirement for their to be a character.
If you have a resources directory in your root, I would imagine your <url-pattern> would looks something like this:
<url-pattern>/resources/**</url-pattern>, thereby allowing you access to all sub-directories of the resources directory.
This may help provide some more clarity:
https://ant.apache.org/manual/dirtasks.html
According to this I would say that by writing / you are restricting access to the servlet while by writing /* you are restricting access to a certain path. So essentially "/" and "/*" would be the same.
The url pattern under security constraint does not belong to any mapping for servlet instead it is a regular expression. With the security constraint you can allow/restrict users with the mentioned role (in auth-constraint) for the given URL pattern.
Section 12.2 of servlet specification (version 3) states following:
A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used for path mapping.
A string beginning with a ‘*.’ prefix is used as an extension mapping.
The empty string ("") is a special URL pattern that exactly maps to the application's context root, i.e.,requests of the form
http://host:port/contextroot/. In this case the path info is ’/’ and
the servlet path and context path is empty string (““).
A string containing only the ’/’ character indicates the "default" servlet of the application. In this case the servlet path
is the request URI minus the context path and the path info is null.
All other strings are used for exact matches only
Related
The familiar code:
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>main</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
My understanding is that /* maps to http://host:port/context/*.
How about /? It sure doesn't map to http://host:port/context root only. In fact, it will accept http://host:port/context/hello, but reject http://host:port/context/hello.jsp.
Can anyone explain how is http://host:port/context/hello mapped?
<url-pattern>/*</url-pattern>
The /* on a servlet overrides all other servlets, including all servlets provided by the servletcontainer such as the default servlet and the JSP servlet. Whatever request you fire, it will end up in that servlet. This is thus a bad URL pattern for servlets. Usually, you'd like to use /* on a Filter only. It is able to let the request continue to any of the servlets listening on a more specific URL pattern by calling FilterChain#doFilter().
<url-pattern>/</url-pattern>
The / doesn't override any other servlet. It only replaces the servletcontainer's built in default servlet for all requests which doesn't match any other registered servlet. This is normally only invoked on static resources (CSS/JS/image/etc) and directory listings. The servletcontainer's built in default servlet is also capable of dealing with HTTP cache requests, media (audio/video) streaming and file download resumes. Usually, you don't want to override the default servlet as you would otherwise have to take care of all its tasks, which is not exactly trivial (JSF utility library OmniFaces has an open source example). This is thus also a bad URL pattern for servlets. As to why JSP pages doesn't hit this servlet, it's because the servletcontainer's built in JSP servlet will be invoked, which is already by default mapped on the more specific URL pattern *.jsp.
<url-pattern></url-pattern>
Then there's also the empty string URL pattern . This will be invoked when the context root is requested. This is different from the <welcome-file> approach that it isn't invoked when any subfolder is requested. This is most likely the URL pattern you're actually looking for in case you want a "home page servlet". I only have to admit that I'd intuitively expect the empty string URL pattern and the slash URL pattern / be defined exactly the other way round, so I can understand that a lot of starters got confused on this. But it is what it is.
Front Controller
In case you actually intend to have a front controller servlet, then you'd best map it on a more specific URL pattern like *.html, *.do, /pages/*, /app/*, etc. You can hide away the front controller URL pattern and cover static resources on a common URL pattern like /resources/*, /static/*, etc with help of a servlet filter. See also How to prevent static resources from being handled by front controller servlet which is mapped on /*. Noted should be that Spring MVC has a built in static resource servlet, so that's why you could map its front controller on / if you configure a common URL pattern for static resources in Spring. See also How to handle static content in Spring MVC?
I'd like to supplement BalusC's answer with the mapping rules and an example.
Mapping rules from Servlet 2.5 specification:
Map exact URL
Map wildcard paths
Map extensions
Map to the default servlet
In our example, there're three servlets. / is the default servlet installed by us. Tomcat installs two servlets to serve jsp and jspx. So to map http://host:port/context/hello
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Doesn't match any extensions, next.
Map to the default servlet, return.
To map http://host:port/context/hello.jsp
No exact URL servlets installed, next.
No wildcard paths servlets installed, next.
Found extension servlet, return.
Perhaps you need to know how urls are mapped too, since I suffered 404 for hours. There are two kinds of handlers handling requests. BeanNameUrlHandlerMapping and SimpleUrlHandlerMapping. When we defined a servlet-mapping, we are using SimpleUrlHandlerMapping. One thing we need to know is these two handlers share a common property called alwaysUseFullPath which defaults to false.
false here means Spring will not use the full path to mapp a url to a controller. What does it mean? It means when you define a servlet-mapping:
<servlet-mapping>
<servlet-name>viewServlet</servlet-name>
<url-pattern>/perfix/*</url-pattern>
</servlet-mapping>
the handler will actually use the * part to find the controller. For example, the following controller will face a 404 error when you request it using /perfix/api/feature/doSomething
#Controller()
#RequestMapping("/perfix/api/feature")
public class MyController {
#RequestMapping(value = "/doSomething", method = RequestMethod.GET)
#ResponseBody
public String doSomething(HttpServletRequest request) {
....
}
}
It is a perfect match, right? But why 404. As mentioned before, default value of alwaysUseFullPath is false, which means in your request, only /api/feature/doSomething is used to find a corresponding Controller, but there is no Controller cares about that path. You need to either change your url to /perfix/perfix/api/feature/doSomething or remove perfix from MyController base #RequestingMapping.
I think Candy's answer is mostly correct. There is one small part I think otherwise.
To map host:port/context/hello.jsp
No exact URL servlets installed, next.
Found wildcard paths servlets, return.
I believe that why "/*" does not match host:port/context/hello because it treats "/hello" as a path instead of a file (since it does not have an extension).
The essential difference between /* and / is that a servlet with mapping /* will be selected before any servlet with an extension mapping (like *.html), while a servlet with mapping / will be selected only after extension mappings are considered (and will be used for any request which doesn't match anything else---it is the "default servlet").
In particular, a /* mapping will always be selected before a / mapping. Having either prevents any requests from reaching the container's own default servlet.
Either will be selected only after servlet mappings which are exact matches (like /foo/bar) and those which are path mappings longer than /* (like /foo/*). Note that the empty string mapping is an exact match for the context root (http://host:port/context/).
See Chapter 12 of the Java Servlet Specification, available in version 3.1 at http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html.
We usually end up with writing <url-pattern>/*</url-pattern> in web.xml for any Filter in servlets.
<filter-mapping>
<filter-name>requestRedirectorFilter</filter-name>
<url-pattern>/action</url-pattern>
</filter-mapping>`.
Now my doubt is how java identifies which is next servlet/jsp is? Because any request we make through
request.getRequestDispatcher("/ABCXYZ").forward(request, (HttpServletResponse)servletResponse);
to navigate on next servlet/jsp, container by default is going to search in web.xml. And in web.xml <url-pattern>/*</url-pattern> is already there for the filter we use. Exactly here actual problem begins.
If <url-pattern>/*</url-pattern> [which is acting like a universal receiver for any request] is already there in web.xml then How the heck container knows to follow <url-pattern>/ABCXYZ</url-pattern> instead <url-pattern>/*</url-pattern> ? Please share your views and knowledge on this front.
Servlet Matching Procedure
A request may match more than one servlet-mapping in a given context. The servlet container uses a straightforward matching procedure to determine the best match.
The matching procedure has four simple rules.
First, the container prefers an exact path match over a wildcard path match.
Second, the container prefers to match the longest pattern.
Third, the container prefers path matches over filetype matches.
Finally, the pattern <url-pattern>/</url-pattern> always matches any request that no other pattern matches.
For example, a context web.xml file can map the home page for an online catalog to one pattern and the search page for the catalog to a different pattern, as shown below:
<servlet-mapping>
<servlet-name>catalogBrowse</servlet-name>
<url-pattern>/Catalog/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>catalogSearch</servlet-name>
<url-pattern>/Catalog/search/*</url-pattern>
</servlet-mapping>
Below figure illustrates the matching process for a context. Since the container prefers to match the longest pattern, a URL that includes /Catalog/search/ always matches the mapping for catalogSearch rather than the mapping for catalogBrowse.
URL pattern matching
It is copied form the below link if your are not interested to go to the link.
Please have a look at URL Patterns where it is described in detail with examples.
I want my spring application to access url like http://myapplication.com/app1/feature/ rather than http://myapplication.com/app1/feature.html
So basically how should I configure.
My Current config is below it works with *.html
web.xml
and it gives 404 error it I do map it to * .* etc
and it gives 404 error it I do map it to * .* etc
The servlet spec is very strict about what's allowed in a url-pattern. You're probably looking for /*, which will direct all requests to the DispatcherServlet, regardless of the path. Then it's up to you to define what happens.
For reference, "Specification of Mappings" (12.2) allows the following patterns:
A string beginning with a ‘/’ character and ending with a ‘/*’ suffix is used for
path mapping.
A string beginning with a ‘*.’ prefix is used as an extension mapping.
The empty string ("") is a special URL pattern that exactly maps to the
application's context root, i.e., requests of the form http://host:port/<contextroot>/. In this case the path info is ’/’ and the servlet path and context path is
empty string (““).
A string containing only the ’/’ character indicates the "default" servlet of the
application. In this case the servlet path is the request URI minus the context path
and the path info is null.
All other strings are used for exact matches only
My filter mapping in web.xml is as follows:
<filter>
<filter-name>LoginCheckFilter</filter-name>
<filter-class>com.tutorial.filter.LoginCheckFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>LoginCheckFilter</filter-name>
<url-pattern>/admin*</url-pattern>
</filter-mapping>
When I run my app and hit http://localhost:8080/admin my filter is not getting executed. I'm not able to understand why.
Is there any problem with the pattern. Also If I remove '*' from the pattern then the filter is getting executed on hitting above url.
Need help on this. Thanks.
The specifications (paragraph 12.2) says the following:
In the Web application deployment descriptor, the following syntax is
used to define mappings:
A string beginning with a ‘/’ character and
ending with a ‘/*’ suffix is used for path mapping.
A string
beginning with a ‘*.’ prefix is used as an extension mapping.
The
empty string ("") is a special URL pattern that exactly maps to the
application's context root, i.e., requests of the form
http://host:port/<contextroot>/. In this case the path info is ’/’ and
the servlet path and context path is empty string (““).
A string
containing only the ’/’ character indicates the "default" servlet of
the application. In this case the servlet path is the request URI
minus the context path and the path info is null.
All other strings
are used for exact matches only.
So the * is taken literally, unless the pattern ends with /* or starts with *.
Use /admin/* instead of /admin*.
Servlet container will not recognize /admin* as correct URL pattern.
Maybe try:
<url-pattern>/admin/*</url-pattern>
While configuring the security constraints for a web-module's roles in J2EE application I'm having the following problem:
Application:
Giving a servlet named customersServlet, which receives two parameters in the URL:
A string representing an operation (INS, UPD, DLT and DSP).
An identification number to identify a customer on which the operation will be performed.
E.G.: the url /servlet/cusotmersServlet?UPD,5 is used to update customer number 5 data, and the url /servlet/customersServlet?DLT,8 is used to delete customer number 8.
Problem:
If I use this security-constraint the servlet can only be accessed by the role specified, which is ok:
<security-constraint>
<web-resource-collection>
<web-resource-name>...</web-resource-name>
<url-pattern>/servlet/clientsServlet*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>clientAdmin</role-name>
</auth-constraint>
</security-constraint>
But I want to restrict the ability to insert customers only to a role named clientAdmin.
I've tried several url patterns but none of them works as I want (all of them allow every role to access the servlet with any parameter):
<url-pattern>/servlet/clientsServlet?INS,*</url-pattern>
<url-pattern>/servlet/clientsServlet?INS/*</url-pattern>
...
How to use the wildcard * in the url-pattern tag?
Note: The application cannot be changed, so I need a solution that only implies touching the deployment descriptor.
The <url-pattern> tag only allows a very restricted subset of wildcards. This is probably not what you are used to from other situations, where a * can be used at any position. You can download the Servlet specification here:
http://jcp.org/aboutJava/communityprocess/mrel/jsr154/index2.html
Section SRV.11.2 of that document describes how these URL patterns are interpreted. In particular, the * does not mean "zero or more arbitrary characters" here.
Note: The application cannot be changed, so I need a solution that only implies touching the deployment descriptor.
Not sure if this counts as an application change - perhaps you could think of it as a plug-in. You could add a Filter. This would require the ability to add a new JAR to WEB-INF/libs and the ability to define the filter in web.xml. The Filter would allow you to restrict access programmatically.