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 1)

Publicado no grupo Random-PT
Conhecimento necessário para entender o artigo: Você já descobriu mais ou menos o Java Core e gostaria de ver 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 1) - 1
Este material é a continuação lógica do meu artigo Criando o projeto da Web mais simples no IntelliJ Idea Enterprise . Nesse artigo, demonstrei como criar um modelo de projeto da Web funcional. Desta vez, mostrarei como criar um aplicativo da Web simples, mas totalmente atraente, usando a API Java Servlet e a API JavaServer Pages . Nosso aplicativo terá uma página inicial com dois links:
  • um link para uma página para adicionar usuários;
  • um link para a lista de usuários.
Como antes, usarei IntelliJ Idea Enterprise Edition , Apache Maven (vamos apenas conectar algumas dependências) e Apache Tomcat . No final, vamos "embelezar" nosso aplicativo usando o framework W3.CSS . Vamos supor que você já tenha um projeto vazio ao qual adicionaremos agora. Se não, percorra o primeiro artigo e faça um. Levará apenas alguns minutos :)

Um pouco sobre a estrutura da nossa futura aplicação

Nossa página inicial (/) será uma página HTML estática comum com um cabeçalho e dois links/botões:
  • adicionar um novo usuário (navega para / adicionar );
  • visualizar a lista de usuários (navega para / list ).
O Tomcat vai pegar as requisições desses endereços e enviar para um dos dois servlets que vamos fazer (vamos especificar o mapeamento em web.xml ). Os servlets processarão as solicitações, prepararão os dados (ou salvarão os dados, se estivermos adicionando um usuário) e transferirão o controle para os arquivos JSP apropriados , que então "renderizarão" o resultado. Armazenaremos os dados em uma lista simples (List).

Crie uma página inicial estática

Se você index.jsp em sua pasta da web, exclua-o. Em vez disso, crie um arquivo HTML simples chamado index.html nesta pasta:

<!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>    <!-- button holder -->
            <button onclick="location.href='/list'">List users<//button>
            <button onclick="location.href='/add'">Add user<//button>
        </div>
    </div>
</body>
</html>
Não há nada complicado aqui. Na tag de título , indicamos o título da nossa página. No corpo da página, temos dois divs principais: header e content . O conteúdo div inclui um suporte para nossos botões. E aí temos dois botões que levam você ao endereço correspondente com um clique. Você pode executar o projeto e ver como ele se parece agora. Se você clicar nos botões, obterá páginas de erro 404, porque nós, as páginas correspondentes, ainda não existem. Mas podemos dizer que os botões funcionam. Observe que esta não é a abordagem mais universal: se o JavaScript estiver desativado no navegador, esses botões não funcionarão. Mas vamos supor que ninguém desabilita o JavaScript. :) Obviamente, você poderia se virar com links simples, mas eu prefiro botões. Você pode fazer como preferir. E não se preocupe com o fato de que meus exemplos terão muitos divs . Vamos preenchê-los com estilos mais tarde e tudo ficará mais bonito. :)

Crie arquivos JSP para renderizar o resultado

No mesmo diretório web , crie uma pasta onde adicionaremos nossos arquivos JSP . Eu chamei de ' views ', mas mais uma vez você pode improvisar. Nesta pasta, criaremos dois arquivos JSP:
  • add.jsp — uma página para adicionar usuários;
  • list.jsp — página para exibir a lista de usuários.
Atribua cabeçalhos de página apropriados a eles. Algo como " Adicionar novo usuário " e " Lista de usuários ", e deixaremos assim.

Criar dois servlets

Os servlets receberão e processarão as solicitações enviadas pelo Tomcat . Na pasta src/main/java , crie o pacote app , onde colocaremos nosso código fonte. Outros pacotes também irão para lá. Então, para evitar que esses pacotes sejam criados um dentro do outro, vamos criar alguma classe no pacote do app (deletaremos depois). Agora crie três pacotes diferentes no pacote do aplicativo :
  • entidades — nossas entidades (a classe que descreve os objetos do usuário) vão aqui;
  • model — é para onde vai o nosso modelo (falaremos sobre isso um pouco mais tarde);
  • servlets — e é aqui que nossos servlets vão.
Depois de fazer isso, você pode excluir com calma essa classe do pacote do aplicativo (se você a criou, é claro). No pacote servlets , crie duas classes:
  • AddServlet — processa solicitações enviadas para / add ;
  • ListServlet — processa solicitações enviadas para / list .

Conectando dependências no Maven

O Tomcat 9 .* implementa as especificações para Servlet 4.0 e JavaServer Pages 2.3 . É o que afirma a segunda linha do primeiro parágrafo da documentação oficial do Tomcat 9. Isso significa que, se você, como eu, usa esta versão do Tomcat , o código que você escreverá e executará usará essas versões. Mas gostaríamos de ter essas especificações em nosso projeto, para que nosso código, que as usa, pelo menos seja compilado com sucesso. E para fazer isso, precisamos carregá-los em nosso projeto. É aqui que Maven vem em socorro.

A regra geral é esta: se você precisar conectar algo ao seu projeto usando o Maven:

  • vá para o site do repositório do Maven;
  • localize a versão necessária da biblioteca necessária;
  • obtenha o código de dependência que precisa ser colado em seu pom.xml;
  • colar! :)
Vamos começar. Primeiro, prepare o arquivo POM . Em algum lugar após a entrada /version , mas antes de /project , insira o seguinte:

<dependencies>

</dependencies>
Fazemos isso para indicar que listaremos as dependências necessárias nessas tags. Agora vá para mvnrepository.com . Há um campo de pesquisa na parte superior. Para começar, procure por ' servlet '. O primeiro resultado, que já foi utilizado mais de sete mil vezes, nos convém. Lembre-se, precisamos da versão 4.0 (para Tomcat 9). Outras versões podem ser apropriadas para implementações mais antigas. Esta é uma versão bastante recente, então não há muitos usos. Mas nós precisamos disso. Uma página é aberta onde você pode obter o código dessa dependência para vários gerenciadores de pacotes ou simplesmente baixá-lo. Mas como queremos conectá-lo usando o Maven, selecionaremos o código na guia Maven. Copiamos e colamos na seção de dependência do nosso arquivo POM. Se você receber uma notificação perguntando se deseja habilitar a importação automática no canto inferior direito do IDEA , vá em frente e concorde com ela. Se você recusou acidentalmente, vá para " Configurações " e ative a importação automática manualmente: Configurações (Ctrl + Alt + S) -> Construção, Execução, Implantação -> Maven -> Importação .e os arquivos de configuração IDEA para este projeto em sincronia. Seguindo o mesmo princípio, vamos encontrar e conectar JavaServer Pages 2.3 (procure por "JSP"). E como já iniciamos o Maven, digamos apenas que nossos arquivos de origem seguem a sintaxe do Java 8 e que precisamos compilá-los em bytecode para essa versão. Após todos esses passos, nosso pom.xml ficará mais ou menos assim:

<?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>cc.codegym.info.fatfaggy</groupId>
    <artifactId>my-super-project</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compile.source>1.8</maven.compile.source>
        <maven.compile.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>

Transforme nossos servlets em servlets reais

No momento, o par de servlets que criamos são, na verdade, classes comuns. Eles não têm nenhuma funcionalidade. Mas agora conectamos a API do Servlet ao nosso projeto e, portanto, podemos usar suas classes. Para tornar nossos servlets "reais", tudo o que precisamos fazer é fazê-los herdar a classe HttpServlet .

Mapeamento ou marcação

Agora, seria bom dizer ao Tomcat que as solicitações para o endereço / add são processadas por nosso AddServlet e as solicitações para o endereço / list são tratadas pelo ListServlet . Esse processo é chamado de mapeamento (marcação). Isso é feito em web.xml usando o mesmo princípio:
  • para começar, descreva o servlet (forneça algum nome e especifique o caminho para a própria classe);
  • em seguida, vincule este servlet a um endereço específico (especifique o nome do servlet, que acabamos de fornecer, e especifique o endereço cujas solicitações devem ser enviadas para este servlet).
Descreva o servlet:

<servlet>
    <servlet-name>add</servlet-name>
    <servlet-class>app.servlets.AddServlet</servlet-class>
</servlet>
Agora vincule-o ao endereço:

<servlet-mapping>
    <servlet-name>add</servlet-name>
    <url-pattern>/add</url-pattern>
</servlet-mapping>
Como você pode ver, o nome do servlet é o mesmo em ambos os casos. Como resultado, o Tomcat sabe que se uma solicitação de /add for recebida, ela deverá ser enviada para app.servlets.AddServlet. Fazemos a mesma coisa com o segundo servlet. Ao final, nosso web.xml tem aproximadamente o seguinte conteúdo:

<?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>
A propósito, não criamos marcação para a página inicial (/). O fato é que não precisamos disso neste caso. Nossa página inicial é um arquivo HTML simples que exibe apenas dois botões. Ele não tem conteúdo dinâmico, então não precisamos criar um servlet separado para requisições de / que não fará nada além de encaminhar a execução para algum JSP (que também teria que ser criado) para desenhar dois botões para nós. Nós não precisamos disso. Uma página estática nos convém. Quando o Tomcat recebe uma solicitação, ele verifica se existe um único servlet que possa processar a solicitação para esse endereço e, em seguida, verifica se esse endereço já contém o arquivo HTML pronto, que servirá. Podemos executar nosso aplicativo novamente (reiniciar o servidor ou reimplementá-lo novamente - o que você preferir) e garantir que a página inicial seja renderizada, nada quebrado e as transições ocorram quando clicamos nos botões (embora novamente recebamos um erro). A propósito, enquanto antes obtínhamos um erro 404, agora obtemos um 405. Isso significa que o mapeamento funcionou e os servlets foram encontrados, mas eles não tinham um método adequado para lidar com a solicitação.

Breve digressão: o que acontece "sob o capô"?

Você provavelmente já pensou em como nosso aplicativo funciona no Tomcat. O que acontece lá dentro? E onde está o método main ()? Assim que você acessar localhost:8080 em seu navegador, o navegador enviará uma solicitação para esse endereço usando o protocolo HTTP. Espero que você já saiba que existem muitos tipos diferentes de requisições, e as mais populares são GET e POST. Cada solicitação deve ser respondida. Espera-se que uma solicitação GET receba uma resposta de código HTML pronto para uso, retornado ao navegador. O navegador então substitui o código por todas as letras, botões e formulários bonitos. Uma solicitação POST é um pouco mais interessante, pois também carrega algumas informações. Por exemplo, suponha que você insira credenciais em um formulário de registro ou login em um site e clique em "Enviar". Isso faz com que uma solicitação POST com suas informações pessoais seja enviada ao servidor. O servidor recebe essas informações, as processa e retorna alguma resposta (por exemplo, uma página HTML com seu perfil). A principal diferença entre eles é que as requisições GET são usadas apenas para recuperar dados do servidor, enquanto as requisições POST carregam algumas informações (e os dados no servidor podem mudar). Por exemplo, quando você envia sua foto para o servidor, ela é transportada para lá em uma solicitação POST e o servidor a adiciona ao banco de dados, ou seja, ocorre uma alteração. Agora, de volta ao Tomcat. Quando recebe uma requisição de um cliente, ele olha o endereço. Ele verifica se existe um servlet adequado para processar requisições para aquele endereço (ou um recurso disponível que pode ser retornado imediatamente). Se não encontrar algo para retornar, em seguida, ele responde com um erro 404 em vez de uma página HTML. Mas se ele encontrar um servlet adequado "sentado" naquele endereço, ele examinará o tipo de solicitação (GET, POST ou qualquer outro) e perguntará ao servlet se ele possui um método que possa lidar com esse tipo de consulta. Se o servlet disser que não sabe como lidar com esse tipo, entãoO Tomcat retorna um código 405. E foi exatamente isso que aconteceu em nosso projeto. Mas se um servlet adequado for encontrado e tiver um método adequado, o Tomcat criará um objeto servlet e o iniciará em um novo thread(que o permite rodar sozinho), e o Tomcat continua seu próprio trabalho, aceitando e enviando requisições. Além disso, o Tomcat cria mais dois objetos: um HttpServletRequest (que chamarei de "solicitação" para abreviar) e um HttpServletResponse (que chamarei de "resposta"). Ele coloca todos os dados recebidos da solicitação do cliente no primeiro objeto, para que todos os dados sejam extraídos dele. E depois de tudo isso, ele passa esses dois objetos para o método apropriado do servlet que foi iniciado em um thread separado. Assim que o servlet termina seu trabalho e tem uma resposta pronta para ser enviada ao cliente, ele acena uma bandeira para o Tomcat, dizendo "Terminei. Está tudo pronto". O Tomcat recebe a resposta e a envia ao cliente. Isso permite que o Tomcat receba solicitações e envie respostas, sem se distrair, e todo o trabalho é feito por servlets rodando em threads separados. Isso significa que, quando escrevemos o código do servlet, determinamos qual trabalho será executado. E você pode pensar no método main() como estando localizado dentro do próprio Tomcat (sim, ele é escrito em Java), e quando "lançamos" o Tomcat, o método main() é iniciado. Criando um aplicativo da web simples usando servlets e JSPs (parte 1) - 2

Use servlets para capturar métodos GET e enviar respostas super simples

No momento, nossos servlets não possuem métodos adequados (GET), então o Tomcat retorna um erro 405. Vamos criá-los! A classe HttpServlet, herdada por nossos servlets, declara vários métodos. Para atribuir um código específico aos métodos, simplesmente os sobrescrevemos. Nesse caso, precisamos substituir o doGet()método em ambos os servlets.

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

}
Como você pode ver, este método recebe dois argumentos: req (solicitação) e resp (resposta). Esses são os próprios objetos que o Tomcat cria e preenche para nós quando chama o método apropriado no servlet. Para começar, criaremos as respostas mais simples. Para fazer isso, pegaremos o objeto resp e obteremos dele um objeto PrintWriter. Este tipo de objeto é usado para compor uma resposta. Vamos usá-lo para gerar uma string simples.

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    PrintWriter writer = resp.getWriter();
    writer.println("GET method from AddServlet");
}
Faremos algo semelhante no ListServlet e, em seguida, reiniciaremos nosso servidor. Como você pode ver, tudo funciona! Ao clicar nos botões, você obtém páginas com o texto que "escrevemos" com o PrintWriter. Porém os arquivos JSP que preparamos para gerar páginas com respostas não estão sendo utilizados. Isso é simplesmente porque eles nunca são executados. Nosso servlet cria a própria resposta e finaliza a execução, sinalizando ao Tomcat que está pronto para responder ao cliente. O Tomcat apenas recebe a resposta e a envia de volta ao cliente. Vamos passar o controle dos servlets para os arquivos JSP. Vamos alterar o código dos nossos métodos da seguinte forma:
  • obtemos um objeto dispatcher de solicitação do objeto de solicitação e passamos a ele o endereço da página JSP para a qual queremos transferir o controle;
  • usamos este objeto para transferir o controle para a página JSP especificada, não esquecendo de passar os objetos request e response que recebemos do Tomcat.

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    RequestDispatcher requestDispatcher = req.getRequestDispatcher("views/add.jsp");
    requestDispatcher.forward(req, resp);
}
Na tag do corpo das páginas JSP, você pode adicionar algo para que possamos ver claramente qual página está sendo exibida. Depois de fazer isso, reinicie o servidor e verifique. Clicamos nos botões da página principal e as páginas abrem, o que significa que as requisições estão sendo enviadas para os servlets. Em seguida, o controle é passado para as páginas JSP, que agora estão sendo renderizadas. É tudo por agora. Na próxima parte deste artigo, trabalharemos na funcionalidade do nosso aplicativo.
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION