JavaRush /Java Blog /Random EN /Creating a simple web application using servlets and jsp ...
fatfaggy
Level 26
Киев

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

Published in the Random EN group
I continue to describe the process of creating a web application using servlets, jsp, Maven and Tomcat. Beginning of the article , if necessary.
We create entities.
Let's create a User class in the entities package, in which we will create two private string variables name and password. Let's create constructors (default and one that would accept both values), getters/setters, override the toString() method just in case, as well as the equals() and hashCode() methods. public class User { private String name; private String password; public User() { } public User(String name, String password) { this.name = name; this.password = password; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", password='" + password + '\'' + '}'; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (name != null ? !name.equals(user.name) : user.name != null) return false; return password != null ? password.equals(user.password) : user.password == null; } @Override public int hashCode() { int result = name != null ? name.hashCode() : 0; result = 31 * result + (password != null ? password.hashCode() : 0); return result; } } Now we can start creating a list of users, where we will add our users, and from where we will take them for display. But there is a problem. We do not create our servlet objects; Tomcat creates them for us. The methods that we override in them are also already defined for us and we cannot add a parameter. How then can we create a common list that would be visible in both of our servlets? If we simply create our own list object in each servlet, it will turn out that we will be adding users to one list, but displaying a list of users using the ListServlet servlet will be completely different. It turns out that we need an object that would be common to both servlets. Generally speaking, we need an object that would be common to all classes in our program; the only object for the entire program. I hope you've heard something about design patterns. And perhaps for some this is the first real need to use the Singleton template in their program. You can get creative and make some cool singleton, with double checks and synchronization (yes, we have a multi-threaded application, since Tomcat runs servlets in different threads), but I will use the option with early initialization, since in this case it quite suitable.
Creating a model.
Then we’ll create a class (and implement the singleton template in it) in the model package, and we’ll also call it quite colorfully Model. Let's create a private user list object in it, and make two methods: one so that you can add a user, and the second - let it simply return a list of strings (user names). Since our user object consists of a name and password, we would not like to “reveal” user passwords, so we will only return a list of their names. public class Model { private static Model instance = new Model(); private List model; public static Model getInstance() { return instance; } private Model() { model = new ArrayList<>(); } public void add(User user) { model.add(user); } public List list() { return model.stream() .map(User::getName) .collect(Collectors.toList()); } }
A little about mvc.
Since you've heard about singleton, it means you've probably heard about another design pattern - MVC (model-view-controller, or in Russian model-view-controller, or just like in English model-view-controller). Its essence is to separate business logic from presentation. That is, separate the code that determines what to do from the code that determines how to display . The View (view or just views) is responsible for the form in which some data is presented. In our case, views are our JSP pages. That's why I put them in a folder called views. The model is the actual data with which the program works. In our case, these are users (list of users). Well, controllers are the connecting link between them. They take data from the model and transfer it to views, or they receive some data from Tomcat, process it and transfer it to the model. Business logic (that is, what to do ) should be described in them, and not in the model or in the view. Thus, everyone does their own thing:
  • model stores data
  • Views draw a beautiful representation of data
  • controllers process data
This allows them all to be fairly simple and maintainable. And not a monstrous dump of all code in one class. MVC is not only suitable for web programming, but it is still very common (if not always) in this area. In our case, servlets will act as controllers. Yes, this is a very superficial and even rough description of this pattern, but this article is not about design patterns, but about how to make a simple web application :) Who wants to know more - Google knows everything ! :) Let's return to our views.
Create a form for adding a user.
Let's add a form to the add.jsp file, consisting of two text inputs (one regular, the other a password type) and a button for sending data to the server. Here the form has a method attribute with the value post. This means that the data from this form will be sent to the server in the form of a POST request. The action attribute is not specified, which means this request will go to the same address where we went to this page (/add). Thus, our servlet, which is bound to this address, upon receiving a GET request, returns this jsp with the form for adding users, and if it receives a POST request, then this form has sent its data there (which we will retrieve from the request object in the doPost() method , process it and transfer it to the model for saving). It is worth noting that inputs have a name parameter here (for a field with a name it has the value name, and for a field with a password it has the value pass). This is a pretty important point. Since in order to get this data (name and password that will be entered) from the request (already inside the servlet), we will use exactly these name and pass. But more on that later. The button for sending data itself is again made in the form of a button, and not an input, as is usually customary. I don’t know how universal this option is, but it works for me in Chrome :)
Processing a POST request with a servlet.
Let's return to the AddServlet servlet. We already know that in order for our servlet to be able to “catch” GET requests, we have overridden the doGet() method from the HttpServlet class. To teach our servlet to also catch POST requests, we also override the doPost() method. It receives similar request and response objects from Tomcat, which we will work with. First, let’s extract from the request the name and pass parameters that the form sent (if you named them differently in the form, then those are the names you write). Then we will create our user object using the received data. Then we will get the model object and add the created user to the model. @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); }
Transferring data to the view.
Now let's move on to the ListServlet servlet. We have already implemented the doGet() method, which simply transfers control to the list.jsp view. If you don’t have this yet, do it by analogy with the same method from the AddServlet servlet. Now it would be nice to get a list of usernames from the model and pass them to the view, which will receive them there and display them nicely. To do this, we will again use the request object that we received from Tomcat. We can add an attribute to this object, giving it some name and, in fact, the object itself that we would like to transfer to the view. Due to the fact that when transferring the execution process from a servlet to a view, we pass there the same request and response objects that the servlet itself received, then by adding our list of names to the request object, we can then from this request object in the view create our list of user names and get. We are done with the ListServlet class, so here is the code for the entire class. package app.servlets; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.List; public class ListServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { Model model = Model.getInstance(); List names = model.list(); req.setAttribute("userNames", names); RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp"); requestDispatcher.forward(req, resp); } }
Executing java code in jsp files.
Now let's move on to the list.jsp file. This file will only be executed when the ListServlet passes the execution process here. In addition, in that servlet we have already prepared a list of user names from the model and passed it here in the request object. Given a list of names, we can run a for loop through it and print each name. As I already said, jsp files can execute java code (in principle, this is what makes them different from static html pages). In order to execute some code, it is enough to place a construction in the place we need. <% // java code %> Inside such a construction, we get access to several variables: request - our request object, which we passed from the servlet, where it was simply called req response - the response object, in The servlet was called resp out - an object of the JspWriter type (inherited from the usual Writer), with the help of which we can “write” something directly into the html page itself. Out.println("Hello world!") is very similar to System.out.println("Hello world!"), but don't confuse them! out.println() "writes" to the html page, and System.out.println - to the system output. If you call the System.out.println() method inside the section with jsp code, you will see the results in the Tomcat console, and not on the page, as you might want :) You can look for other available objects inside jsp here . Using the request object we can get the list of names that was passed from the servlet (we attached the corresponding attribute to this object), and using the out object we can display these names. Let's do this for now simply in the form of an html list: If we want to display the list only when there are users, and otherwise display a warning that there are no users yet, we can rewrite this section a little: Now that we know how to transfer data from servlets to views - we can improve our AddServlet a little so that a notification is displayed about the successful addition of a user. To do this, in the doPost() method, after adding a new user to the model, we can add the name of this user to the attributes of the req object and pass control back to the add.jsp view. And in it already make a section with Java code, where you can check whether such an attribute is in the request, and if so, then display a message that the user has been successfully added. After these changes, the complete code of the AddServlet servlet will look something like this: Here, at the end of the doPost() method, we set an attribute with the name of the user added to the model, and then call the doGet() method, to which we pass the current request and response. And the doGet() method already transfers control to the view, where it sends a request object with the name of the added user attached as an attribute. It remains to correct add.jsp itself so that it displays such a notification if such an attribute is present. Final add.jsp
    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { for (String s : names) { out.println("
  • " + s + "
  • "); } } %>
<% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    package app.servlets; import app.entities.User; import app.model.Model; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class AddServlet extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp"); requestDispatcher.forward(req, resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String name = req.getParameter("name"); String password = req.getParameter("pass"); User user = new User(name, password); Model model = Model.getInstance(); model.add(user); req.setAttribute("userName", name); doGet(req, resp); } } <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("

    User '" + request.getAttribute("userName") + "' added!

    "); } %>

    Add user

    The body of the page consists of a div with a header, after which there is a div container for content, in which it checks whether an attribute with the user name exists, then a div with a form for adding users, and at the end a footer with a button to return to the main page. It may seem like there are too many divs, but we will use them later when we add styles :) Well, the final version is list.jsp. Thus , we have a fully working web application that can store and add users, as well as display a list their names. All that remains is to embellish it... :) <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println(" "); for (String s : names) { out.println("
  • " + s + "
  • "); } out.println("
    "); } else out.println("

    There are no users yet!

    "); %>
    Adding styles. We use the W3.CSS framework.
    At the moment, our application is working, but absolutely crazy :) We need to add a background, colors for text and buttons, stylize lists, do alignment, add indents, in general a lot of things. If you write styles manually, it can take a lot of time and nerves. Therefore, I suggest using the CSS framework W3.CSS . It already has ready-made classes with styles; all that remains is to place in the right places the CSS classes that we want to apply in these places. In order to add them to our pages, first we need to include a file with styles. This can be done in two ways: 1. go through our pages and in the head section insert a direct link to the file with styles. This option is suitable if you have a constant Internet connection. Then, when you open your pages on a local server, the styles will be pulled from the Internet. 2. If you want to have all the styles locally and not be dependent on an Internet connection, you can simply download the file with styles and place it somewhere inside the web folder (for example web/styles/w3.css), and then go through on all our pages (index.html, add.jsp, list.jsp) and enter a link to this file with styles inside the head section. After that, just go through the tags and tag them with the styles that you like. I will not dwell on this in detail, but will immediately give my ready-made versions of my three files with arranged style classes. index.html add.jsp list.jsp That's all :) If you still have any questions or have any comments, or on the contrary, something doesn’t work out - leave a comment. Well, I’ll attach a couple of screenshots of what came out of it all. And finally. If you want to practice with this project, you can try: Super app!

    Super app!

    <%@ page contentType="text/html;charset=UTF-8" language="java" %> Add new user

    Super app!

    <% if (request.getAttribute("userName") != null) { out.println("
    \n" + " ×\n" + "
    User '" + request.getAttribute("userName") + "' added!
    \n" + "
    "); } %>

    Add user

    <%@ page import="java.util.List" %> <%@ page contentType="text/html;charset=UTF-8" language="java" %> Users list

    Super app!

    Users

    <% List names = (List ) request.getAttribute("userNames"); if (names != null && !names.isEmpty()) { out.println("
      "); for (String s : names) { out.println("
    • " + s + "
    • "); } out.println("
    "); } else out.println("
    \n" + " ×\n" + "
    There are no users yet!
    \n" + "
    "); %>
    Application home page Add user window a list of users
    • make a servlet and jsp to delete a user and a couple more to change/edit an existing user. You will get a real CrUD web application :) on servlets))
    • replace list (List ) to work with the database so that added users do not disappear after the server is restarted :)
    Good luck!
    Comments
    TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
    GO TO FULL VERSION