First of all, put the servlet class in a Java package
(you
should ALWAYS put publicly reuseable Java classes in a package, otherwise they are invisible to classes which are by itself in a package). This way you eliminiate potential environment-specific problems. In case of a "plain" IDE project, the class needs to
be placed in its package structure inside "Java Resources" folder (and thus NOT "WebContent", this is for web files such as JSP). In case of a Maven project, the class needs to be placed in its package structure inside main/java
(and
thus NOT e.g. main/resources
,
this is for non-class files).
Second, the servlet's URL is specified as the "URL pattern" of the servlet mapping. It's absolutely not per definition the classname/filename of the servlet class.
So, given a servlet class like below,
package com.example;
public class YourServlet extends HttpServlet {
// ...
}
the servlet registration in web.xml
must
look like this:
<servlet>
<servlet-name>yourServlet</servlet-name>
<servlet-class>com.example.YourServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>yourServlet</servlet-name>
<url-pattern>/servlet</url-pattern> <!-- This is the URL of the servlet! -->
</servlet-mapping>
Or, in case you're already on Servlet 3.0+ (Tomcat 7 or newer), and the web.xml
file
is declared conform Servlet 3.0+ (and thus NOT e.g. 2.5 or lower),
then all of above XML code can be replaced by a single @WebServlet
annotation
whose value represents the URL pattern.
package com.example;
@WebServlet("/servlet") // This is the URL of the servlet!
public class YourServlet extends HttpServlet {
// ...
}
As to your concrete problem with the HTML <form>
,
the <form
action>
needs to be a valid URL. You need to understand how absolute/relative URLs work. You know, an URL is a web address as you can enter/see in the webbrowser's address bar. If you're specifying a relative URL as form action, i.e. without the http://
scheme,
then it becomes relative to the current URL as you see in your webbrowser's address bar. It's thus absolutely not relative to the JSP/HTML file location in server's WAR folder structure as many starters
seem to think.
So, provided that a webapp is successfully deployed on a context path of /contextname
,
and the servlet hasn't failed its initialization (read server logs for any deploy/servlet success/fail messages and the actual context path and servlet mapping), then this servlet is available at http://localhost:8080/contextname/servlet
.
So, assuming that the JSP page with the HTML form is opened by http://localhost:8080/contextname/jsps/page.jsp
,
here are several cases:
-
Form action submits to an URL with a leading slash.
<form action="/servlet">
The leading slash /
makes
the URL relative to the domain, thus the form will submit to
http://localhost:8080/servlet
But this will likely result in a 404 as it's in the wrong context.
-
Form action submits to an URL without a leading slash.
<form action="servlet">
This makes the URL relative to the current folder of the current URL, thus the form will submit to
http://localhost:8080/contextname/jsps/servlet
But this will likely result in a 404 as it's in the wrong folder.
-
Form action submits to an URL which goes one folder up
<form action="../servlet">
This will go one folder up (exactly like as in local disk file system paths!), thus the form will submit to
http://localhost:8080/contextname/servlet
This one must work!
The canonical approach, however, is to make the URL domain-relative so that you don't need to fix the URLs once again when you happen to move the JSP files around into another folder.
<form action="${pageContext.request.contextPath}/servlet">
This will generate
<form action="/contextname/servlet">
which will thus always submit to the right URL.
See also: