What is a servlet?
First, let's figure out what servlets are and why you hear about them so often. The Java Servlet API is a standardized API intended to be implemented on the server. It interacts with clients according to a request-response scheme. A servlet is a class that can receive requests from a client and return responses to the client. In fact, servlets are exactly the building blocks we use to create a client-server architecture in Java. You may recall that we already spoke about that architecture in another one of the articles in the series. We're not going to beat around the bush: let's write some code right away.What you need to create a web application
For greatest convenience when working with Java servlets, you need IntelliJ IDEA Ultimate Edition. It is a paid product, but you can activate a 30-day trial or use the early access version, which is always free. Also, install Apache Tomcat — our application's server. Tomcat is a servlet container: it processes incoming requests and passes them to our application. Download Tomcat at here.Let's create our first web application
If everything is ready, create a Maven project. If you're not familiar with Maven, take a look at the previous article. Let's begin!In pom.xml, add a javax.servlet-api dependency and specify WAR packaging:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>servlets</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <dependencies> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> </dependency> </dependencies> </project>
Simple servlet class:
import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; @WebServlet("/hello") public class MainServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html"); PrintWriter printWriter = resp.getWriter(); printWriter.write("Hello!"); printWriter.close(); } }
To run the application, you need to create a Tomcat configuration:
Next, we indicate which version of Tomcat we will use, and the URL and port for communicating with the server. You should have something like this:
Now we just need to specify the artifact (the assembled project in a JAR archive) that will be deployed in the container. You can click the Fix button and select war exploded: this means that after the project is rebuilt, the artifact will automatically be placed in the servlet container.
The default value for Application context is servlets_war_exploded. This means that we access the application at: http://localhost:8080/servlets_war_exploded.
Why would we want any extra text? Let's delete what is unnecessary. Now we our web application's address is: http://localhost:8080.
Click OK. We see that we can now launch the application:
Now when you open the application in your browser, you should get a 404 error. This is makes sense, because the address http://localhost:8080/ needs a servlet that maps to "/", but our only servlet maps to "/hello".
We can access it at http://localhost:8080/hello. Once we do that, we get the expected answer — the string "Hello"!
@WebServlet()
annotation. This is where we bind (or map) the servlet to a specific path ("/hello"). This annotation appeared only in Java Servlet API 3.0, so the Internet has a lot of examples where servlet mapping happens through an XML file. This is no longer necessary.
To handle GET requests, we override the doGet()
method. Pay attention to the method's parameters: HttpServletRequest
and HttpServletResponse
. The HttpServletRequest
object provides us with all the necessary information about the request. In the HttpServletResponse
, we write our response and set the necessary headers.
Working with parameters and a session
Let's improve our servlet so that it can process request parameters and work with a session:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet("/hello")
public class MainServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
HttpSession session = req.getSession();
Integer visitCounter = (Integer) session.getAttribute("visitCounter");
if (visitCounter == null) {
visitCounter = 1;
} else {
visitCounter++;
}
session.setAttribute("visitCounter", visitCounter);
String username = req.getParameter("username");
resp.setContentType("text/html");
PrintWriter printWriter = resp.getWriter();
if (username == null) {
printWriter.write("Hello, Anonymous" + "<br>");
} else {
printWriter.write("Hello, " + username + "<br>");
}
printWriter.write("Page was visited " + visitCounter + " times.");
printWriter.close();
}
}
Now the servlet works with a session, increasing the value of visitCounter
every time the page is visited. If the visitCounter
attribute has not yet been created (upon the first visit to the page), the getAttribute()
method returns null, so we need to check for null. The same goes for request parameters. If the user does not pass the username parameter, then its value will be null. In this case, we greet the user as an anonymous visitor.
To pass a parameter in a GET request, a query string is used, For example, we could use the following URL: http:// localhost:8080/hello?Username=Paul. You can read more about HTTP requests in the previous article in the series.
Our application currently doesn't have much logic, but it's a little annoying that we get a 404 error at the root path. To fix this, we'll create another servlet and map it to the start page: @WebServlet("/")
. The purpose of this servlet is to redirect requests to the "/hello" path. There are two ways to do this: using "forward" or "redirect". Perhaps it's worthwhile to understand the difference between them.
A forward delegates processing of the request to another servlet on the server. The client is not involved. To do this, add the following code to the new servlet's doGet() method:
getServletContext().getRequestDispatcher("/hello").forward(req, resp);
In this code, we access the servlet context, get the request dispatcher for the relevant servlet, and ask it to process a specific request with the specified arguments (req, resp).
A redirect returns to the client the address that the client must use to process its request. Most browsers automatically navigate to the returned URL. To implement a redirect, you need to add this code:
resp.sendRedirect(req.getContextPath() + "/hello");
We call the redirect()
method on the HttpServletResponse
parameter and pass it the address that the client needs to use. Here's an important detail: HTTP parameters must also be added at the end of the full redirect path, which is not very convenient.
In our situation, it is preferable to use forward
, but sometimes using redirect
is better. If you understand the difference in how they work, you won't make the wrong choice.
The code for the new servlet looks like this:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/")
public class IndexServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// getServletContext().getRequestDispatcher("/hello").forward(req, resp);
resp.sendRedirect(req.getContextPath() + "/hello");
}
}
GO TO FULL VERSION