CodeGym /Blogue Java /Random-PT /Criando um aplicativo da web simples usando servlets e JS...
John Squirrels
Nível 41
San Francisco

Criando um aplicativo da web simples usando servlets e JSPs (parte 2)

Publicado no grupo Random-PT
Criando um aplicativo da Web simples usando servlets e JSPs (parte 1) Conhecimento necessário para entender o artigo: Você já descobriu mais ou menos o Java Core e gostaria de examinar as tecnologias JavaEE e a programação da Web. Faria mais sentido para você estar estudando atualmente a missão Java Collections, que trata de tópicos próximos ao artigo.
Criando um aplicativo da web simples usando servlets e JSPs (parte 2) - 1

Criando entidades

No pacote de entidades , criaremos uma Userclasse que possui duas variáveis ​​string privadas: name e password . Crie construtores (padrão e um que aceita ambos os valores) e getters/setters e substitua o toString()método apenas por precaução, junto com os métodos equals()e hashCode(). Em outras palavras, faremos tudo o que um desenvolvedor Java respeitável faz ao criar uma classe.

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;
    }
}
Agora podemos começar a criar uma lista de usuários. Adicionaremos usuários a ele e retiraremos os usuários dele para exibi-los. No entanto, temos um problema. Não criamos nossos objetos de servlet. O Tomcat faz isso por nós. Os métodos que sobrescrevemos neles já estão definidos para nós, e não podemos parâmetros. Como então criamos uma lista compartilhada que ficará visível em ambos os nossos servlets? Se apenas criarmos um objeto de lista em cada servlet, estaremos adicionando usuários a uma lista, mas exibindo usuários de outra no ListServlet. Portanto, precisamos de um objeto compartilhado por ambos os servlets. De um modo geral, precisamos de um objeto que seja compartilhado por todas as classes do nosso programa: um objeto para todo o programa. Espero que você tenha ouvido algo sobre padrões de projeto. Para algumas pessoas, esta pode ser a primeira necessidade real do padrão Singleton em seu programa. Você poderia enlouquecer e produzir um doce Singleton com verificações duplas e sincronização (sim, nosso aplicativo é multithread, já que os servlets Tomcat são executados em threads separados). Mas vou usar a técnica de inicialização antecipada, porque ela é totalmente adequada para nossos propósitos aqui.

Criando um modelo

Crie uma classe (e implemente o padrão Singleton ) no pacote do modelo e chame-a de algo incomum. Por exemplo, Modelo . Vamos criar uma lista privada de usuários em nossa classe e implementar dois métodos: um para adicionar um usuário e outro para retornar uma lista de strings (nomes de usuário). Como nosso objeto de usuário consiste em um nome de usuário e uma senha, e não queremos revelar as senhas dos usuários, teremos apenas uma lista de nomes.

public class Model {
    private static Model instance = new Model();

    private List<User> model;

    public static Model getInstance() {
        return instance;
    }

    private Model() {
        model = new ArrayList<>();
    }

    public void add(User user) {
        model.add(user);
    }

    public List<String> list() {
        return model.stream()
                .map(User::getName)
                .collect(Collectors.toList());
    }
}

Um pouco sobre MVC

Como você já ouviu falar sobre singleton , provavelmente já ouviu falar sobre outro padrão de design model-view-controller (MVC). Sua finalidade é separar a lógica de negócios da exibição. Ou seja, separar o código que determina o que fazer do código que determina como exibir as coisas. A visão é responsável por como os dados são apresentados. No nosso caso, as visualizações são nossas páginas JSP . É exatamente por isso que os coloco em uma pasta chamada views . O modelo são os dados com os quais o programa realmente trabalha. No nosso caso, são os usuários (lista de usuários). E os controladores são o elo entre eles. Eles pegam dados do modelo e os passam para as visualizações (ou obtêm alguns dados do Tomcat, processe-o e passe-o para o modelo). Você define sua lógica de negócios (o que o programa deve fazer) neles, não no modelo ou na visão. Assim, cada parte cuida do seu próprio negócio:
  • o modelo armazena dados;
  • as visualizações renderizam belas representações dos dados;
  • controladores lidam com o processamento de dados.
Isso permite que o programa seja bastante simples e fácil de manter, em vez de uma pilha monstruosa de todo o código em uma classe. O MVC não é apenas adequado para programação web, mas é usado especialmente frequentemente nesta área (quase sempre). No nosso caso, os servlets atuarão como controladores. Esta é uma descrição muito superficial e breve do padrão, mas o MVC não é o tópico principal deste artigo. Se alguém quiser saber mais, o Google é seu amigo! Crie um formulário para adicionar um usuário. Inclua o formulário em add.jsp . Deve consistir em dois campos de entrada de texto (um comum, o outro - um campo de senha) e um botão para enviar os dados ao servidor.

<form method="post">
    <label>Name:
        <input type="text" name="name"><br />
    </label>

    <label>Password:
        <input type="password" name="pass"><br />
    </label>
    <button type="submit">Submit</button>
</form>
Aqui o formulário tem um atributo method com o valor post . Isso indica que os dados deste formulário irão para o servidor como uma solicitação POST . O atributo action não é especificado, o que significa que a solicitação será enviada para o mesmo endereço de onde viemos para esta página ( /add ). Assim, ao receber uma requisição GET , nosso servlet vinculado a este endereço retorna o JSP com o formulário add-user. E se ele receber uma requisição POST , então sabemos que o formulário enviou seus dados para cá (que extraímos do objeto request nodoPost()método, processar e passar para o modelo para salvar). Vale a pena notar que os campos de entrada têm um parâmetro chamado nome (para nomes de usuário ou passe para senhas). Este é um ponto muito importante. Assim, para receber esses dados (o nome de usuário e a senha que serão inseridos) da requisição (dentro do servlet), usaremos esses campos nome e senha . Mas mais sobre isso mais tarde. Meu botão para envio de dados voltou a ser feito como um botão , não como um campo de saída como de costume. Não sei até que ponto essa abordagem é amplamente adotada, mas funciona para mim (navegador Chrome).

Manipulação de servlet de solicitações POST

Vamos retornar ao AddServlet . Relembro que para permitir que nosso servlet "pegue" as requisições GET , sobrescrevemos o doGet()método na classe HttpServlet . Para ensinar nosso servlet a também capturar solicitações POST , também devemos substituir o doPost()método. O Tomcat passa a ele objetos de solicitação e resposta semelhantes com os quais trabalharemos. Para começar, extraia o nome da solicitação e passe os parâmetros enviados pelo formulário (se você especificou nomes diferentes no formulário, use esses nomes). Depois disso, crie um objeto de usuário usando os dados recebidos. Em seguida, obtemos o objeto do modelo e adicionamos o usuário criado ao modelo.

@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);
}

Passando dados para a exibição

Vamos passar para o ListServlet . O doGet()método já está implementado. Ele simplesmente transfere o controle para a exibição ( list.jsp ). Se você ainda não tem isso, crie-o por analogia com o método no AddServlet . Agora seria bom pegar a lista de nomes de usuários do modelo e passá-los para a exibição, que os receberá e os exibirá lindamente. Para fazer isso, usaremos novamente o objeto request que recebemos do Tomcat . Podemos adicionar um atributo a este objeto, dando-lhe algum tipo de nome. Na verdade, podemos adicionar o objeto que queremos passar para a exibição. Devido ao fato de que, ao transferir o controle do servlet para a exibição, passamos à exibição os mesmos objetos de solicitação e resposta que o servlet recebeu, podemos adicionar nossa lista de nomes ao objeto de solicitação e, em seguida, obter nossa lista de nomes de usuário da solicitação objeto na exibição. Acabamos com a classe ListServlet , então vou apresentar o código de toda a classe aqui:

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<String> names = model.list();
        req.setAttribute("userNames", names);

        RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/list.jsp");
        requestDispatcher.forward(req, resp);
    }
}

Executando código Java em arquivos JSP

É hora de olhar para list.jsp . Ele só será executado quando o ListServlet transferir o controle para ele. Além disso, já preparamos a lista de nomes de usuários do modelo no servlet e passamos aqui no objeto request. Como temos a lista de nomes, podemos iterar sobre ela usando um forloop e exibir cada nome. Como eu disse antes, os arquivos JSP podem executar código Java (que é o que os torna diferentes das páginas HTML estáticas). Para executar algum código, tudo o que precisamos fazer é colocar a seguinte construção no local apropriado:

<!-- html code -->
<%
    // Java code
%>
<!-- html code -->
Dentro desta construção, temos acesso a várias variáveis:
  • request — nosso objeto request, que passamos do servlet, onde era chamado simplesmente de req ;
  • response — o objeto de resposta (chamado resp no servlet);
  • out — um objeto JspWriter (que herda um Writer comum ), que podemos usar para "escrever" algo diretamente na própria página HTML . A instrução out.println("Hello, World!") é muito semelhante a System.out.println("Hello, World!") , mas não as confunda!
  • out.println() "grava" em uma página HTML , enquanto System.out.println grava no fluxo de saída do sistema . Se você chamar System.out.println() em uma seção JSP com código Java , verá os resultados no console do Tomcat , mas não na página.
Você pode procurar outros objetos disponíveis em um JSP aqui . Podemos usar o objeto request para obter a lista de nomes passados ​​do servlet (anexamos o atributo correspondente a esse objeto) e podemos usar o objeto out para exibir esses nomes. Vamos exibi-los (por enquanto, como uma simples lista HTML):

<ul>
    <%
        List<String> names = (List<String>) request.getAttribute("userNames");

        if (names != null && !names.isEmpty()) {
            for (String s : names) {
                out.println("<li>" + s + "</li>");
            }
        }
    %>
</ul>
Se precisarmos exibir a lista apenas se houver usuários e, caso contrário, exibir um aviso de que ainda não há usuários, podemos reescrever um pouco esta seção:

<%
    List<String> names = (List<String>) request.getAttribute("userNames");

    if (names != null && !names.isEmpty()) {
        out.println("<ui>");
        for (String s : names) {
            out.println("<li>" + s + "</li>");
        }
        out.println("</ui>");
    } else out.println("<p>There are no users yet!</p>");
%>
Agora que sabemos como passar dados de servlets para visualizações, podemos melhorar nosso AddServlet para que ele exiba uma notificação sobre a adição bem-sucedida de um usuário. Para fazer isso, no doPost()método, após adicionar um novo usuário ao modelo, podemos adicionar esse nome de usuário aos atributos do objeto req e passar o controle de volta para uma view ( add.jsp ). E agora adicionaremos uma seção com código Java a ela, onde verificaremos se a solicitação possui tal atributo e, se tiver, exibiremos uma mensagem informando que o usuário foi adicionado com sucesso. Após essas alterações, o código completo do AddServlet ficará mais ou menos assim:

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);
    }
}
Aqui, ao final do doPost()método criamos um atributo com o nome do usuário que foi adicionado ao modelo, e então chamamos o doGet()método, para o qual passamos a requisição e resposta atual. O doGet()método agora transfere o controle para a view, que também recebe o objeto request com o nome do usuário adicionado anexado como atributo. O que nos resta fazer é corrigir add.jsp para que ele exiba a notificação caso não exista tal atributo. Aqui está a versão final do add.jsp :

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

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<p>User '" + request.getAttribute("userName") + "' added!</p>");
                }
            %>
            <div>
                <div>
                    <h2>Add user</h2>
                </div>

                <form method="post">
                    <label>Name:
                        <input type="text" name="name"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass"><br />
                    </label>
                    <button type="submit">Submit</button>
                </form>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
O corpo da página consiste no seguinte:
  • um div com um cabeçalho;
  • um contêiner div para conteúdo, que inclui uma verificação da existência de um atributo com um nome de usuário;
  • um div com o formulário add-user;
  • e na parte inferior, um rodapé com um botão para retornar à página inicial.
Isso pode parecer muitos divs, mas os usaremos mais tarde quando adicionarmos estilos. Aqui está a versão final de list.jsp :

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

    <body>
        <div>
            <h1>Super app!</h1>
        </div>

        <div>
            <div>
                <div>
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ui>");
                        for (String s : names) {
                            out.println("<li>" + s + "</li>");
                        }
                        out.println("</ui>");
                    } else out.println("<p>There are no users yet!</p>");
                %>
            </div>
        </div>

        <div>
            <button onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
Assim, temos um aplicativo da Web totalmente funcional que pode salvar e adicionar usuários e também exibir uma lista de seus nomes. Agora é só deixar bonito… :) Criando um aplicativo da web simples usando servlets e JSPs (parte 2) - 2

Adicionando estilos. Usaremos a estrutura W3.CSS

No momento, nosso aplicativo funciona, mas parece absolutamente ultrajante. Então, vamos adicionar um plano de fundo, colorir o texto e os botões, adicionar estilo às listas, alinhar elementos, adicionar recuos e assim por diante. Escrever estilos manualmente pode levar muito tempo e sobrecarregar nossos nervos. Então proponho usar o framework W3.CSS . Já possui classes prontas para uso com estilos. Só precisamos organizar as classes CSS que queremos usar nos lugares certos. Para adicioná-los às nossas páginas, primeiro conectamos o arquivo de estilo. Existem duas maneiras de fazer isso:
  1. percorra nossas páginas e insira o seguinte link direto para o arquivo de estilo na seção de cabeçalho

    <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">

    Esta opção é adequada se você tiver uma conexão permanente com a Internet. Quando você abrir suas páginas no servidor local, os estilos serão extraídos da Internet.

  2. Mas se você quiser ter todos os estilos localmente e não depender de uma conexão com a Internet, baixe o arquivo de estilo e coloque-o em algum lugar dentro da pasta web (por exemplo, web/estilos/w3.css ). Em seguida, percorra todas as nossas páginas ( index.html, add.jsp, list.jsp ) e adicione o seguinte link ao arquivo de estilo dentro da seção head :

    <link rel="stylesheet" href="styles/w3.css">

    Depois disso, basta percorrer as tags e adicionar os estilos que você gosta. Não vou me alongar sobre isso em detalhes. Em vez disso, fornecerei apenas versões prontas para uso de três dos meus arquivos com classes de estilo raster.

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Super app!</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center">
            <div class="w3-bar w3-padding-large w3-padding-24">
                <button class="w3-btn w3-hover-light-blue w3-round-large" onclick="location.href='/list'">List users</button>
                <button class="w3-btn w3-hover-green w3-round-large" onclick="location.href='/add'">Add user</button>
            </div>
        </div>
    </body>
</html>
adicionar.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Add new user</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-padding">
            <%
                if (request.getAttribute("userName") != null) {
                    out.println("<div class=\"w3-panel w3-green w3-display-container w3-card-4 w3-round\">\n" +
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-green w3-border w3-border-green w3-hover-border-grey\">×</span>\n" +
                            "   <h5>User '" + request.getAttribute("userName") + "' added!</h5>\n" +
                            "</div>");
                }
            %>
            <div class="w3-card-4">
                <div class="w3-container w3-center w3-green">
                    <h2>Add user</h2>
                </div>
                <form method="post" class="w3-selection w3-light-grey w3-padding">
                    <label>Name:
                        <input type="text" name="name" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <label>Password:
                        <input type="password" name="pass" class="w3-input w3-animate-input w3-border w3-round-large" style="width: 30%"><br />
                    </label>
                    <button type="submit" class="w3-btn w3-green w3-round-large w3-margin-bottom">Submit</button>
                </form>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
lista.jsp

<%@ page import="java.util.List" %>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Users list</title>
        <link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
    </head>

    <body class="w3-light-grey">
        <div class="w3-container w3-blue-grey w3-opacity w3-right-align">
            <h1>Super app!</h1>
        </div>

        <div class="w3-container w3-center w3-margin-bottom w3-padding">
            <div class="w3-card-4">
                <div class="w3-container w3-light-blue">
                    <h2>Users</h2>
                </div>
                <%
                    List<String> names = (List<String>) request.getAttribute("userNames");

                    if (names != null && !names.isEmpty()) {
                        out.println("<ul class=\"w3-ul\">");
                        for (String s : names) {
                            out.println("<li class=\"w3-hover-sand\">" + s + "</li>");
                        }
                        out.println("</ul>");

                    } else out.println("<div class=\"w3-panel w3-red w3-display-container w3-card-4 w3-round\">\n"
+
                            "   <span onclick=\"this.parentElement.style.display='none'\"\n" +
                            "   class=\"w3-button w3-margin-right w3-display-right w3-round-large w3-hover-red w3-border w3-border-red w3-hover-border-grey\">×</span>\n" +
                            "   <h5>There are no users yet!</h5>\n" +
                            "</div>");
                %>
            </div>
        </div>

        <div class="w3-container w3-grey w3-opacity w3-right-align w3-padding">
            <button class="w3-btn w3-round-large" onclick="location.href='/'">Back to main</button>
        </div>
    </body>
</html>
E é isso. :) Se você ainda tiver dúvidas ou comentários, ou se algo não funcionar, deixe um comentário. E vou anexar algumas capturas de tela de como tudo acabou.
Criando um aplicativo da web simples usando servlets e JSPs (parte 2) - 3
Criando um aplicativo da web simples usando servlets e JSPs (parte 2) - 4
Criando um aplicativo da web simples usando servlets e JSPs (parte 2) - 5
E, finalmente , se você quiser praticar com este projeto, tente o seguinte:
  • crie um servlet e JSP para excluir um usuário e adicione outro par para editar um usuário existente. O resultado será um aplicativo da web CRUD genuíno construído usando servlets. ;)
  • substitua a Lista por um banco de dados, para que os usuários adicionados não desapareçam após a reinicialização do servidor. :)
Boa sorte!
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION