JavaRush /Blogue Java /Random-PT /Aplicação web em Java
Viacheslav
Nível 3

Aplicação web em Java

Publicado no grupo Random-PT
Aplicação Web em Java - 1

Introdução

Era uma vez, o Java fortaleceu sua posição ao escolher as aplicações web como prioridade. Desde seus primórdios, Java tem lutado para encontrar seu caminho. Primeiro, sugeri miniaplicativos. Isso proporcionou muitas oportunidades para os desenvolvedores criarem conteúdo dinâmico em páginas HTML estáticas. No entanto, os miniaplicativos não corresponderam às expectativas por vários motivos: segurança, sobrecarga e outros. Então os desenvolvedores da linguagem Java propuseram uma alternativa - API Servlet . E acabou sendo a decisão certa. A API Servlet é a especificação na qual qualquer aplicativo Web Java é construído, seja um aplicativo baseado na Web ou um serviço Web que retorna informações conforme solicitado. Portanto, o caminho para entender como funcionam as aplicações web Java começa com a compreensão da API Servlet.
Aplicação Web em Java - 2

API de servlet

Portanto, a API Servlet é o que os desenvolvedores da linguagem ofereceram aos desenvolvedores Java. A API Servlet é uma especificação que deve responder às nossas principais questões. Você pode encontrá-lo aqui: " JSR-000340 JavaTM Servlet 3.1 Versão Final para Avaliação ". O capítulo “ 1.1 O que é um Servlet? ” diz que um servlet é um componente web baseado na tecnologia Java que cria conteúdo dinâmico (ou seja, conteúdo). "Baseado em Java" significa que um servlet é uma classe Java compilada em bytecode . Os servlets são gerenciados por um contêiner de servlet, às vezes chamado de Servlet Engine. Um contêiner de servlet é uma extensão de servidor web que fornece funcionalidade de servlet. Por sua vez, os servlets proporcionam interação com o cliente no paradigma solicitação/resposta, que é implementado pelo contêiner do servlet. No capítulo " 1.2 O que é um contêiner de servlet? "é dito que um contêiner de servlet faz parte de um servidor web ou servidor de aplicativos que fornece serviços de rede através dos quais solicitações e respostas são enviadas, solicitações e respostas baseadas em MIME são geradas e processadas . Além disso, os contêineres de servlets gerenciam o ciclo de vida dos servlets (ou seja, decidem quando criá-los, excluí-los, etc.). Todos os contêineres de servlet devem suportar o protocolo HTTP para receber solicitações e enviar respostas. Gostaria de acrescentar aqui que MIME é um padrão, uma especificação que informa como as informações devem ser codificadas e as mensagens formatadas para que possam ser enviadas pela Internet.
Aplicação Web em Java - 3

Servidor web

Um servidor web é um servidor que aceita solicitações HTTP de clientes e fornece respostas HTTP (geralmente junto com uma página HTML, imagem, arquivo ou outros dados). Os recursos solicitados são identificados por URLs. Um dos servidores web mais populares com suporte à API Servlet é o Apache Tomcat . A maioria dos servidores web são máquinas complexas compostas de vários componentes, cada um dos quais desempenha funções específicas. Por exemplo:
Aplicação Web em Java - 4

Conectores

— Na entrada temos Conectores (ou seja, conectores) que aceitam solicitações recebidas de clientes. O conector HTTP no Tomcat é implementado usando o componente "Coyote". Os conectores recebem dados do cliente e os repassam ao Tomcat Engine. Servlet Container - Tomcat Engine, por sua vez, processa a solicitação recebida do cliente através do componente "Catalina", que é um contêiner de servlet. Consulte a documentação do Tomcat: " Visão Geral da Arquitetura " para obter mais detalhes. Existem outros servidores web que suportam a especificação da API Servlet. Por exemplo, " Jetty " ou " Ressaca ". Sua arquitetura é semelhante, portanto, entendendo o princípio de trabalhar com um contêiner de servlet, você pode passar a trabalhar com outro.
Aplicação Web em Java - 5

Aplicativo Web

Portanto, para executarmos uma aplicação web, precisamos de um servidor web que suporte a API Servlet (ou seja, um que tenha um componente de extensão que implemente o suporte da API Servlet para o servidor web). Multar. Afinal, o que é um aplicativo da web? De acordo com o capítulo “ 10 Aplicações Web ” da especificação da API Servlet, uma aplicação Web é uma coleção de servlets, páginas HTML, classes e outros recursos que compõem uma aplicação final em um servidor Web. De acordo com o capítulo " 10.6 Web Application Archive File ", uma aplicação web pode ser empacotada em Web ARchive (um arquivo com extensão WAR). Conforme declarado na página " Glossário-219 ":
Aplicação Web em Java - 6
Ou seja, é feito WAR em vez de JAR para mostrar que se trata de uma aplicação web. O próximo fato importante: devemos ter uma certa estrutura de diretórios em nosso arquivo WAR. Na especificação da API do Servlet no capítulo " 10.5 Estrutura de Diretórios ". Este capítulo diz que existe um diretório especial chamado "WEB-INF". Este diretório é especial porque não é visível para o cliente e não é mostrado diretamente a ele, mas é acessível ao código do servlet. Também diz o que o diretório WEB-INF pode conter:
Aplicação Web em Java - 7
De toda essa lista, não sabemos e não entendemos o item sobre algum arquivo web.xml chamado descritor de implantação . O que é? O capítulo " 14. Descritor de implantação " é dedicado ao descritor de implantação. Resumindo, um descritor de implantação é um arquivo xml que descreve como implantar (ou seja, executar) nosso aplicativo web em um servidor web. Por exemplo, o descritor de implantação indica quais URLs devem ser usados ​​para acessar nosso aplicativo, são indicadas configurações de segurança relacionadas ao nosso aplicativo, etc. O capítulo " 14.2 Regras para processamento da implantação " diz que o web.xml será validado pelo esquema antes de nossa aplicação ser configurada e lançada (ou seja, será feita uma verificação de que o conteúdo do web.xml está escrito corretamente de acordo com o esquema) . E no capítulo " 14.3 Deployment Descriptor " é indicado que o diagrama está aqui: http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd Se olharmos o conteúdo do arquivo, podemos ver:
Aplicação Web em Java - 8
Qual é o esquema usado para arquivos XML? Os esquemas indicam como preencher corretamente um documento XML: quais elementos podem ser usados, que tipo de dados podem ser especificados nos elementos, em que ordem os elementos devem ir, quais elementos são necessários, etc. Você pode comparar o esquema de um documento XML com uma interface em Java, porque o esquema em Java também especifica como as classes que satisfazem uma determinada interface (ou seja, que implementam uma determinada interface) devem ser escritas. Então, estamos munidos de conhecimento secreto e prontos para criar nossa primeira aplicação web!
Aplicação Web em Java - 9

Criando um aplicativo da Web

É difícil imaginar trabalhar com um aplicativo Java moderno sem usar sistemas automáticos de construção de projetos. Alguns dos sistemas mais populares são Maven e Gradle . Usaremos Gradle para esta revisão. A instalação do Gradle está descrita no site oficial . Para criar uma nova aplicação, precisamos de um plugin embutido no Gradle: “ Build Init Plugin ”. Para criar uma aplicação Java você precisa executar o seguinte comando: gradle init --type java-application
Aplicação Web em Java - 10
Após criar o projeto, precisaremos editar o arquivo build.gradle . Este é o chamado Build Script (para mais detalhes, veja a documentação do Gradle: " Writing Build Scripts "). Este arquivo descreve como montar o projeto e outros aspectos do trabalho com um projeto Java. O bloco plugins descreve quais " plugins Gradle " devem ser usados ​​para o projeto Gradle atual. Os plug-ins expandem as capacidades do nosso projeto. Por exemplo, o plugin padrão é “ java ”. Este plugin é sempre usado se precisarmos de suporte Java. Mas não precisamos do plugin “ aplicativo ”, porque... sua descrição afirma que ele é usado para criar um "aplicativo JVM executável", ou seja, executando aplicativos JVM. Precisamos criar um aplicativo Web na forma de um arquivo WAR. E se procurarmos a palavra WAR na documentação do Gradle, encontraremos “ War Plugin ”. Portanto, especificaremos os seguintes plugins:
plugins {
    id 'java'
    id 'war'
}
Também no " War Plugin Default Settings " é dito que o diretório com todo o conteúdo da aplicação web deve ser "src/main/webapp", deve haver o mesmo diretório WEB-INF no qual o web.xml deve estar localizado. Vamos criar esse arquivo. Vamos preencher um pouco mais tarde, porque... ainda não temos informações suficientes para isso. No bloco "dependências" indicamos as dependências do nosso projeto, ou seja, aquelas bibliotecas/frameworks sem as quais a nossa aplicação não pode funcionar. Neste caso, estamos escrevendo uma aplicação web, o que significa que não podemos trabalhar sem a API do Servlet:
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testCompile 'junit:junit:4.12'
}
provideCompile significa que a dependência não precisa ser incluída em nosso arquivo WAR da aplicação web: ela é necessária apenas para compilação. E quando executada, essa dependência será fornecida por outra pessoa (ou seja, o servidor web). Bem, deixamos no script de construção informações sobre qual repositório de dependências queremos usar - todas as dependências especificadas serão baixadas dele:
repositories {
    jcenter()
}
Removemos todo o resto do arquivo de script de construção. Agora vamos editar a classe src\main\java\App.java. Vamos fazer um servlet disso. A especificação da API do Servlet no capítulo " CAPÍTULO 2. A Interface do Servlet " afirma que a Interface do Servlet possui uma implementação básica de HttpServlet , que deve ser suficiente na maioria dos casos e os desenvolvedores só precisam herdar dela. E no capítulo " 2.1.1 Métodos de tratamento de solicitações específicas HTTP " são indicados os principais métodos que processam solicitações recebidas. Assim, vamos reescrever a classe App.java:
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.IOException;

public class App extends HttpServlet {
    public String getGreeting() {
        return "Hello world.";
    }

    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 		// https://www.oracle.com/technetwork/java/servlet-142430.html
 		PrintWriter out = resp.getWriter();
 		out.println(this.getGreeting());
 		out.close();
 	}
}
Então, parece que temos tudo pronto. Resta apenas escrever o descritor de implantação corretamente. No diagrama, copie o seguinte texto em web.xml:
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="..."
      version="3.1">
      ...
</web-app>
E também o caminho para o esquema indicado nele: http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd Agora vamos ver um exemplo de como o web.xml deve ser na especificação da API do Servlet. Este exemplo é dado no capítulo " 14.5.1 Um Exemplo Básico ". Vamos combinar o que está indicado no diagrama com o exemplo indicado na especificação. Obtemos o seguinte:
<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">
      <display-name>A Simple Web Application</display-name>
      <servlet>
		<servlet-name>app</servlet-name>
		<servlet-class>App</servlet-class>
	  </servlet>
	  <servlet-mapping>
		<servlet-name>app</servlet-name>
		<url-pattern>/app</url-pattern>
	  </servlet-mapping>
</web-app>
Como você pode ver, usamos o esquema e o esquemaLocation especificados anteriormente. E a descrição dos próprios elementos foi retirada do exemplo do Capítulo 14.5.1. Se fizermos tudo corretamente, executaremos a tarefa gradle war sem erros:
Aplicação Web em Java - 11
Aplicação Web em Java - 12

Iniciando um aplicativo da web

Como um aplicativo da web é iniciado? Vamos lidar primeiro com a opção mais complexa. Dissemos anteriormente que existe um servidor web Apache Tomcat que suporta a API Servlet. Isso significa que podemos implantar nosso arquivo de guerra coletado (eles também dizem “implantar”) neste servidor. Na página " Baixar Tomcat ", baixe da seção "Distribuições Binárias" o tipo de entrega "Core" em formato zip. E descompacte o arquivo baixado em algum diretório, por exemplo, em C:\apache-tomcat-9.0.14. Antes de iniciar o servidor, vamos abrir o arquivo para edição conf\tomcat-users.xmle adicionar a seguinte linha nele: <user username="tomcat" password="tomcat" roles="tomcat,manager-gui,admin-gui"/> Agora, na linha de comando, vá até o diretório bin e execute catalina.bat start. Por padrão, o console do servidor estará disponível em http://localhost:8080/manager. O login e a senha são os mesmos que especificamos em tomcat-users.xml. O Tomcat possui um diretório "webapps", que contém aplicativos da web. Se quisermos implantar o nosso próprio, devemos copiar nosso arquivo de guerra para lá. Quando executamos anteriormente o comando gradle war, \build\libs\um arquivo war foi criado no diretório. É isso que precisamos copiar. Após copiar, atualize a página http://localhost:8080/managere veja:
Aplicação Web em Java - 13
Depois de concluído http://localhost:8080/javaweb/app, passaremos ao nosso servlet, porque Anteriormente “mapeamos” (ou seja, mapeamos) a solicitação /app para o servlet App. Existe uma maneira mais rápida de verificar como o aplicativo funciona. E o sistema de montagem nos ajuda novamente nisso. No script de construção do nosso projeto Gradle, podemos adicionar um novo plugin " Gretty " à seção de plugins: id "org.gretty" version "2.3.1" E agora podemos realizar uma tarefa Gradle para executar nossa aplicação:gradle appRun
Aplicação Web em Java - 14
Consulte " Adicionar o plugin Gretty e executar o aplicativo " para obter detalhes.
Aplicação Web em Java - 15

API Spring e Servlet

Servlets são a base de tudo. E mesmo o agora popular Spring Framework nada mais é do que um complemento da API Servlet. Para começar, o Spring Framework é uma nova dependência para o nosso projeto. Portanto, vamos adicioná-lo ao script de construção no bloco de dependências: compile 'org.springframework:spring-webmvc:5.1.3.RELEASE' Na documentação do Spring Framework há um capítulo " 1.1. DispatcherServlet ". Diz que o Spring Framework é construído em um padrão "front controller" - isto é, quando existe um servlet central chamado " DispatcherServlet ". Todas as solicitações chegam a esse servlet e ele delega chamadas aos componentes necessários. Veja, mesmo aqui existem servlets. Você precisa adicionar um ouvinte ao descritor de implantação:
<listener>
	&ltlistener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Este é um ouvinte de eventos de contexto de servlet. Ou seja, quando o Contexto Servlet é iniciado, o contexto Spring (WebApplicationContext) também é iniciado. O que é contexto de servlet? Está descrito na especificação da API Servle no capítulo " CAPÍTULO 4. Contexto do Servlet ". Um contexto de servlet é uma "visão" do servlet da aplicação web na qual os servlets estão sendo executados. Cada aplicação web possui seu próprio contexto de servlet. Em seguida, para habilitar o Spring Framework, você precisa especificar context-param - o parâmetro de inicialização para o contexto do servlet.
<context-param>
	<param-name>contextConfigLocation</param-name>
	<param-value>/WEB-INF/app-context.xml</param-value>
</context-param>
E a definição do DispatcherServlet completa a configuração :
<servlet>
	<servlet-name>app</servlet-name>
	<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	<init-param>
		<param-name>contextConfigLocation</param-name>
 		<param-value></param-value>
	</init-param>
	<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
	<servlet-name>app</servlet-name>
	<url-pattern>/</url-pattern>
</servlet-mapping>
E agora só precisamos preencher o arquivo especificado em contextConfigLocation. Como fazer isso está descrito na documentação do Spring Framework no capítulo "1.3.1. Declaração":
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">

    <context:component-scan base-package="ru.javarush.javaweb"/>
    <mvc:annotation-driven/>
</beans>
É importante aqui não apenas indicar qual pacote verificar, mas também que queremos que seja orientado a anotações, ou seja, controlar as anotações sobre como o Spring funcionará. Resta apenas criar o pacote ru.javarush.javaweb e colocar a classe do controlador Spring nele:
package ru.javarush.javaweb;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class SpringController {

    @GetMapping("/app")
    @ResponseBody
    public String getGreeting() {
        return "Hello world.";
    }
}
Agora executando gradle appRun e indo para o endereço, http://127.0.0.1:8080/javaweb/appobteremos o mesmo Hello World. Como você pode ver, o Spring Framework está intimamente ligado à API do Servlet e a utiliza para trabalhar sobre ela.
Aplicação Web em Java - 16

Anotações

Como vimos, as anotações são convenientes. E não fomos os únicos que pensamos assim. Portanto, na especificação da API do Servlet, a partir da versão 3.0, apareceu o capítulo “ CAPÍTULO 8 Anotações e capacidade de conexão ”, que especifica que os contêineres de servlet devem suportar a capacidade de especificar o que foi especificado anteriormente no Deployment Descriptor por meio de anotações. Assim, web.xml pode ser completamente removido do projeto, e acima da classe servlet você pode especificar a anotação @WebServlet e indicar para qual caminho mapear o servlet. Tudo parece claro aqui. Mas e se conectássemos o Spring ao projeto, o que requer configurações mais complexas? Aqui tudo é um pouco mais complicado. Primeiro, a documentação do Spring diz que para configurar o Spring sem web.xml, você precisa usar sua própria classe que implementará o WebApplicationInitializer. Para mais detalhes veja o capítulo " 1.1. DispatcherServlet ". Acontece que esta é uma aula Spring. Como então a API Servlet é usada aqui? Na verdade, o ServletContainerInitializer foi adicionado à API Servlet 3.0 . Usando um mecanismo especial em Java (chamado SPI ), o Spring especifica seu inicializador de contêiner de servlet chamado SpringServletContainerInitializer. Por sua vez, ele já procura implementações do WebApplicationInitializer e chama os métodos necessários e realiza as configurações necessárias. Consulte " Como o contêiner do servlet localiza implementações do WebApplicationInitializer " para obter mais detalhes. As configurações acima podem ser feitas assim:
package ru.javarush.javaweb.config;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

public class AppInitializer implements WebApplicationInitializer {
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        // регистрируем конфигурацию созданую высше
        ctx.register(AppConfig.class);
        // добавляем в контекст слушателя с нашей конфигурацией
        servletContext.addListener(new ContextLoaderListener(ctx));

        ctx.setServletContext(servletContext);

        // настраиваем маппинг Dispatcher Servlet-а
        ServletRegistration.Dynamic servlet =
                servletContext.addServlet("dispatcher", new DispatcherServlet(ctx));
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
    }
}
Agora, usando a " configuração baseada em Java ", indicaremos qual pacote verificar + habilitar anotações:
package ru.javarush.javaweb.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "ru.javarush.javaweb.controllers")
public class AppConfig {
}
E o próprio SpringController foi movido para ru.javarush.javaweb.controllers, para que durante a varredura a configuração não se encontrasse, mas apenas procurasse controladores.
Aplicação Web em Java - 17

Resumindo

Espero que esta visão geral tenha esclarecido como os aplicativos da web funcionam em Java. Isso é apenas a ponta do iceberg, mas sem entender o básico fica difícil entender como funcionam as tecnologias baseadas nesse alicerce. A API Servlet é a parte central de qualquer aplicação web Java, e vimos como outras estruturas se encaixam nela. Para continuar, você pode visualizar os seguintes materiais: #Viacheslav
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION