JavaRush /Java Blog /Random EN /Creating a simple web application using servlets and jsp ...
Стас Пасинков
Level 26
Киев

Creating a simple web application using servlets and jsp (part 1)

Published in the Random EN group
Level of knowledge required to understand the article: you have already more or less understood Java Core and would like to look at JavaEE technologies and web programming. It makes the most sense if you are currently studying the Java Collections quest, which covers topics close to the article. Creating a simple web application using servlets and jsp (part 1) - 1This material is a logical continuation of my article Creating a simple web project in IntelliJ Idea Enterprise . In it I demonstrated how to create a working web project template. This time I'll show you how to create a simple but pretty web application using the Java Servlet API and JavaServer Pages API technologies. Our application will have a home page with two links:
  • to the user adding page;
  • to the user list view page.
I'll still be using IntelliJ Idea Enterprise Edition, Apache Maven (just include a few dependencies) and Apache Tomcat. At the end, we will “decorate” our application using the W3.CSS framework . We will assume that at the moment you already have an empty project, which we will develop here. If not, go through the first article and make it. It will only take a few minutes :)

A little about the structure of the future application

Our main page ( / ) will be the most ordinary static html page with a header and two links/buttons:
  • add a new user (will be sent to /add );
  • view the list of users (sends to /list ).
Tomcat will catch requests to these addresses and send them to one of the two servlets that we will make (we will describe the mapping in the web.xml file ). And the servlets, in turn, will process requests, prepare data (or save it if a user is added), and transfer control to the corresponding jsp files, which will already “render” the result. We will store the data in the most common list (List).

Let's create a static home page

If you have index.jsp in your web folder , delete it. Instead, in this folder we will create a simple html file called index.html :
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My super project!</title>
</head>
<body>
    <!-- header -->
    <div>
        <h1>Super app!<//h1>
    </div>

    <div>       <!-- content -->
        <div>    <!-- buttons holder -->
            <button onclick="location.href='/list'">List users<//button>
            <button onclick="location.href='/add'">Add user<//button>
        </div>
    </div>
</body>
</html>
There's nothing complicated here. In title we indicate the title of our page. In the body of the page we have two main divs: header (header) and content (content). In the content we have a holder for our buttons, and actually two buttons that, when clicked, are sent to the appropriate addresses. You can run the project and see what it looks like now. If you click on the buttons, pages with a 404 error open because we don't have them yet. But this suggests that the buttons work. Let me note that this is not the most universal option, because if you suddenly have JavaScript disabled, these buttons will be of no use in the browser. But we will assume that no one disabled JavaScript :). It is clear that simple links could be used, but I prefer buttons. You do what you like best. And don’t look at the fact that in my examples there will be a lot of divs . Then we will fill them with styles, and everything will look more beautiful :).

Create jsp files to render the result

In the same web directory , we will create a folder where we will put our jsp files . I called it views, and again, you can improvise. In this folder we will create two jsp files:
  • add.jsp — page for adding users;
  • list.jsp - page for displaying a list of users.
Let's give them the appropriate page headings. Something like “Add new user” and “Users list”, and we’ll leave it that way for now.

Let's create two servlets

Servlets will accept and process requests that Tomcat will pass to them. In the src/main/java folder we will create an app package , which will contain our sources. There we will have more different packages. Therefore, so that these packages are not created inside each other, let's create some class in the app package (then delete it). Now let's create three different packages in the app package:
  • entities - this is where our entities will lie (the class itself, which will describe user objects);
  • model - our model will be here (more on this a little later);
  • servlets - well, here will be our servlets.
After this, you can safely remove that class from the app package (if you created it, of course). In the servlets package we will create two classes:
  • AddServlet - will process requests received at /add ;
  • ListServlet - will process requests received at /list .

Connecting dependencies in Maven

Tomcat version 9.* implements the Servlet version 4.0 and JavaServer Pages version 2.3 specifications. This is written in the official documentation of Tomcat 9 in the first paragraph in the second line. This means that if you, like me, are using this version of Tomcat, then the code we write and send to run will use exactly the specified versions. But we would like to have these specifications in our project, so that our code that uses them will at least compile successfully. And for this we need to load them into our project. This is where Maven comes to the rescue.

The general rule is this: if you need to connect something to your project using Maven:

  • go to the Maven repository website;
  • look there for the library you need and the version you need;
  • you get the dependency code that needs to be inserted into your pom.xml;
  • insert! :)
So let's begin. First, let's prepare a pom file . Somewhere after /version but before /project , insert the following:
<dependencies>

</dependencies>
Thus, we indicated that inside these tags we will list the dependencies we need. Now go to mvnrepository.com , there will be a search field at the top. First, enter servlet into the search. The first result, where there are more than seven thousand uses, suits us. We remember that we need version 4.0 (for Tomcat 9; for other versions, older implementations may be suitable). This is a fairly recent version, so there aren't many uses, but it's the one we need. A page will open where you can get the code for this dependency for various package managers and you can even just download it. But since we want to connect it using Maven, we select the code on the Maven tab. We copy and paste into our pom file inside the dependencies section. If a notification appears in the lower right corner of IDEA asking if we want to enable auto-import, we agree. If you accidentally refused, go to “Settings” and enable auto-import manually: Settings (Ctrl + Alt + S) -> Build, Execution, Deployment -> Maven -> Importing This will keep the pom file and IDEA configuration files for this project in sync. Now, using the same principle, we will find and connect JavaServer Pages version 2.3 (enter jsp in the search). And since we’ve already taken up Maven, let’s immediately tell it that our sources comply with Java 8 syntax, and that they need to be compiled into bytecode of the same version. After all these manipulations, our pom.xml will look something like this:
<?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>ru.javarush.info.fatfaggy</groupId>
    <artifactId>my-super-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compile.source>
        <maven.compiler.target>1.8</maven.compile.target>
    </properties>

    <dependencies>
        <!-- Servlet API 4.0 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>4.0.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- JavaServer Pages API 2.3 for tomcat 9 -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

</project>

Making our servlets real servlets

At this point, the couple of servlets we've created are actually just regular classes. They don't have any functionality. But now we have connected the Servlet API to our project, and, if so, we can use classes from there. To make our servlets “real” servlets, we simply need to inherit them from the HttpServlet class .

Mapping or partitioning

Now it would be nice to somehow tell Tomcat so that requests from /add are handled by our AddServlet servlet , and therefore requests from /list are handled by the ListServlet servlet . This process is called mapping . This is done in the web.xml file according to this principle:
  • first we describe the servlet (we give some name and indicate the path to the class itself);
  • then we bind this servlet to a specific address (we indicate the name of the servlet that we just gave it and indicate the address from which requests should be sent to this servlet).
Let's describe the servlet:
<servlet>
    <servlet-name>add</servlet-name>
    <servlet-class>app.servlets.AddServlet</servlet-class>
</servlet>
Now we bind it to the address:
<servlet-mapping>
    <servlet-name>add</servlet-name>
    <url-pattern>/add</url-pattern>
</servlet-mapping>
As you can see, the servlet-name is the same in both cases. Thanks to this, Tomcat knows that if a request comes to the /add address , it needs to be passed to the app.servlets.AddServlet servlet . We do the same with the second servlet. As a result, our web.xml has approximately the following content:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <!-- add servlet -->
    <servlet>
        <servlet-name>add</servlet-name>
        <servlet-class>app.servlets.AddServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>add</servlet-name>
        <url-pattern>/add</url-pattern>
    </servlet-mapping>

    <!-- list servlet -->
    <servlet>
        <servlet-name>list</servlet-name>
        <servlet-class>app.servlets.ListServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>list</servlet-name>
        <url-pattern>/list</url-pattern>
    </servlet-mapping>
</web-app>
By the way, we didn’t create markup for the main page here (at / ). The fact is that in this case we don’t need it. Our home page is a simple html file that simply displays two buttons. There is no dynamic content, so it makes no sense for us to create a separate servlet for it, to which requests from the address / will be sent , and which will do nothing except transfer execution to some jsp (which would also have to be created), which would draw If only we had two buttons. We don't need this; we're happy with a static resource. When Tomcat receives a request, it will check that there is not a single servlet that could process the request at such an address, and then it will see that at this address there is actually a ready-made html file , which it will successfully send. We can run our application again (restart the server or re-deploy, as you wish) and make sure that the main page is rendered, nothing is broken, when we click on the buttons, transitions occur, but for now an error is also written. By the way, if before we had a 404 error, now we have a 405. This means the mapping worked, the servlets were found, but they just didn’t have any suitable methods to process the request. If at this stage you still get a 404 error, although everything was done correctly, perhaps you should correct the deployment configuration in the idea. To do this, you need to go to Edit configurations (at the top near the start button), go to the Deployment tab on the right side of the window and make sure that in the Application context it is simply indicated /

A short lyrical digression: what is happening “under the hood”?

You've probably already wondered how our application works in Tomcat? What's going on there? And where is the main() method ? As soon as you type localhost:8080 into your browser and go to this address, the browser sends a request to this address via the http protocol . I hope you are already aware that requests can be of different “types”, the most popular being GET and POST . Every request must have an answer. A GET request expects that in response it will be given a ready-made html code , which will be returned to the browser, and the browser will beautifully replace this code with all sorts of letters, buttons, and forms. The POST request is a little more interesting, since it also carries some information with it. For example, in the user registration or authorization form, you entered your data and clicked “send”. At this moment, a POST request was sent to the server with your personal information inside. The server accepted this information, processed it and returned some kind of response (for example, an html page with your profile). The fundamental difference between them is that GET requests are intended only to receive data from the server, while POST requests carry some information with them, and the data on the server may change (for example, when you upload your photo to the server, it will fly in the POST request and the server will add it to the database, that is, some change will occur. Now let's go back to Tomcat. When it receives some request from the client, it looks at the address. Searches its data to see if there is a suitable servlet, which would process requests to such an address (or a ready-made resource that can be returned right away). If it doesn’t find anything to return, it responds not with an html page, but with a 404 response. If it finds a suitable servlet, which "sits" on this address, it looks at what type of request it received (GET, POST, or some other), and then asks the servlet if it has a method that could handle this type of request. If the servlet says, that it cannot process this type, Tomcat responds to the client with code 405. This is what just happened to us. But if a suitable servlet is found, and it has a suitable method, Tomcat creates an object of this servlet, runs it in a new thread ( thread ), which allows the servlet to work in a separate thread, and Tomcat continues to work further in its own, receiving and sending requests. In addition, Tomcat creates two more objects: one of type HttpServletRequest (I will briefly call it a request in the future), and the second of type HttpServletResponse(I will call it the answer). In the first object it places all the data that it received in a request from the client, so all that data can be pulled out from this object. Well, after all this, it passes these two objects to the appropriate method of the servlet that is running in a separate thread. As soon as the servlet finishes its work and has a response ready to send to the client, it raises a flag to Tomcat, saying, “I’m done, everything is ready.” Tomcat accepts the response and sends it to the client. This allows Tomcat to accept requests and send responses without interruption, while all the work is done by servlets running in separate threads. Accordingly, when we write servlet code, we define the work that will be performed. And yes, you can think of the main() method as being in Tomcat itself (yes, it's written in Java), and when we "start" Tomcat, the main().

We catch GET methods with servlets and send simple responses

At the moment, our servlets do not have suitable methods (GET), so Tomcat returns us a 405 error. Let's make them! The HttpServlet class , from which we inherit our servlets, defines different methods. In order to set some code for methods, we simply override them. In this case, we need to override the doGet() method in both servlets.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}
As you can see, this method accepts two objects: req (request) and resp (response). These are the very objects that Tomcat will create and populate for us when it calls the appropriate method in this servlet. First, let's do the simplest answers. To do this, take the resp object and get from it a PrintWriter object , which can be used to compose responses. Well, using it we will print some simple string.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("Method GET from AddServlet");
}
We’ll do something similar in the ListServlet servlet , after which we’ll start our server again. As you can see, everything works! When you click on the buttons, pages open with the text that we “recorded” with PrintWriter . It’s just that our jsp that we prepared for generating pages with answers are not used in any way. This is because the execution simply does not reach them. The serverlet itself now generates a response and finishes its work, signaling Tomcat that it has a response ready for the client. Tomcat simply takes this response and sends it back to the client. We transfer control from the servlets to jsp. Let's change the code of our methods this way:
  • we get from the request object a request manager object, where we pass the jsp address of the page to which we want to transfer control;
  • using the received object, we transfer control to the specified jsp page, and do not forget to attach there the request and response objects that we received from Tomcat.
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
    requestDispatcher.forward(req, resp);
}
In the body of jsp pages (inside the body tag) we can write something so that we can clearly see which page is being displayed. After that, we restart the server and check. Buttons on the main page are pressed, pages are opened, which means requests are sent to servlets, after which control is transferred to jsp pages, which are already rendered. That's all. In the next part of the article we will deal with the functionality of our application.

What else to read:

Creating a simple web project in IntelliJ Idea Enterprise. Step by step, with pictures


My chat
Comments
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION