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

Creating a simple web application with 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 (by default and one that would take 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 pick them up for display. But there is a problem. We do not create objects of our servlets, 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 to create the general list which would be visible in both our servlets? If we simply create our own list object in each servlet, then it turns out that we will add users to one list, and display a list of users using the ListServlet servlet - 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 in the entire program. Hope, Have you heard anything about design patterns? And perhaps for someone this is the first real need to use a template Singleton in your program. You can pervert and write down some cool singleton, with double checks and synchronization (yes, we have a multi-threaded application, since the Tomcat servlets are launched in different threads), but I will use the early initialization option, since in this case it quite suitable.
Model creation.
Then we will create a class (and implement the singleton template in it) in the model package, and 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 - just return a list of strings (usernames). Since our user object consists of a username and password, we would not want to "shine" 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 have heard about singleton, it means that you have probably heard about another design pattern - MVC (model-view-controller, or model-view-controller in Russian, or just like model-view-controller in English). Its essence is to separate the business logic from the presentation. That is, separate the code that determines what to do from the code that determines how to display. View (view or just views) is just responsible for how to present some data. In our case, the views are our jsp pages. That is why I put them in a folder called views. The model is actually the data itself with which the program works. In our case, these are users (list of users). Well, controllers are the link between them. They take data from the model and pass it to the views, or they receive some data from the tomcat, process it and pass 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. So everyone minds their own business:
  • model stores data
  • views draw a beautiful representation of the data
  • controllers handle data
This allows all of them to be fairly simple and maintainable. And not a monstrous dump of all code in one class. MVC is suitable not only for web programming, but nevertheless it is 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 get back 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 is normal, the other is a password type) and a button for sending data to the server.
Here, the form has a method attribute with a value of post. This indicates that the data from this form will fly to the server in the form of a POST request. The action attribute is not specified, so this request will fly 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 extract from the request object in the doPost () method , process and transfer to the model for saving). It is worth noting that the inputs have the name parameter here (for the field with the name it has the value name, and for the field with the password it has the value pass). This is a pretty important point. Since in order to get this data from the request (inside the servlet already) (the name and password that will be entered) - we will use exactly these name and pass. But more on that later. The send data button itself is again made in the form of a button, and not as an input, as is usually the case. I don’t know how universal this option is, but it works for me in chrome :)
Handling a POST request by a servlet.
Let's go back 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 catch POST requests as well, we also override the doPost() method. It receives similar request and response objects from the tomcat, which we will work with. To begin with, we will extract the name and pass parameters from the request that the form sent (if you named them differently in the form, then you write those names). After that, we will create an object of our user using the received data. Then we 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); }
Passing data to the view.
Now let's move on to the ListServlet servlet. We have already implemented the doGet() method here, which simply transfers control to the list.jsp view. If you don't already have it, 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 beautifully. To do this, we will use again the request object that we received from the tomcat. We can add an attribute to this object, giving it some name and, in fact, the object itself, which we would like to transfer to the view. Due to the fact that when transferring the execution process from the servlet to the 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 get our list of user names from this request object in the view. We have finished with the ListServlet class, so I am giving the code of 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); } }
Execution of java code in jsp files.
Now let's move on to the list.jsp file. This file will only be executed when the ListServlet sends an execution process here. In addition, we have already prepared a list of usernames from the model in that servlet and passed it here in the request object. Given a list of names, we can loop through it with a for loop and output each name. As I said, jsp files can execute java code (in principle, this is what differs from static html pages). In order to execute some code, it is enough to put the construction in the right place for us <% // 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 responce - the response object, in the servlet it was called resp out - an object of type JspWriter (inherited from the usual Writer), using 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 jsp java code section, you will see the results in the tomcat console, and not on the page, as you might like :) You can search for other available objects inside jsp here. Using the request object, we can get the list of names that were passed from the servlet (we attached the appropriate attribute to this object), and using the out object, we can display these names. Let's do it for now just in the form of an html list: If we want to display the list only when there are users, otherwise we want to display a warning that there are no users yet, we can rewrite this section a bit:
    <% 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!

    "); %>
    Now that we know how to pass data from servlets to views, we can slightly improve our AddServlet so that a notification is displayed about the successful addition of a user. To do this, in the doPost () method, after we have added a new user to the model, we can add the name of this user to the attributes of the req object and transfer control back to the add.jsp view. And in it already make a section with Java code, where to check whether there is such an attribute in the request, and if so, then display a message that the user has been successfully added. After these changes, the complete AddServlet servlet code will look something like this: 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); } } Here, at the end of the doPost() method, we set an attribute with the name of the user added to the model, after which we call the doGet() method, into which we pass the current request and response. And the doGet () method already transfers control to the view, where it sends the request object with the added user name attached as an attribute. It remains to correct add.jsp itself so that it displays such a notification if such an attribute is present. The final version of add.jsp The body of the page consists of a div with a header, then a div container for the content, it checks if an attribute with the username exists, then a div with the form for adding users, and at the end a footer with a button to return to the main page page. It may seem like too many divs, but we will use them later when we add styles :) And the final version of list.jsp <%@ 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

    <%@ 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!

    "); %>
    Thus, we have a fully working web application that can store and add users, as well as display a list of their names. It remains only to embellish ... :)
    Adding styles. We use the W3.CSS framework.
    At the moment, our application is working, but absolutely eye-catching :) We need to add a background, text and button colors, style lists, make 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 W3.CSS CSS framework . It already has ready-made classes with styles, it remains only to place in the right places those 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. walk 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 permanent 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 style file and place it somewhere inside the web folder (for example, web/styles/w3.css), then go 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 sign 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 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" + "
    "); %>
    That's all :) If you have any questions or comments, or vice versa something doesn't work - leave a comment. Well, I'll attach a couple of screenshots of what came out of it all. Application main page Add user window a list of users And finally. If you want to practice with this project - you can try:
    • make a servlet and a jsp for deleting a user and a couple more for changing/editing an existing user. You will get a real CrUD web application :) on servlets))
    • replace list (List ) to work with the database so that the 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