Logo Passei Direto
Buscar

Camada de Controle com Spring

Ferramentas de estudo

Material
páginas com resultados encontrados.
páginas com resultados encontrados.
left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

left-side-bubbles-backgroundright-side-bubbles-background

Crie sua conta grátis para liberar esse material. 🤩

Já tem uma conta?

Ao continuar, você aceita os Termos de Uso e Política de Privacidade

Prévia do material em texto

Camada de controle - serviços
Utilização do framework Spring para criação de aplicativos Java, segundo a arquitetura MVC, tanto no modelo
Web tradicional como estruturado em Web Services do tipo REST, focando nas camadas de controle e
serviço, incluindo os elementos de segurança do Spring Security.
Prof. Denis Cople
1. Itens iniciais
Propósito
O aluno deverá estar apto a criar sistemas Web e Web Services REST com grande produtividade, obedecendo ao
padrão arquitetural MVC, através do framework Spring, além de lidar com elementos de autenticação e
autorização, via Spring Security. Com base no conhecimento adquirido, o aluno será capaz de implementar
controladores e serviços, alinhados às melhores técnicas adotadas pelo mercado, incluindo os requisitos de
segurança necessários.
Preparação
Antes de iniciar este conteúdo, acesse os arquivos dos projetos desenvolvidos (https://stecine.azureedge.net/
repositorio/00212ti/03592/docs/projetos.zip). É necessário também configurar o ambiente, com a instalação do
JDK e IDE NetBeans completa, em versão com suporte a projetos Maven, além de adicionar o servidor Tomcat EE
na instalação da IDE. Lembre-se: de modo geral, o mundo da computação é colaborativo.
É comum, quando encontramos erros nas bibliotecas utilizadas, copiarmos o log de erro e procurarmos em
qualquer motor de busca. Provavelmente, alguma resposta será retornada em algum fórum de discussão, como
StackOverflow, Github, Reddit, entre outros. Não só isso é uma prática comum na comunidade de
desenvolvimento de software e computação, como também nos possibilita aprender cada vez mais.
Objetivos
Empregar o Spring Web na construção da camada de controle para sistemas MVC.
Aplicar o Spring Boot para a construção da camada de serviços no modelo REST.
Implantar o Spring Security no controle de acesso para sistemas Web e Web 
Services.
Introdução
Vamos abordar os elementos essenciais para a construção de aplicativos comerciais robustos, de forma ágil,
com base no framework Spring. Nosso foco inicial será na definição de controladores e rotas, com base no
Spring Web, além da adoção de repositórios Spring Data, que diminuem muito o esforço de programação
necessário para a persistência. Ao longo do conteúdo, teremos a definição de serviços, com base no Spring
Boot, segundo o modelo REST, com utilização de dados no formato JSON.
Após a definição das camadas de controle e de serviços, utilizaremos o módulo Spring Security para adicionar
requisitos de segurança, cumprindo com as ações de autenticação e autorização, através de diferentes modelos
para controle de acesso, incluindo OAuth 2.0, onde o usuário é autenticado a partir de empresas conhecidas,
como Google e Facebook.
• 
• 
• 
https://stecine.azureedge.net/repositorio/00212ti/03592/docs/projetos.zip
https://stecine.azureedge.net/repositorio/00212ti/03592/docs/projetos.zip
https://stecine.azureedge.net/repositorio/00212ti/03592/docs/projetos.zip
https://stecine.azureedge.net/repositorio/00212ti/03592/docs/projetos.zip
1. Implementação da camada de controle com Spring Web
Arquitetura MVC utilizando Spring
Framework Spring
Responsável por permitir a construção da camada de controle em uma arquitetura MVC (Model, View e
Controller) para a Web, sendo uma ferramenta de código aberto para a plataforma Java.
No Spring, temos a inversão de controle, no qual parte do fluxo de execução não é definido no código, mas
efetuado a partir de um container no servidor. Ao utilizar essa abordagem, ocorre uma minimização do
acoplamento no sistema, além de diminuir muito o esforço de programação necessário.
O núcleo de execução do container é organizado em módulos, vejamos:
Data Access / Integration
Com gerenciamento de transações, acesso a banco de dados, mapeamento objeto-relacional e
conexão com mensagerias.
Web
Para a construção de Servlets e Portlets, entre outros, dentro de uma arquitetura MVC.
Core Container
Consiste no coração do framework, no qual temos classes estruturais, suporte à injeção de
dependências, comunicação com os componentes e a sintaxe para configurações gerais.
AOP / Instrumentação
Possui ferramentas para o carregamento de classes, suporte ao AspectJ e programação orientada a
aspectos.
Test
Para a implementação de testes unitários via JUnit ou TestNG.
Quando trabalhamos com Spring, devemos criar nossas classes com as anotações necessárias, e efetuar as
configurações gerais em um arquivo XML (Extended Markup Language). 
Atenção
Com utilização de um arquivo XML de configuração, temos acesso a diferentes serviços de
middleware, sem que o código-fonte do sistema precise de modificações. 
A arquitetura geral do núcleo de execução pode ser observada a seguir.
Módulos do framework Spring.
Arquitetura MVC
A utilização do Spring promove a divisão de responsabilidades dentro do padrão MVC. De forma resumida, o 
spring-data fornece os recursos necessários para a camada de persistência. Sempre temos controladores
anotados, e as interfaces, em modo texto ou Web, sempre acessam os controladores para enviar e receber
dados, o que está em pleno acordo com as regras da arquitetura.
View
Componentes e responsabilidades:
Os componentes são as telas e
interfaces do sistema.
Fornece as informações obtidas a
partir do controle.
Envia as solicitações do usuário
ao controle.
Controller
Componentes e responsabilidades:
 
São os componentes que definem
o comportamento do sistema.
Mapeia as opções para consultas
e alterações.
Define as regras de negócio do
sistema.
Model
Componentes e responsabilidades:
São os elementos voltados para a
persistência de dados.
Encapsula o estado geral do
sistema.
Trabalha com padrão DAO e
mapeamento objeto-relacional.
Iniciamos com a criação da entidade, que, no caso, será a classe Produto, posicionada no pacote unesa.model.
• 
• 
• 
• 
• 
• 
• 
• 
• 
java
 
A entidade JPA, definida pela anotação Entity, grava os dados na tabela de mesmo nome, conforme especificado
na anotação Table. No corpo da classe, temos apenas um POJO (Plain Old Java Object), com um conjunto de
atributos, alguns construtores, getters e setters, além da chave Id.
Deverá existir a tabela Produto no banco de dados e, aqui, utilizaremos o Derby, ou Java DB, de fácil utilização no
ambiente do NetBeans.
@Entity
@Table(name = "PRODUTO")
public class Produto implements Serializable {
 @Id
 private String codigo;
 private String nome;
 private Integer quantidade;
 public Produto() { }
 public Produto(String codigo) { this.codigo = codigo; }
 public Produto(String codigo, String nome, Integer quantidade) {
 this.codigo = codigo;
 this.nome = nome;
 this.quantidade = quantidade;
 }
 
 public String getCodigo() { return codigo; }
 public void setCodigo(String codigo) { this.codigo = codigo; }
 public String getNome() { return nome; }
 public void setNome(String nome) { this.nome = nome; }
 public Integer getQuantidade() { return quantidade; }
 public void setQuantidade(Integer quantidade) {
 this.quantidade = quantidade;
 }
 @Override
 public int hashCode() {
 return codigo != null ? codigo.hashCode() : 0;
 }
 @Override
 public boolean equals(Object object) {
 return object != null && 
 object instanceof Produto &&
 this.codigo.equals(((Produto)object).getCodigo());
 }
}
Captura de tela da Criação da tabela Produto no NetBeans.
Com o mapeamento objeto-relacional definido através da entidade JPA, criaremos a classe ProdutoDAO, no
pacote unesa.dao, com os métodos necessários para consulta e inserção.
java
 
A anotação Component coloca a classe no contexto de execução do Spring. Temos a anotação 
PersistenceContext, do JPA, aplicada a um gerenciador de entidades, do tipo EntityManager, onde a conexão
com o banco de dados será configurada ao nível dos arquivos XML.
O método persist irá adicionar os dados da entidade como um registro do banco de dados; findAll efetuará a
consulta e retornará uma coleção com todaspacote unesa.security, para definição do cliente Retrofit com inserção de 
credenciais. 
 com.squareup.okhttp3
 okhttp
 4.9.3
public class InterceptadorLogin implements Interceptor {
 private String token;
 public InterceptadorLogin(String token) { this.token = token; }
 @Override
 public Response intercept(Chain chain) throws IOException {
 Request original = chain.request();
 Request.Builder builder = original.newBuilder()
 .header("Authorization", token);
 Request request = builder.build();
 return chain.proceed(request);
 }
}
java
 
Existe muita semelhança com o código do cliente REST sem autenticação, mas agora utilizamos um cliente do 
tipo OkHttpClient na instância do Retrofit. Para configurar nosso cliente HTTP, primeiro obtemos o token a partir 
do usuário e senha fornecidos, o que é feito pela classe Credentials, depois instanciamos um objeto do tipo Inter
ceptadorLogin com a passagem do token, e finalmente anexamos o interceptador ao cliente HTTP através de ad
dInterceptor.
 A classe principal ClienteREST precisa de uma leve modificação para uso do novo gerenciador, sendo o trecho 
modificado apresentado a seguir. 
java
 
Podemos executar nosso cliente REST, obtendo os mesmos resultados da versão original, mas agora com 
autenticação efetuada via token, através do protocolo HTTP.
public class GestorServico {
 private final OkHttpClient.Builder httpClient = 
 new OkHttpClient.Builder();
 
 private final Retrofit retrofit;
 public GestorServico(String user, String password) {
 String token = Credentials.basic(user, password);
 InterceptadorLogin interceptador = 
 new InterceptadorLogin(token);
 httpClient.addInterceptor(interceptador);
 retrofit = new Retrofit.Builder()
 .baseUrl("http://localhost:8080")
 .client(httpClient.build())
 .addConverterFactory(JacksonConverterFactory.create())
 .build();
 }
 
 public ProdutoService createService(){
 return retrofit.create(ProdutoService.class);
 }
}
public static void main(String[] args) throws Exception {
 ProdutoService service = 
 new GestorServico("usu1", "1234").createService();
 Produto p1 = new Produto();
 // Todo o restante do método permanece inalterado
Autenticação com OAuth 2.0
OAuth 2.0
Hoje é comum aceitar a autenticação por terceiros, como Google e Facebook, empresas em que o usuário já 
confia, ocorrendo a solicitação da senha apenas no primeiro acesso. O protocolo por trás desse tipo de 
comportamento é chamado de OAuth 2.0, relacionado à autenticação, com envio de dados do usuário de forma 
padronizada, segundo o padrão OIDC (Open Id Connect).
 Os papéis definidos no OAuth 2.0 são: cliente, acessado no navegador; autenticador, onde temos exemplos 
como Google e Twitter; e o sistema em si. O login é solicitado no navegador, as credenciais são enviadas para o 
autenticador, que envia um token de acesso para o cliente e para o sistema, e finalmente o cliente utiliza o token 
para acessar o sistema, onde é feita a comparação com a versão recebida do autenticador.
 
 
 
Saiba mais
 
Um Bearer Token é um texto codificado, adotado pelo OAuth 2,0, que não tem significado para os 
clientes. Alguns servidores emitirão tokens como uma sequência de caracteres hexadecimais, 
enquanto outros podem usar tokens estruturados, como JSON Web Tokens.
 
 
Exemplo MeuTesteOAuth
Para exemplificar o uso de OAuth 2.0 no Spring Security, vamos criar um projeto padrão, do tipo Maven, com o 
nome MeuTesteOAuth, e alterar o arquivo pom.xml para a construção de um aplicativo Spring Boot, de acordo 
com a listagem apresentada a seguir.
python
 4.0.0
 
 org.springframework.boot
 spring-boot-starter-parent
 2.6.3
 
 
 unesa
 MeuTesteOAuth
 1.0-SNAPSHOT
 jar
 
 
 org.springframework.boot
 spring-boot-starter-oauth2-client
 
 
 org.springframework.security
 spring-security-oauth2-jose
 
 
 org.springframework.boot
 spring-boot-starter-security
 
 
 org.springframework.boot
 spring-boot-starter-web
 
 
 
 org.apache.tomcat.embed
 tomcat-embed-jasper
 
 
 javax.servlet
 jstl
 
 
 
 
 
 org.springframework.boot
 spring-boot-maven-plugin
 
 
 
 
 
 UTF-8
 15
As duas primeiras dependências são relacionadas ao cliente com autenticação OAuth 2.0, e na sequência temos 
as dependências para o Spring Boot e Spring Web, para dar suporte à criação do aplicativo Web. As duas últimas 
dependências servem para a interpretação de páginas JSP, com base no jasper, e suporte à sintaxe JSTL.
 
 
 
Comentário
 
Após salvar o arquivo, lembre-se de recarregar as configurações com o clique do botão direito sobre 
o projeto e escolha de Reload POM. Se necessário, faça uma compilação limpa do projeto, para que 
as novas bibliotecas sejam carregadas.
 
 
Vamos precisar de credenciais OAuth 2.0 para cada entidade autenticadora que formos utilizar, como o Google, 
no endereço https://console.developers.google.com/apis/credentials, onde será necessário configurar um 
projeto no Google Cloud. Com o projeto selecionado, devemos clicar em CRIAR CREDENCIAIS, escolhendo a 
opção Id do cliente OAuth, o que irá redirecionar para a criação da página de consentimento OAuth, caso ela 
ainda não esteja configurada. Serão solicitadas informações acerca do aplicativo, segundo uma sequência de 
telas, de forma geral irrelevantes, à exceção da escolha do tipo de usuário, que deverá ser externo, habilitando o 
acesso para qualquer pessoa com uma conta Google quando publicado.
Nem todos os campos são obrigatórios, e após o preenchimento, teremos um aplicativo, mas não as credenciais 
ainda. Devemos voltar para o painel de credenciais e clicar novamente em CRIAR CREDENCIAIS, com a opção Id 
do cliente OAuth, onde agora devemos escolher o tipo de aplicativo como Aplicativo da Web, adotando o nome 
de nosso projeto (MeuTesteOAuth).
 
 
 
Atenção
 
Caso você já tenha um aplicativo cadastrado no console do Google, teremos apenas a segunda 
parte do procedimento sendo efetuada.
 
 
Após a escolha do tipo de aplicativo e especificação do nome, o clique no botão CRIAR fará com que sejam 
gerados o Id do Cliente e a Chave Secreta, exibidos na tela a seguir, permitindo a cópia. 
Cadastro de cliente OAuth 2.0.
Ainda em relação ao AAuth criado, é importante observar que:
 
 
 
Comentário
 
Pode ser necessário voltar para a configuração da tela de consentimento, ocorrida na primeira parte, 
e adicionar usuários de teste, para liberar a chave antes da publicação.
 
 
Vamos precisar adicionar dois diretórios ao projeto, a partir de src/main, onde o primeiro será resources e o 
segundo webapp. Para cria-los, utilizamos o clique com o botão direito sobre o projeto e escolhemos a opção Ne
w, seguido de Folder, abrindo a tela seguinte. 
Criação do diretório resources.
Ao final, teremos uma seguinte estrutura de diretórios.
Estrutura de diretórios do projeto.
Iremos adicionar, na raiz de resources, o arquivo application.properties, com as configurações gerais do Spring 
Boot.
java
 
As duas primeiras configurações estão relacionadas ao Servlet dispatcher do Spring Web, com o relacionamento 
entre as rotas e os arquivos JSP. Segundo as informações apresentadas, será utilizado o sufixo jsp e as páginas 
serão colocadas no diretório jsps de webapp.
Nas demais configurações efetuadas, estamos definindo o cliente-id e o secret-id para efetuar a autenticação 
via Google e Facebook. É nesse ponto que devemos colocar os valores obtidos anteriormente pelo console do 
autenticador,ou seja, o Id do Cliente e a Chave Secreta.
Com o ambiente preparado, vamos começar a codificar, com a criação da classe SecurityConfig, no pacote unes
a.security.
# View Resolver
spring.mvc.view.prefix=/jsps/
spring.mvc.view.suffix=.jsp
# Clientes OAuth
spring.security.oauth2.client.registration.google.client 
id=368238083842-3d4gc7p54rs6bponn0qhn4nmf6apf24a.apps.googleusercontent.c
om
spring.security.oauth2.client.registration.google.client secret=2RM2QkEaf3A8-
iCNqSfdG8wP
spring.security.oauth2.client.registration.facebook.client id=151640435578187
spring.security.oauth2.client.registration.facebook.client 
secret=3724fb293d401245b1ce7b2d70e97571
java
 
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
 @Override
 protected void configure(HttpSecurity http) throws Exception {
 http.authorizeRequests()
 .antMatchers("/oauth_login", "/loginFailure", "/", "/index")
 .permitAll()
 .anyRequest().authenticated()
 .and()
 .logout().clearAuthentication(true).deleteCookies()
 .invalidateHttpSession(true)
 .and()
 .oauth2Login().loginPage("/oauth_login")
 .authorizationEndpoint().baseUri("/oauth2/authorize-client")
 .authorizationRequestRepository(
 authorizationRequestRepository())
 .and()
 .tokenEndpoint()
 .accessTokenResponseClient(accessTokenResponseClient())
 .and()
 .defaultSuccessUrl("/loginSuccess")
 .failureUrl("/loginFailure");
 http.csrf().disable();
 }
 @Bean
 public AuthorizationRequestRepository 
 authorizationRequestRepository() {
 return new HttpSessionOAuth2AuthorizationRequestRepository();
 }
 @Bean
 public OAuth2AccessTokenResponseClient 
 accessTokenResponseClient() {
 DefaultAuthorizationCodeTokenResponseClient 
 accessTokenResponseClient = new 
 DefaultAuthorizationCodeTokenResponseClient();
 return accessTokenResponseClient;
 }
}
Definindo um cliente OAuth 2.0
Cliente OAuth 2.0
Definir um cliente OAuth 2.0 é uma tarefa razoavelmente complexa, como podemos ver em nossa configuração 
de segurança. Liberamos o acesso a algumas rotas, com permitAll, e exigimos autenticação nos demais 
endereços, o que é definido com authenticated, mas começamos a ver diferenças a partir desse ponto.
 Concatenamos a configuração do logout, eliminando a autenticação corrente, deletando todos os cookies e 
invalidando a sessão.
 
 
 
Essa configuração específica é necessária para eliminar todos os tokens utilizados pelo OAuth 2.0 no 
cliente, causando a efetiva desconexão do usuário.
 
No terceiro segmento, utilizamos oauth2Login para definir o modelo de autenticação utilizado, com a 
especificação da página de login e o endpoint para efetivar a conexão do usuário. Temos ainda a configuração 
do repositório de requisições de autenticação, com base em um bean que utiliza um objeto do tipo HttpSessionO
Auth2AuthorizationRequestRepository.
 Definimos o gerenciamento de tokens, através de tokenEndpoint, com a definição da resposta via objeto do tipo 
DefaultAuthorizationCodeTokenResponseClient. Através desse trecho é fixada a política de conversação 
controlada por Bearer Tokens.
 Temos ainda a definição das páginas de login bem-sucedido (loginSuccess) e de falha no login (loginFailure), no 
formato JSP. Temos ainda uma configuração adicional, em um bloco separado, para desabilitar a proteção CSRF, 
facilitando o logout.
 Podemos criar a classe LoginController, no pacote unesa.security, com o conteúdo apresentado a seguir. Esse 
controlador será responsável pelas rotas relacionadas ao processo de login.
java
 
@Controller
public class LoginController {
 private static final String baseUri = "oauth2/authorize-client";
 @Autowired
 private ClientRegistrationRepository clientRegistrationRepository;
 @Autowired
 private OAuth2AuthorizedClientService authorizedClientService;
 @GetMapping("/oauth_login")
 public String getLoginPage(Model model) {
 Map oauth2Urls = new HashMap();
 Iterable registrations = 
 (Iterable)
 clientRegistrationRepository;
 registrations.forEach(registration -> 
 oauth2Urls.put(registration.getClientName(),
 baseUri+"/"+registration.getRegistrationId()));
 model.addAttribute("urls", oauth2Urls);
 return "oauth_login";
 }
 @GetMapping("/loginSuccess")
 public String getLoginInfo(Model model, 
 OAuth2AuthenticationToken authentication) {
 OAuth2AuthorizedClient client = 
 authorizedClientService.loadAuthorizedClient(
 authentication.getAuthorizedClientRegistrationId(), 
 authentication.getName());
 String userInfoEndpointUri = client.getClientRegistration()
 .getProviderDetails().getUserInfoEndpoint().getUri();
 RestTemplate restTemplate = new RestTemplate();
 HttpHeaders headers = new HttpHeaders();
 headers.add(HttpHeaders.AUTHORIZATION, 
 "Bearer " + client.getAccessToken().getTokenValue());
 HttpEntity entity = new HttpEntity("", headers);
 ResponseEntity response = restTemplate.exchange(
 userInfoEndpointUri, HttpMethod.GET, entity, Map.class);
 Map userAttributes = response.getBody();
 model.addAttribute("name", userAttributes.get("name"));
 return "loginSuccess";
 }
 
 @GetMapping("loginFailure")
 public String loginFailure() { return "loginFailure"; }
}
Inicialmente, definimos o endereço de base para efetuar a autenticação via OAuth 2.0, além do acesso a dois 
beans, onde o primeiro nos dará acesso aos autenticadores que foram definidos no arquivo de propriedades, e o 
segundo fornecerá os serviços para um usuário logado.
 Na rota oauth_login, via método GET, temos a obtenção dos autenticadores a partir do bean, com a conversão 
de tipo para um Iterable, e alimentamos um HashMap onde a chave é o nome do autenticador e o valor é 
preenchido com o endereço de autenticação. Por padrão, formamos esse endereço anexando o id do 
autenticador ao endereço de base.
 No final do primeiro método, o HashMap é associado ao atributo urls, no modelo, e o nome da página JSP de 
destino é retornado. Fica claro que devemos criar o arquivo oauth_login.jsp, que ficará no diretório jsps, a partir 
de webapp. 
 
 
 
Atenção
 
Ocasionalmente, o NetBeans mapeia o diretório webapp para uma visualização padrão, em uma 
divisão com o nome Web Pages. O processo ocorre de forma automática.
 
 
A página servirá para oferecer ao usuário as opções de login por terceiros disponíveis no sistema, e utilizará uma 
biblioteca do Bootstrap para melhorar o aspecto visual.
 O conteúdo do arquivo oauth_login.jsp pode ser observado na listagem seguinte. 
python
 
Observe como o atributo urls é utilizado, em uma expressão forEach, para oferecer os links de autenticação para 
o Google e o Facebook, onde o campo value contém o endereço e o campo key traz o nome do autenticador. O 
resultado pode ser observado a seguir, onde o usuário precisa clicar no autenticador preferido para logar no 
sistema.
 
 
 
 
Logar com:
 
 
 
 
 
 
 
 
 ${url.key} (${url.value})
$%7Burl.value%7D
$%7Burl.value%7D
$%7Burl.value%7D
$%7Burl.value%7D
Tela de autenticação via OAuth 2.0.
Continuando nossa análise de LoginController, temos a rota loginSuccess, onde são obtidos os dados do usuário 
a partir do autenticador, segundo o padrão OIDC. O endereço para o serviço de dados, que ficará na variável use
rInfoEndpointUri, será fornecido pelo cliente autenticado.
 O serviço de dados é um serviçoREST, levando à adoção de um objeto do tipo RestTemplate, com a passagem 
do Bearer Token, obtido através do cliente, no cabeçalho da requisição, e conteúdo vazio. A partir de uma 
chamada exchange, com comportamento síncrono, via método GET do HTTP, acessamos o endereço contido 
em userInfoEndpointUri, e recuperamos os dados no corpo da resposta (body), na forma de um mapa (Map) com 
pares chave-valor.
 Em seguida, o nome do usuário é recuperado do mapa, sendo associado ao atributo name no modelo de dados, 
sendo retornado o nome da página de destino (loginSuccess). Devemos criar a página loginSuccess.jsp, no 
diretório jsps, com o conteúdo apresentado a seguir. 
python
 
A página inclui elementos de formatação do Bootstrap e a apresentação das boas-vindas, com o nome fornecido 
pelo controlador. A página resultante pode ser observada a seguir, mas será apresentada apenas quando não 
existir uma página de destino, ou seja, após uma ação de logout e reapresentação da tela de login.
Tela de login bem-sucedido.
A última rota controlada por LoginController será loginFailure, sem informações adicionais, e com o simples 
direcionamento para a página JSP. Criamos a página loginFailure.jsp, em jsps, com o conteúdo a seguir.
 
 
 Bem-vindo ${name}
 
 
 
python
 
A nova página é muito semelhante a loginSuccess.jsp, com o mesmo aspecto visual, inclusive, mas utiliza uma fra
se fixa, indicando a falha no login.
Todos os recursos necessários para o processo de autenticação estão concluídos, e agora criaremos a classe Ge
neralController, no pacote unesa.controller, responsável pelas rotas do sistema em si. Veja o código da nova 
classe a seguir.
java
 
Temos apenas as rotas index e protegido, ambas retornando o nome da página JSP de destino, e uma rota para 
a raiz do sistema, apontando para o mesmo local de index. Não há controles específicos para as páginas, pois 
não estamos lidando com dados cadastrais no exemplo.
 Vamos criar a página index.jsp, no diretório jsps, com a listagem seguinte.
 
 
 Falha de Login
 
 
 
@Controller
public class GeneralController {
 @RequestMapping("/")
 public String raiz() { return "index"; }
 @RequestMapping("/index")
 public String index() { return "index"; }
 @GetMapping("protegido")
 public String protegido() { return "protegido"; }
}
python
 
Ao executar o sistema, a página index será apresentada, oferecendo um link para a página protegida, que 
direcionará para a tela de autenticação quando o usuário não estiver logado, ou abrirá a página normalmente 
com o usuário logado, além de um link para efetuar o logout.
A tela inicial do sistema, representada por index, pode ser observada a seguir.
 
 
 
Página Inicial
 
 
 
 
 
 
 Página Protegida
 (/protegido)
 Logout
 (/logout)
/protegido
/protegido
/protegido
/protegido
/protegido
/logout
/logout
/logout
/logout
/logout
Tela inicial do sistema com OAuth 2.0.
Também precisamos criar a página protegido.jsp, no diretório jsps, de acordo com o código a seguir. Devido às 
configurações de segurança, só poderá ser acessada por um usuário já autenticado no sistema.
python
 
Uma página simples, contendo um título, uma pequena mensagem, e um link para a tela inicial do sistema, como 
pode ser observada a seguir.
 
 
 
Página Protegida
 
Se está vendo isso é porque está logado
 
 
 
 
 
 Página Inicial (/index)
/index
/index
/index
/index
Tela protegida através de OAuth 2.0.
Como passo final, definiremos a classe principal, com o nome MeuTesteOAuthApp, contendo o código a seguir. 
A localização da nova classe não terá impactos sobre a compilação, mas é sugerido o pacote unesa.meutesteoau
th.
java
 
Agora, vamos selecionar nossa classe principal, clicando com o botão direito sobre o projeto e escolhendo a 
opção Properties. Em seguida, navegamos até a opção run, clicamos em Browse e selecionamos unesa.meuteste
oauth.MeuTesteOAuthApp.
@SpringBootApplication
@ComponentScan(basePackages = "unesa")
public class MeuTesteOAuthApp {
 public static void main(String[] args) {
 SpringApplication.run(MeuTesteOAuthApp.class, args);
 }
}
Seleção da classe principal no projeto com autenticação OAuth 2.0.
Só falta executar o projeto, abrir o navegador no endereço http://localhost:8080, e utilizar as funcionalidades 
relacionadas à autenticação via OAuth 2.0.
Autenticação com OAuth 2.0
Confira agora os princípios da autenticação com OAuth 2.0, demonstrando sua utilização pelo framework Spring.
 
 
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para assistir ao vídeo.
 
 
 
 
Vem que eu te explico!
Arquitetura do Spring Security.
Os vídeos a seguir abordam os assuntos mais relevantes do conteúdo que você acabou de estudar.
 
 
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para assistir ao vídeo.
 
 
 
 
Modelo de Segurança do REST.
 
 
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para assistir ao vídeo.
 
 
 
 
Verificando o aprendizado
Questão 1
Criptografia é um ferramental essencial para o sigilo de dados, mas como temos utilizações diferenciadas para 
cada tipo de informação, os processos criptográficos disponíveis adotam diferentes estratégias de 
funcionamento. Por exemplo, o algoritmo 3DES caracteriza-se por ser um processo reversível, onde a mesma 
chave, normalmente denominada Secret Key, é utilizada para criptografar e para recuperar os dados originais, 
segundo um processo conhecido como:
 
A
 
Criptografia assimétrica
 
 
B
 
Codificação simples
 
 
C
 
Assinatura digital
 
 
D
 
Criptografia simétrica
 
 
E
 
Criptografia destrutiva
 
A alternativa D está correta.
A criptografia simétrica é aquela na qual utilizamos a mesma chave para criptografar e para recuperar os 
dados. Quando trabalhamos com criptografia assimétrica, temos a chave pública, utilizada para 
criptografar e verificar assinaturas, e a chave privada, para recuperar os dados e assinar um pacote 
(assinatura digital). Já a codificação simples não envolve chaves, mas apenas um processo reversível, 
enquanto a criptografia destrutiva não permite a recuperação dos dados.
Questão 2
Ao definirmos um Web Service do tipo REST, oferecemos diversas funcionalidades, a partir de endereços e 
métodos HTTP específicos, mas nem todos os endereços devem ser disponibilizados para o público em geral. 
Em um primeiro nível de segurança, podemos solicitar a autenticação do usuário, mas mesmo os usuários do 
sistema podem ter restrições de acesso para algumas das funcionalidades, o que nos faz trabalhar com 
processos de autorização., onde a forma mais comum é o uso de perfis de utilização. Qual método de 
HttpSecurity permite definir o acesso ao endereço apenas para determinados perfis?
 
A
 
hasRole
 
 
B
 
authorizeRequests
 
 
C
 
permitAll
 
 
D
 
rolesE
 
authenticated
 
A alternativa A está correta.
Através do método hasHole, temos a exigência de um perfil específico para o acesso a determinados 
endereços, enquanto permitAll define o acesso livre para os endereços. Toda a cadeia é iniciada com 
authorizeRequests, onde authenticated é aplicado a endereços que devem ser acessados com 
autenticação, sendo comum o uso de anyRequest, para que inicialmente todos os endereços exijam 
autenticação. Já o método roles não pertence a HttpSecurity, e sim a UserDetails, definindo o conjunto de 
perfis utilizados por determinado usuário.
 
 
4. Conclusão
 
 
Considerações finais
No atual mercado de desenvolvimento, o tempo de resposta, em termos de implementação, é primordial, algo 
que pode ser observado nas metodologias ágeis, como Scrum e XP, e a utilização de ferramentas de 
produtividade, como o framework Spring, se tornou essencial para cumprir os prazos extremamente curtos, mas 
ainda assim garantindo a qualidade necessária.
Com base no Spring, a construção de um sistema Web na arquitetura MVC acaba se tornando uma tarefa 
extremamente simples, onde o uso de anotações para definição de controladores e rotas, bem como para a 
captura de dados da requisição, se traduz no aumento de produtividade ao definir a camada de controle do 
sistema. Aliado à estrutura do sistema, temos ainda recursos como o Spring Data, onde o mapeamento objeto-
relacional se reduz à definição de interfaces.
Não menos importante, a comunicação com dispositivos móveis, no modelo B2C, padronizou o uso de Web 
Services do tipo REST, e o mesmo modelo da camada de controle do Spring pode ser utilizado agora para criar 
uma camada de serviço, com dados no formato JSON.
Finalmente, tanto na utilização de controladores, em um sistema Web, quanto na definição de uma camada de 
serviços REST, devemos poder restringir o acesso a alguns recursos, e o Spring Security fornece todo o 
ferramental necessário para ações de autenticação e autorização.
 
 
Podcast
 
Ouça agora um resumo dos recursos do framework Spring, devendo ser abordados os módulos 
Spring Web, Spring Data e Spring Security, bem como sua utilização para a definição de controles e 
serviços, incluindo elementos de autenticação e autorização.
 
 
 
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para ouvir o áudio.
 
 
 
 
 
 
Explore +
Confira agora as indicações que separamos especialmente para você!
Verifique a documentação Spring Tutorial, oferecida pela Editora Baeldung, com uma excelente trilha de 
aprendizagem para o framework Spring.
Verifique a documentação Spring Tutorial – Spring Core Framework Tutorials, oferecida pelo Journal Dev, com 
ótimas referências e exemplos acerca do Spring.
Pesquise o guia Building a RESTful Web Service, na documentação oficial do Spring, com todos os passos 
necessários para a criação de Web Services RESTful com Spring.
Pesquise o guia Spring Boot and OAuth2, na documentação oficial do Spring, com os passos necessários para 
utilização de OAuth 2.0 em sistemas com Spring Boot.
Pesquise o guia Spring Security na documentação oficial do Spring, descrevendo a estrutura que permite 
fornecer autenticação e autorização para aplicativos Java.
Referências
BOAGLIO, F. SPRING BOOT. 1. ed. São Paulo: Casa do Código, 2017.
 BURKE, B.; MONSON, R. ENTERPRISE JAVA BEANS 3.0. 5. ed. São Paulo: Pearson, 2007.
 COSMINA, I.; HARROP, R.; SCHAEFER, C.; HO, C. PRO SPRING. 5. ed. USA: Apress, 2017.
 DEITEL, H.; DEITEL, P. JAVA, como programar. 10. ed. São Paulo: Pearson, 2016.
 JOHNSON, R. et al. Spring Framework Reference Documentation. 4.0.0.RC2. Consultado na internet em: 30 mar. 
2022.
 PATEL, N. SPRING 5.0 PROJECTS. 1. ed. Reino Unido: Packt Publishing, 2019.
 SPILCA, L. SPRING SECURITY IN ACTION. 1. ed. USA: Manning, 2020.
 TURNQUIST, G. LEARNING SPRING BOOT 2.0. 2. ed. Reino Unido: Packt Publishing, 2017.
 VARANASI, B.; BELIDA, S. SPRING REST. 1. ed. USA: Apress, 2021.
 WALLS, C. SPRING IN ACTION. 5. ed. USA: Manning, 2018.
 ZOCHIO, M. Introdução à criptografia. 1. ed. São Paulo: Novatec, 2016. 
 
 
	Camada de controle - serviços
	1. Itens iniciais
	Propósito
	Preparação
	Objetivos
	Introdução
	1. Implementação da camada de controle com Spring Web
	Arquitetura MVC utilizando Spring
	Framework Spring
	Data Access / Integration
	Web
	Core Container
	AOP / Instrumentação
	Test
	Atenção
	Arquitetura MVC
	View
	Controller
	Model
	Spring Framework 5.2.9
	EclipseLink (JPA 2.1)
	Driver do Java DB
	Implementação da camada de controle
	Controladores e rotas
	Spring-webmvc
	Spring-webflux
	Spring-websocket
	Escolher projeto
	Nome e local de salvamento
	Tipo de servidor
	Frameworks
	Configuração do framework
	Camada de Visualização
	Novo Produto
	Lista de Produtos Cadastrados
	Configurações gerais e execução
	Arquitetura MVC com Spring
	Conteúdo interativo
	Vem que eu te explico!
	Framework Spring
	Conteúdo interativo
	Arquitetura MVC
	Conteúdo interativo
	Verificando o aprendizado
	2. Implementação da camada de serviço
	Conceitos
	Interoperabilidade
	Saiba mais
	Web Services
	SOAP
	REST
	Saiba mais
	Sintaxe XML e JSON
	Padrão XML
	Padrão JSON
	Exemplo
	Web Service REST
	Arquitetura REST
	Consulta de dados
	Inclusão de dados
	Alteração de dados
	Remoção de dados
	Spring Boot
	Projeto ServicoSpring02
	Configuração
	Escolher projeto
	Nome e local de salvamento
	Spring Data JPA
	Spring Web
	Apache Derby Database
	Camada de Serviços REST
	Método save
	Método deleteById
	Método findById e findAll
	Comentário
	Conexão com o banco de dados
	REST com Retrofit
	Retrofit
	Projeto ClienteRest
	Escolher projeto
	Nome e local de salvamento
	Web Service RESTful com Spring
	Conteúdo interativo
	Vem que eu te explico!
	Web Services
	Conteúdo interativo
	Arquitetura REST
	Conteúdo interativo
	Retrofit
	Conteúdo interativo
	Verificando o aprendizado
	3. Implementação da camada de segurança com Spring Security
	Camada de segurança
	Autenticação e autorização
	Codificação e Criptografia
	Criptografia simétrica
	Criptografia assimétrica
	Relacionado à funcionalidade ou serviço
	Relacionado aos dados de domínio
	Sistemas Web com Spring Security
	Arquitetura do Spring Security
	Saiba mais
	Primeiro passo
	Segundo passo
	Terceiro passo
	Saiba mais
	Exemplo com Spring Web
	Spring-security-web
	Spring-security-config
	Spring-security-core
	Lista de Produtos Cadastrados
	Produtos
	Segurança no REST
	Modelo de Segurança do REST
	Criptografia com REST
	Solicitações HTTP do Retrofit
	Autenticação com OAuth 2.0
	OAuth 2.0
	Saiba mais
	Exemplo MeuTesteOAuth
	Comentário
	Atenção
	Comentário
	Definindo um cliente OAuth 2.0
	Cliente OAuth 2.0
	Atenção
	Logar com:
	Bem-vindo ${name}
	Falha de Login
	Página Inicial
	Página Protegida
	Autenticação com OAuth 2.0
	Conteúdo interativo
	Vem que eu te explico!
	Arquitetura do Spring Security.
	Conteúdo interativo
	Modelo de Segurança do REST.
	Conteúdo interativo
	Verificando o aprendizado
	4. Conclusão
	Considerações finais
	Podcast
	Conteúdo interativo
	Explore +
	Referênciasas entidades que já foram armazenadas anteriormente.
A classe de serviço que utilizará ProdutoDAO, com as transações controladas pelo container, receberá o nome 
GerenciadorProduto, compondo o pacote unesa.controller.
@Component
public class ProdutoDAO {
 @PersistenceContext
 private EntityManager em;
 public void persist(Produto produto) {
em.persist(produto);
 }
 public List findAll() {
 return em.createQuery("SELECT p FROM Produto p")
 .getResultList();
 }
}
java
 
A anotação Autowired efetua a configuração e utilização automática de ProdutoDAO através do Spring, enquanto
Transictional coloca o método em uma transação gerenciada pelo container. O método add será utilizado para
acrescentar um produto na base, e findAll utilizará o DAO para recuperar a coleção de entidades, mas, como o
segundo método não envolve modificação de valores, a transação pode ser definida como somente leitura.
O arquivo de configuração será posicionado na raiz do projeto com o nome spring.xml, envolvendo os
componentes relevantes do projeto.
@Component
public class GerenciadorProduto {
 @Autowired
 private ProdutoDAO produtoDAO;
 
 @Transactional
 public void add(Produto produto){
 produtoDAO.persist(produto);
 }
 
 @Transactional(readOnly = true)
 public List findAll(){
 return produtoDAO.findAll(); 
 }
}
python
 
Após incluir todos os namespaces necessários, temos as configurações, onde a mais simples foi a do contexto,
com a definição do pacote a partir do qual os beans serão pesquisados, que no caso é unesa, permitindo o
reconhecimento de GerenciadorProduto e ProdutoDAO no contexto do Spring.
A configuração da conexão com o banco de dados tem como base a classe DriverManagerDataSource, onde as
propriedades necessárias são o driver do Derby, a URL de conexão, usuário e senha. A conexão é utilizada na
definição de uma fábrica de gerenciadores de entidades, do tipo LocalContainerEntityManagerFatoryBean,
fazendo a ponte com driver JPA através da classe EclipseLinkJpaVendorAdapter.
As configurações para controle transacional que, por trabalhar com o JPA, serão baseadas na classe 
JpaTransactionManager, que encapsulará a fábrica de gerenciadores de entidades configurada anteriormente.
Agora, precisamos adicionar as bibliotecas 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Spring Framework 5.2.9 EclipseLink (JPA 2.1)
Driver do Java DB
No ambiente do NetBeans, basta clicar com o botão direito na pasta Libraries, escolher a opção Add Libray, e
selecionar cada biblioteca.
Finalmente, a criação de uma classe principal para o projeto, utilizando todos os artefatos gerados nos passos
anteriores. 
java
 
O contexto do Spring é recuperado, a partir do arquivo XML de configuração, na variável ctx, o que nos permite
obter os beans criados com a anotação Component. Note que ao instanciar o GerenciadorProduto, temos a
adição automática do ProdutoDAO, por causa da utilização de Autowired, o que garante que as operações sobre
o banco de dados sejam efetuadas.
Na sequência, vemos algumas operações de inclusão e consulta ao banco de dados, através do gerenciador,
finalizando com o encerramento do contexto através do método close. Como resultado da execução, teremos o
acompanhamento das instruções SQL geradas, bem como a listagem com o nome de cada produto que foi
incluído na base de dados.
Implementação da camada de controle
Controladores e rotas
Para a construção de sistemas Web modernos, é comum a adoção de controladores e rotas, onde os primeiros
definem as ações que serão executadas, e as últimas definem os endereços que levarão ao acionamento das
ações.
public class ExemploSpring001 {
 public static void main(String[] args) {
 ClassPathXmlApplicationContext ctx = 
 new ClassPathXmlApplicationContext("classpath:/spring.xml");
 GerenciadorProduto gerenciador = 
 ctx.getBean(GerenciadorProduto.class);
 gerenciador.add(new Produto("A001","Caneta", 100));
 gerenciador.add(new Produto("A002","Lapis", 230));
 for(Produto p: gerenciador.findAll())
 System.out.println(p.getNome());
 ctx.close();
 }
}
A base para a construção de aplicativos Web no spring é o pacote spring-web, onde temos a infraestrutura
necessária para tratar as requisições e lidar com o mapeamento de rotas. Para cada perfil de utilização na Web,
temos um pacote especializado, como:
Spring-webmvc
Com suporte à arquitetura MVC.
Spring-webflux
Usado com arquitetura de fluxo.
Spring-websocket
Voltada para jogos, streaming e outras
comunicações binárias.
Vamos iniciar com a criação de um aplicativo Web, adotando o servidor Tomcat. Adicione o framework Spring, ao
final, sendo aqui utilizada a versão 4.3.29, em conjunto com JEE 7.
Escolher projeto
Nome e local de salvamento
Tipo de servidor
Frameworks
Configuração do framework
Copie os pacotes unesa.model e unesa.dao, criados no primeiro projeto. A classe DAO deve ser alterada para
acrescentar o método de remoção e as anotações para o controle transacional, sempre lembrando que a
biblioteca EclipseLink (JPA 2.1) deve ser adicionada ao projeto.
java
 
Como passo seguinte, vamos criar a classe ProdutoController, no diretório unesa.controller.
@Component
public class ProdutoDAO {
 @PersistenceContext
 private EntityManager em;
 
 @Transactional
 public void persist(Produto produto) { em.persist(produto); }
 @Transactional
 public void remove(String codigo) {
 em.remove(em.find(unesa.model.Produto.class, codigo));
 }
 
 public List findAll() {
 return em.createQuery("SELECT p FROM Produto p").
 getResultList();
 }
}
java
 
Esse controlador inclui as transações RequestMapping, para definir nossas rotas, 
EnableTransactionManagement, que habilitará o gerenciamento de transações, e RequestParam, que mapeia os
parâmetros da requisição.
Como temos uma rota definida ao nível da classe, todos os mapeamentos aplicados aos métodos serão
complementares à rota inicial, ou seja, para acessar o método listaProdutos, será utilizado o endereço http://
localhost:8080/NomeApp/produtos/listaProdutos. A mesma regra deve ser aplicada aos demais métodos da
@Controller
@RequestMapping("/produtos")
@EnableTransactionManagement
public class ProdutoController {
 @Autowired
 ProdutoDAO dao;
 
 @RequestMapping(value = "/dadosProduto", 
 method = RequestMethod.GET)
 public ModelAndView dadosProduto() {
 return new ModelAndView("dadosProduto", "command",
 new Produto());
 }
 
 @RequestMapping(value = "/addProduto", 
 method = RequestMethod.POST)
 public String adicionarProduto(
 @ModelAttribute Produto dadosProduto, ModelMap model) {
 dao.persist(dadosProduto);
 model.addAttribute("produtos", dao.findAll());
 return "listaProdutos";
 }
 @RequestMapping(value = "/removeProduto", 
 method = RequestMethod.GET)
 public String delProduto(
 @RequestParam(name="codigo") String codigoProduto, 
 ModelMap model) {
 dao.remove(codigoProduto);
 model.addAttribute("produtos", dao.findAll());
 return "listaProdutos";
 }
 
 @RequestMapping(value = "/listaProdutos", 
 method = RequestMethod.GET)
 public String listaProdutos( ModelMap model ) {
 model.addAttribute("produtos", dao.findAll());
 return "listaProdutos";
 }
}
classe, sempre indicando a rota e o método HTTP utilizado. Neste caso, estamos adotando apenas GET ou 
POST.
A classe ModelAndView é responsável pelo relacionamento entre dados e componentes para visualização na
biblioteca spring-webmvc. Na utilização direta, através do construtor, temos a página JSP de destino, o nome do
atributo e o valor associado, conforme utilizado no método dadosProduto, enquanto nos demais métodos temosum parâmetro ModelMap, que permite adicionar atributos diversos, e o nome da página JSP é retornado.
Camada de Visualização
Na forma padrão de utilização do Spring, o fluxo de execução é direcionado pelo controlador para páginas JSP,
onde os dados serão tratados da forma adequada para a concepção da interface de usuário.
Vamos criar a página JSP com o nome dadosProduto, no subdiretório jsp, a partir de WEB-INF.
python
 
 
 
 
Novo Produto
 
 Codigo:
 
 Nome:
 
 
 Quantidade:
 
 
 
 
 
O uso da taglib está relacionado à biblioteca de formulários do Spring, onde os atributos definidos no 
ModelAndView permitirão o preenchimento automático dos campos a partir do atributo path, que indica o campo
da entidade relacionado. Para cada campo temos uma etiqueta (label) e uma caixa de entrada (input), enquanto 
form define o destino como a rota addProduto, interceptada no controlador, utilizando o método POST do HTTP.
Analisando o fluxo de execução, temos a chamada da rota dadosProduto, que o controlador irá direcionar para a
página JSP, e após o preenchimento dos dados pelo usuário e envio, com o clique no botão, ocorrerá a chamada
para a rota addProduto. Em seguida, os dados enviados são capturados em dadosProduto, do tipo Produto, com
o uso da anotação ModelAttribute, sendo efetuada a inclusão no banco através do DAO, além da adição do
atributo produtos e definição da página de destino como listaProdutos.
Vamos à criação da página JSP com o nome listaProdutos, no mesmo diretório da primeira. 
python
 
Nessa página, temos a utilização da sintaxe JSTL padrão para a captura dos dados que foram enviados pelo
controlador. O comando forEach permite percorrer toda a coleção do atributo items, que deve ser produtos,
como no controlador, atribuindo à variável prod e gerando as linhas da tabela com os dados obtidos dos campos
de cada entidade englobada, sempre através de JSTL, como em ${prod.nome}.
A chamada para a rota removeProduto ocorre a partir dos links gerados dinamicamente na segunda página. No
fluxo de execução, o controlador irá interceptar a chamada, obtendo o código, enviado como parâmetro, com
base na anotação RequestParam, seguido da remoção a partir do DAO, preenchimento do atributo produtos e
retorno da página de listagem.
Neste ponto, é possível observar claramente a funcionalidade do módulo Spring Web, com a definição de uma
arquitetura MVC de forma automática para o sistema, onde temos o JPA sendo utilizado na camada Model,
incluindo as entidades anotadas e classes DAO, a camada Controller baseada nos controladores do Spring, os
quais são acionados a partir das rotas mapeadas nas anotações, e um conjunto de páginas JSP implementando a
camada View. 
 
 
Lista de Produtos Cadastrados
 
 
 
Codigo Nome Quantidade 
$
{prod.codigo}
$
{prod.nome}
$
{prod.quantidade}
X (removeProduto?codigo=$
{prod.codigo})
 
 Novo Produto (dadosProduto)
 
removeProduto?codigo=$%7Bprod.codigo%7D
removeProduto?codigo=$%7Bprod.codigo%7D
removeProduto?codigo=$%7Bprod.codigo%7D
removeProduto?codigo=$%7Bprod.codigo%7D
dadosProduto
dadosProduto
Configurações gerais e execução
Os arquivos de configuração do sistema são posicionados no diretório WEB-INF. Com relação ao dispatcher-
servlet.xml, não serão necessárias alterações, pois ele apenas define as resoluções de endereço comuns, mas
iremos acrescentar um arquivo com o nome app-servlet.xml, com os redirecionamentos para nosso controlador,
conforme a seguir.
python
 
Aqui são configurados os redirecionamentos utilizados pelos controladores dos pacotes que podem ser
alcançados a partir do pacote unesa (base-package). Cada retorno dos métodos do controlador chama a página
a partir do diretório WEB-INF/jsp, com o acréscimo do sufixo jsp.
O arquivo applicationContext.xml será bastante modificado, pois precisará definir a conexão com o banco de
dados e sistema de transações utilizado.
 
 
 /WEB-INF/jsp/
 .jsp
 
python
 
A configuração apresentada define a conexão com o banco de dados, no bean dataSource, uma fábrica de
gestores de persistência, denominada entityManagerFactory, além do controle das transações, através do bean 
txManager. Com base nos elementos definidos, o framework será capaz de prover persistência com controle
transacional de forma automatizada, a partir das anotações e injeção de código.
As configurações finais são efetuadas no arquivo web.xml, responsável por organizar o conjunto de
componentes do aplicativo. 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
python
 
 
 appServlet
 
 org.springframework.web.servlet.DispatcherServlet
 
 
 contextConfigLocation
 /WEB-INF/app-servlet.xml
 
 1
 
 
 appServlet
 /
 
 
 contextConfigLocation
 /WEB-INF/applicationContext.xml
 
 
 
 org.springframework.web.context.ContextLoaderListener
 
 
 
 dispatcher
 
 org.springframework.web.servlet.DispatcherServlet
 
 2
 
 
 dispatcher
 *.htm
 
 
 30 
 
 
 redirect.jsp
 
As configurações efetuadas incluem a localização do arquivo de contexto, o applicationContext.xml, e a definição
de um servlet que funciona como controlador frontal para o Spring, interceptando as chamadas efetuadas para
os arquivos do tipo HTML. Temos ainda um trecho que deve ser adicionado, no início de web.xml, para ativar as
configurações definidas no arquivo app-servlet.xml, com a atribuição de um segundo servlet, mapeado para a
raiz do aplicativo, e tendo o parâmetro contextConfigLocation apontando para o arquivo.
Nosso sistema pode ser executado, sendo necessário ativar o banco de dados Derby, antes da execução do
servidor Tomcat.
Execução do sistema baseado no Spring Web MVC.
Arquitetura MVC com Spring
Confira agora a construção de aplicativo usando a arquitetura MVC, no Java, com base no framework Spring.
Conteúdo interativo
Acesse a versão digital para assistir ao vídeo.
Vem que eu te explico!
Os vídeos a seguir abordam os assuntos mais relevantes do conteúdo que você acabou de estudar.
Framework Spring
Conteúdo interativo
Acesse a versão digital para assistir ao vídeo.
Arquitetura MVC
Conteúdo interativo
Acesse a versão digital para assistir ao vídeo.
Verificando o aprendizado
Questão 1
A arquitetura MVC é considerada um padrão no desenvolvimento de aplicativos cadastrais, tanto em sistemas
Web, quanto desktop ou móveis. Segundo o padrão arquitetural, que divide o aplicativo em três camadas bem
definidas, qual camada deveria conter os componentes do tipo DAO?
A
Controller
B
Model
C
Presentation
D
View
E
Dispatcher
A alternativa B está correta.
Entre as camadas do modelo MVC temos a Model, que será responsável pelas atividades relacionadas à
persistência dos dados. Os componentes DAO visam concentrar as operações sobre o banco de dados,
meio mais comum de persistência dos sistemas cadastrais, sendo definidos ao nível da camada Model.
Questão 2
O framework Spring permite a inclusão de funcionalidades nas classes de forma simples, com base em
anotações, as quais são reconhecidas pelo ferramental, gerando o código necessário para que se obtenha o
efeito desejado. Supondo que desejamos mapear uma rota específica para o controlador, ou seja, associar
determinado endereço a um processo de negócios de nosso sistema, qual seria a anotação adequada?
A
Controller
B
EnableTransactionManagement
C
Component
D
RequestMapping
E
Transactional
A alternativa D está correta.
A anotação Controller transforma a classe em um controlador, com as rotas para seus métodos mapeadas
através de RequestMapping. Para habilitar o gerenciamento de transações, nosso controladordeve ser
anotado com EnableTransactionManagement, fazendo com que as transações sejam utilizadas em
qualquer método anotado com Transactional, o que normalmente é indicado para os métodos do DAO que
efetuam modificações sobre os dados.
2. Implementação da camada de serviço
Conceitos
Interoperabilidade
Um sistema interoperável deve permitir acesso a suas funcionalidades, segundo padrões de comunicação
abertos aceitos pelo mercado, tornando transparente, ou quase, o processo de integração.
O elemento principal para viabilizar a interoperabilidade seria a definição de padrões de interface abertos, com o
mínimo de acoplamento possível.
Saiba mais
Com a adoção de tecnologias como as citadas, o termo serviço tornou-se uma terminologia comum,
definindo uma funcionalidade oferecida para o ambiente externo, com base em uma interface
aderente a algum padrão específico, sem exposição dos elementos internos. 
Para definir um serviço independente de plataforma, ou seja, um processo interoperável, iremos precisar de
alguns elementos arquiteturais específicos:
Sistema de registro e localização, para viabilizar acessos externos.
Interface de descrição de serviços, com a assinatura dos serviços disponibilizados.
Protocolo de comunicação, seguindo padrões abertos de ampla aceitação.
Com o surgimento crescente de sistemas para Web, a disponibilização de serviços se tornou muito comum, e
conceitos como B2B (Business to Business) e B2C (Business to Consumer) vieram para sintetizar os objetivos da
comunicação efetuada. B2C define a comunicação entre a empresa e o consumidor, que hoje se popularizou no
uso dos aplicativos para celulares.
Web Services
Os serviços disponibilizados na rede, ou Web Services, imediatamente adotaram padrões de comunicação
abertos, nos quais despontaram os modelos:
SOAP
Simple Object Access Protocol.
REST
Representational State Transfer.
Com relação ao SOAP, ele é mais antigo, sendo continuamente substituído pelo REST no B2C, mas ainda muito
utilizado no B2B, devido ao seu alto nível de formalismo.
Devido ao baixo formalismo do tipo REST, onde há uma grande presença da sintaxe JSON (Java Script Object
Notation) na comunicação, é o tipo predominante na construção de sistemas que envolvam clientes móveis.
• 
• 
• 
Os Web Services REST apenas adotam os métodos do protocolo HTTP, como GET e POST, para efetuar
operações de consulta ou inclusão de recursos, sem um sistema de registro ou descritor de serviços. Claro que a
ausência do descritor de serviços irá inviabilizar a construção de clientes de comunicação de forma
automatizada, exigindo maior conhecimento do desenvolvedor acerca do padrão de chamadas.
Saiba mais
Uma API (Application Program Interface) se refere ao conjunto de chamadas disponibilizadas para
acesso a funcionalidades específicas de um sistema qualquer, comum em muitos utilitários e para o
próprio sistema operacional. Quando consideramos os diversos serviços oferecidos por um sistema
na rede, via SOAP ou REST, temos a API desse sistema. 
Através do framework Spring, teremos grande facilidade para criar controladores do tipo REST, permitindo a
criação de APIs para sistemas corporativos Java de forma rápida.
Sintaxe XML e JSON
Padrão XML
Padrões de escrita como XML (Extended Markup Language) e JSON (Java Script Object Notation) são voltadas
para a representação de dados. Utilizam texto, com neutralidade de plataforma e transparência para firewalls,
permitindo que os mais diversos sistemas trabalhem com os dados, sem risco de bloqueios na comunicação.
Um documento XML bem formado é aquele que segue todas as regras de escrita, possuindo uma
gramática.
A gramática XML Schema Definition (XSD) pode ser observada na sequência. O uso de um namespace no
documento alvo, com base em um atributo xmlns, nos dá uma breve indicação de que podemos adotar mais de
uma gramática.
python
 
O conhecimento acerca de XML é muito útil na implementação de sistemas com base em Spring, particularmente
no que se refere à construção dos arquivos de configuração, algo que podemos observar no fragmento a seguir.
python
 
Note que temos um namespace default, para definir os elementos de bean, e diversos outros elementos 
gramaticais, como o uso de tx para o gerenciamento de transacional, ou context para os elementos relacionados 
ao contexto.
Padrão JSON
Para o JSON, temos apenas regras mínimas, sem qualquer especificação gramatical. As regras definidas para 
escrita em JSON são:
 
 
 
 
 
 
 
 
 Jonas
 Carla - RH
 Férias
 Férias iniciando hoje
Todo campo é um par chave-valor separado por dois pontos.
Nomes de campos, ou chaves, são escritos entre aspas.
Valores podem ser textos, numéricos, booleanos, nulos, listas ou objetos.
Objetos são grupos de pares chave-valor delimitados por chaves.
Listas são definidas com o uso de colchetes.
Por exemplo, os produtos presentes em uma base de dados poderiam ser expressos pelo documento JSON a 
seguir. 
 
 
 
Exemplo
 
{"produtos": [{"id": 1, "nome": "Lápis", "quantidade": 500},{"id": 2, "nome": "Caneta", "quantidade": 
350},{"id": 3, "nome": "Borracha", "quantidade": 400}],"total": 3}
 
 
Web Service REST
Arquitetura REST
Os Web Services do tipo RESTful permitem o uso, entre outras opções, de JSON na comunicação, utilizando um 
formato mais natural para os dados, além de diminuir o fluxo necessário. O nome RESTful está relacionado à 
plena utilização REST.
A característica básica do REST é a utilização dos métodos do protocolo HTTP para oferecer os serviços de:
• 
• 
• 
• 
• 
Consulta de dados
 
 
Inclusão de dados
 
 
Alteração de dados
 
 
Remoção de dados
 
 
No REST, a unidade de trabalho fundamental é a entidade, sempre associada a um endereço de base, e as 
operações efetuadas sobre ela são determinadas pelos métodos HTTP.
 A tabela seguinte resume a utilização dos métodos do HTTP pelo REST e exemplos de endereços para acesso 
aos recursos que serão manipulados. 
Operação Método HTTP Exemplos de Endereços
INCLUSÃO POST http://localhost:8080/cadastro/produtos
ALTERAÇÃO PUT http://localhost:8080/cadastro/produtos
REMOÇÃO DELETE http://localhost:8080/cadastro/produtos/1002
CONSULTA GET http://localhost:8080/cadastro/produtos 
http://localhost:8080/cadastro/produtos/1002
Tabela: Operações sobre entidades no REST.
Denis Cople.
Na inclusão ou alteração, iremos utilizar o mesmo endereço, formado pela junção do endereço de base do sistem
a com o nome da entidade, onde temos a utilização de Produto nos exemplos. Em ambos os casos temos a 
passagem dos valores, para a operação que será efetuada, no corpo (body) da requisição HTTP, utilizando o 
formato JSON.
 
 
 
Apesar de utilizar o mesmo endereço, o método de tratamento será diferenciado, ao nível do Web 
Service, com a identificação do método HTTP utilizado, podendo ser POST ou PUT. 
 
Na consulta, com base no GET, podemos efetuar a chamada descrita no parágrafo anterior, onde serão 
recuperadas todas as entidades do banco, na forma de uma lista JSON, ou podemos acrescentar a chave 
primária da entidade desejada ao endereço, tendo como exemplo o código do produto, o que irá restringir a 
busca, com o retorno de apenas uma entidade, com os dados expressos no formato JSON.
 Na remoção de uma entidade, através do método DELETE, o endereço deve ser o mesmo que foi utilizado para 
a consulta de uma entidade, ou seja, deve incluir a chave primária da entidade. A chave será extraída do 
caminho (path), para que ocorra o tratamento, ao nível do Web Service, e respectiva exclusão da entidade no 
banco de dados.
Spring Boot
Podemos criar de forma muito simples a camada de serviço REST, com base no Spring Boot, o qual define um 
servidor minimalista, que encapsula a implementaçãodo Tomcat, na porta padrão 8080.
 A criação de projetos Spring Boot é simplificada com a utilização do gerenciador Maven, padrão do Eclipse, 
onde a configuração do projeto é definida no arquivo pom.xml. As bibliotecas necessárias devem ser 
referenciadas no arquivo, facilitando o acréscimo de funcionalidades do Spring.
Projeto ServicoSpring02
Configuração
Vamos iniciar com a criação de um projeto simples, tipo Maven, denominado ServicoSpring02, com Group Id 
“unesa”. 
 
 
Escolher projeto 
 
 
 
 
Nome e local de salvamento 
 
 
Para facilitar a configuração do projeto, vamos acessar a ferramenta Spring Initializr, disponível no endereço site 
start.spring.io, onde podemos escolher as opções desejadas do framework Spring, sendo gerado o arquivo pom.
xml. Inicialmente, devemos escolher projeto do tipo Maven, linguagem Java, Spring Boot 2.6.3, e definir os 
mesmos valores utilizados no projeto para Artifact e Group.
Configuração no Spring Initializr.
Em seguida, vamos adicionar as seguintes dependências, com a abertura da seleção efetuada através das 
teclas CTRL+B, ou clique no botão ADD DEPENDENCIES, lembrando-se de segurar a tecla CTRL para a seleção 
múltipla:
Spring Data JPA
 
 
Spring Web
 
 
Apache Derby Database
 
 
As bibliotecas escolhidas, na imagem a seguir, fornecem uma estrutura mínima para o desenvolvimento, 
incluindo a persistência via JPA, arquitetura para Web e driver para acesso ao Derby.
Dependências no Spring Initializr.
Ao final, clicar em GENERATE, ocorrendo o download do projeto compactado para Eclipse, substituindo arquivo p
om.xml pelo gerado. Outra opção é clicar em EXPLORE, copiar o código gerado e colar sobre o conteúdo de 
arquivo.
 Talvez seja necessário algum pequeno ajuste, de forma a obter o conteúdo apresentado a seguir no arquivo pom
.xml do projeto.
python
 
 4.0.0
 
 org.springframework.boot
 spring-boot-starter-parent
 2.6.3
 
 
 unesa
 ServicoSpring02
 0.0.1-SNAPSHOT
 ServicoSpring02
 Service com Spring Boot
 
 11
 
 
 
 org.springframework.boot
 spring-boot-starter-data-jpa
 
 
 org.springframework.boot
 spring-boot-starter-web
 
 
 org.springframework.boot
 spring-boot-starter-test
 test
 
 
 org.apache.derby
 derbyclient
 
 
 
 
 
 org.springframework.boot
 spring-boot-maven-plugin
 
 
 
Para reconhecer as modificações, clique com o botão direito sobre o projeto e escolha a opção Reload POM. 
Clique no botão Resolve em Resolve Project Problems, caso necessário.
Resolução de problemas no NetBeans.
Camada de Serviços REST
Vamos copiar a entidade Produto dos projetos anteriores, mantendo o pacote unesa.model, sem modificações. 
Depois, criar outra versão do DAO, no pacote unesa.dao, mantendo o nome anterior (ProdutoDAO), de acordo 
com a listagem a seguir. 
java
 
Note a simplicidade para a definição de um DAO com base na biblioteca Spring Data. Precisamos definir uma 
interface descendente de JpaRepository, com o fornecimento dos tipos da entidade, no caso Produto, e da chav
e primária.
 Ao executar o servidor, a interface de repositório será identificada, e os códigos JPA necessários para gerenciar 
nossas entidades serão gerados de forma automática. Entre os métodos gerados no processo, podemos 
destacar: 
public interface ProdutoDAO extends 
 JpaRepository{
}
 
 
 Método save
Utilizado tanto na inclusão quanto na alteração da entidade.
 
 
 
 
 
 Método deleteById
Utilizado para exclusão a partir da chave primária.
 
 
 
 
 
 Método findById e findAll
Utilizados nas consultas.
 
 
 
Com a persistência definida, podemos criar o controlador, com o nome ProdutoController, no pacote unesa.contr
oller, utilizando a listagem apresentada a seguir.
java
 
O primeiro passo foi o uso de RestController, uma anotação que avisa ao Spring para criar toda a infraestrutura 
necessária para o serviço, com o mapeamento do endereço inicial, que no caso é produtos, através de RequestM
apping. Quanto à anotação CrossOrigin, ela serve para permitir acesso ao serviço a partir de endereços e portas 
externos, sendo utilizado como exemplo o padrão de execução de aplicativos ReactJS.
 O relacionamento com o DAO é determinado pelo uso de Autowired, que coloca o repositório no contexto do 
Spring, assumindo a conexão padrão com o banco de dados e o gerenciamento de transações pelo contêiner.
 Temos a utilização da anotação GetMapping para as consultas, onde obterTodos retorna todas as entidades do 
banco, a partir de uma chamada para findAll, enquanto obter resgata a chave primária presente no endereço, e 
utiliza findById para retornar o produto correto. 
@RestController
@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping("/produtos")
public class ProdutoController {
 @Autowired
 private ProdutoDAO dao;
 @GetMapping
 public List obterTodos(){
 return dao.findAll();
 }
 @GetMapping("/{codigo}")
 public Produto obter(@PathVariable String codigo) {
 return dao.findById(codigo).get();
 }
 @PostMapping
 public Produto inserir(@RequestBody Produto produto) {
 return dao.save(produto);
 }
 @DeleteMapping("/{codigo}")
 public void deletar(@PathVariable String codigo) {
 dao.deleteById(codigo);
 }
 @PutMapping
 public void alterar(@RequestBody Produto produto) {
 dao.save(produto);
 }
}
 
 
 
Comentário
 
 Note como a parte dinâmica do endereço é definida entre chaves, sendo recuperada nos 
parâmetros de obter através da anotação PathVariable. 
 
 
Para a remoção, é utilizada a anotação DeleteMapping com a chamada para deleteById. Como não temos o 
retorno de valor (tipo void), o serviço é classificado como one way.
Enquanto o método inserir é anotado com PostMapping, alterar recebe PutMapping, sendo que, em ambos os 
casos, temos a passagem dos valores para a entidade fornecidos no corpo do método, no formato JSON. Note a 
recuperação desses valores ao nível dos parâmetros de cada método, com base na anotação RequestBody, e a 
chamada para o método save do DAO, serve tanto para a inclusão quanto para a alteração de um produto.
Conexão com o banco de dados
Agora, precisamos configurar a conexão com o banco, utilizando um arquivo de propriedades, o que deve ser 
iniciado com a criação de um novo diretório de códigos-fonte, clicando com o botão direito sobre o projeto e 
escolhendo a opção New, seguida de Folder.
Definição do diretório de recursos do Spring Boot.
Iremos criar, na raiz do novo diretório, um arquivo com o nome application.properties, onde ficarão as 
configurações necessárias para a execução do Spring Boot. 
java
 
Na primeira parte do arquivo, temos a configuração do JDBC (Java Database Connectivity), onde devem ser 
fornecidos o endereço de conexão, usuário, senha e driver de acesso.
 O pool de conexões, com base no Hikari, permite que um menor número de conexões atenda a uma grande 
quantidade de usuários. Foi utilizada uma configuração comum, tamanho máximo de vinte conexões, com o 
nome HikariPoolExemplo001.
 Na configuração do JPA (dialeto do Derby), a escolha da opção none permite a criação automática de tabelas, 
evitando que os dados sejam apagados a cada nova execução.
 O programa principal, incluindo o método main, com a chamada para o método run de SpringApplication, será 
denominado deServicoSpring02, inserido no pacote unesa. 
# Derby connection settings
spring.datasource.url=jdbc:derby://localhost:1527/exemplo001
spring.datasource.username=exemplo001
spring.datasource.password=exemplo001
spring.datasource.driver-class-name=org.apache.derby.jdbc.ClientDriver
# HikariCP settings
spring.datasource.hikari.minimumIdle=5
spring.datasource.hikari.maximumPoolSize=20
spring.datasource.hikari.idleTimeout=30000
spring.datasource.hikari.maxLifetime=2000000
spring.datasource.hikari.connectionTimeout=30000
spring.datasource.hikari.poolName=HikariPoolExemplo001
# JPA settings
spring.jpa.database-platform=org.hibernate.dialect.DerbyDialect
spring.jpa.hibernate.use-new-id-generator-mappings=false
spring.jpa.hibernate.ddl-auto=none
java
 
Temos a anotação SpringBootApplication, para configurar a classe como principal do aplicativo, e ComponentSca
n, definindo a busca por componentes a partir do pacote unesa. No código interno da classe, temos a execução 
a partir da chamada para run, com a passagem da classe principal do sistema, que, no caso, é a própria classe S
ervicoSpring02.
Podemos executar o sistema, lembrando de ativar o banco Derby antes, efetuando o teste com o acesso ao 
endereço localhost:8080/produtos. O retorno será uma lista JSON com os produtos.
Teste do serviço criado com Spring Boot.
REST com Retrofit
Retrofit
O uso de métodos como PUT e DELETE pelo nosso Web Service, além da adoção de JSON na comunicação, 
pode dificultar testes tradicionais, baseados em formulários HTML. Retrofit, para a plataforma Java, permite o 
uso de todos os métodos do HTTP de forma simplificada, trabalhando com diversos conversores, alguns deles 
capazes de efetuar o mapeamento automático dos dados no formato JSON para objetos Java.
@SpringBootApplication
@ComponentScan(basePackages = "unesa")
public class ServicoSpring02 {
 public static void main(String[] args) {
 SpringApplication.run(ServicoSpring02.class,args);
 }
}
Projeto ClienteRest
Vamos definir nosso cliente em um projeto Java padrão, com base em Maven, adotando o nome ClienteREST, e u
nesa como valor de Group Id, conforme observado a seguir.
 
 
Escolher projeto 
 
 
 
 
Nome e local de salvamento 
 
 
O passo seguinte será a inclusão da dependência referente ao Retrofit com o clique do botão direito sobre a 
divisão Dependencies do projeto, escolhendo a opção Add Dependency. O Group Id será 
com.squareup.retrofit2, Artifact Id terá o valor retrofit e a versão utilizada será 2.9.0.
Acréscimo de dependência em projeto Maven.
Repetiremos o processo, adotando os mesmos Group Id e versão, mas, agora, para o artefato converter-jackson, 
e após acrescentar as dependências, nosso arquivo pom.xml estará com a codificação a seguir.
python
 
A biblioteca Retrofit permite trabalhar com todos os métodos HTTP, tanto de forma síncrona quanto assíncrona, 
através de interfaces Java. Utilizaremos o modo síncrono, pela simplicidade do programa.
 Definiremos uma classe de dados para Produto, onde poderíamos utilizar a entidade original, mas não 
equivaleria a uma situação real, onde fosse adotada uma API de terceiros. Iremos criar a classe Produto, no 
pacote unesa.data, de acordo com a listagem seguinte. Note que buscamos utilizar a forma mais simples 
possível para os objetos que serão instanciados, com a utilização de atributos públicos equivalentes aos campos 
do JSON. 
 4.0.0
 unesa
 ClienteREST
 1.0-SNAPSHOT
 jar
 
 
 com.squareup.retrofit2
 retrofit
 2.9.0
 
 
 com.squareup.retrofit2
 converter-jackson
 2.9.0
 
 
 
 UTF-8
 15
 15
 
java
 
Em seguida, definimos a interface de comunicação ProdutoService, no pacote unesa.retrofit, contendo o código 
a seguir.
java
 
As anotações GET, POST, PUT e DELETE irão definir o tipo de método HTTP utilizado, além da rota de acesso ao 
recurso entre parênteses. No caso de caminhos com identificação do recurso, como na obtenção de um produto 
pelo código, o trecho identificador é colocado entre chaves, sendo relacionado a um parâmetro do método 
através da anotação Path, algo que pode ser observado nos métodos obter e deletar.
 Para envio de dados JSON no corpo da chamada, basta definir um parâmetro do tipo da entidade, que, no caso, 
é Produto, anotado com Body, e todos os métodos encapsulam o retorno em um objeto genérico Call. O 
encapsulamento do tipo de retorno serve para trabalhar: 
 
public class Produto {
 public String codigo;
 public String nome;
 public Integer quantidade;
}
public interface ProdutoService {
 @GET("produtos")
 Call> obterTodos();
 @GET("produtos/{codigo}")
 Call obter(@Path("codigo") String codigo);
 @POST("produtos")
 Call inserir(@Body Produto produto);
 @DELETE("produtos/{codigo}")
 Call deletar(@Path("codigo") String codigo);
 @PUT("produtos")
 Call alterar(@Body Produto produto);
}
 
Para que a interface de serviços seja implementada de forma automática, deve ser instanciado um cliente 
Retrofit, onde o conversor de JSON será especificado. A criação do cliente segue o padrão de desenvolvimento 
Builder, permitindo configurações diversas de uma forma muito dinâmica e simples. Vamos ver como fica? 
 
 
 
Retrofit retrofit = new Retrofit.Builder()
 .baseUrl("http://localhost:8080")
 .addConverterFactory(JacksonConverterFactory.create())
 .build();
ProdutoService service = 
retrofit.create(ProdutoService.class);
 
Configurações para o Retrofit incluem o endereço de base das chamadas REST e a classe para conversão dos 
dados, que, no caso, é a JacksonConverterFactory. Com o cliente instanciado, a interface é implementada a 
partir de uma chamada do tipo create.
A seguir, a utilização das chamadas em nossa classe principal, a qual será criada no pacote unesa.clienterest, 
com o nome ClienteREST.
 
 
 
 
 Tanto de forma síncrona
 
 
 
Através de uma 
invocação via execute. 
 
 
 
 Quanto de forma 
assíncrona
 
 
 
Através de uma 
chamada enqueue e a 
criação de um objeto Cal
lBack.
 
 
 
 
java
 
As chamadas efetuadas para o serviço são muito semelhantes à execução padrão de métodos Java, mas todas 
seguidas de execute, pois estamos utilizando o modo síncrono dos objetos do tipo Call. Temos ainda a captura 
do retorno, na forma de objetos e coleções Java, encadeando uma chamada para body.
 A execução do cliente exemplo irá fornecer a saída ilustrada a seguir, lembrando que o servidor deverá estar 
executando. 
Execução do cliente REST.
A biblioteca Retrofit é muito utilizada para a comunicação com Web Services REST nos aplicativos para Android, 
onde, devido à exigência de processos paralelos para operações de entrada e saída, seria necessário utilizar o 
modelo de chamada assíncrona, como a seguir.
public class ClienteREST {
 public static void main(String[] args) throws Exception {
 Retrofit retrofit = new Retrofit.Builder()
 .baseUrl("http://localhost:8080")
 .addConverterFactory(JacksonConverterFactory.create())
 .build();
 ProdutoService service = retrofit.create(ProdutoService.class);
 // Processando de forma síncrona
 Produto p1 = new Produto();
 p1.codigo = "B002";
 p1.nome = "MANGA";
 p1.quantidade = 500;
 service.inserir(p1).execute();
 p1.quantidade = 800;
 service.alterar(p1).execute();
 for (Produto p : service.obterTodos().execute().body()) {
 System.out.println(p.nome+" ("+p.codigo+"): "+p.quantidade);
 }
 service.deletar("B002").execute();
 }
}
java
 
Na criação de sistemas REST, tanto do lado cliente quanto do lado servidor, com a utilização das bibliotecase 
frameworks corretos, boa parte da implementação é delegada para ferramentais especializados, como Spring 
Boot e Retrofit, permitindo um desenvolvimento ágil e de alta qualidade.
Web Service RESTful com Spring
Confira agora a construção de Web Service do tipo RESTful, no Java, com base no framework Spring.
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para assistir ao vídeo.
 
 
 
service.obterTodos().enqueue(new Callback>() {
 public void onResponse(Call> call, 
 Response> response) {
 for (Produto p : response.body()) {
 System.out.println(p.nome+" ("+p.id+"): "+p.quantidade);
 }
 }
 public void onFailure(Call> call, Throwable t) {
 System.out.println("Falha na conexão");
 }
});
Vem que eu te explico!
Os vídeos a seguir abordam os assuntos mais relevantes do conteúdo que você acabou de estudar.
Web Services
 
 
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para assistir ao vídeo.
 
 
 
 
Arquitetura REST
 
 
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para assistir ao vídeo.
 
 
 
 
Retrofit
 
 
 
 
 
 
 
Conteúdo interativo
 
Acesse a versão digital para assistir ao vídeo.
 
 
 
 
Verificando o aprendizado
Questão 1
Embora os sistemas cadastrais para Web tradicionais, dentro de uma arquitetura MVC, cumpram efetivamente 
com as necessidades de gerenciamento de dados em uma empresa, a comunicação com os clientes, no modelo 
B2C, deve se adequar às plataformas mais utilizadas por eles. Atualmente, é inegável a preponderância dos 
dispositivos móveis como plataforma cliente, e os aplicativos precisam se comunicar com serviços na Web, onde 
ocorre apenas o trânsito de dados, sendo delegado para aplicativo a responsabilidade do desenho das telas. 
Qual o formato de arquivo adotado preferencialmente na comunicação B2C?
 
A
 
XML
 
 
B
 
JAVA
 
 
C
 
RSS
 
 
D
 
DTD
 
 
E
 
JSON
 
A alternativa E está correta.
A forma mais utilizada de comunicação com clientes móveis, segundo um perfil B2C, é através de Web 
Services do tipo RESTful, onde o JSON é adotado como formato padrão, para a troca de informações. 
Serviços também podem ser utilizados na comunicação B2B, mas ocorre uma exigência maior quanto ao 
formalismo, onde o XML pode ser mais adequado, já que permite a definição de gramáticas via XSD ou 
DTD.
Questão 2
Para que um serviço seja aderente ao modelo REST, deve fazer o uso correto dos métodos disponibilizados pelo 
protocolo HTTP, e o mapeamento das rotas do controlador REST, quando utilizamos o framework Spring, é feito 
com base em anotações. Supondo que você queira definir o mapeamento de um método, no controlador REST, 
que promova a inclusão de um registro na base de dados, qual anotação deveria ser utilizada?
 
A
 
DeleteMapping
 
 
B
 
PutMapping
 
 
C
 
PostMapping
 
 
D
 
GetMapping
 
 
E
 
PatchMapping
 
A alternativa C está correta.
No modelo REST, os métodos do HTTP apresentam relação direta com as operações efetuadas sobre o 
banco de dados. Para efetuar uma consulta, usamos o método GET, inclusão de dados é feita via POST, 
alterações são feitas com base em PUT, com dados completos, ou PATCH, para dados parciais, e a 
remoção ocorre com base no DELETE. Se o método em questão causa uma inserção de dados, a anotação 
correta seria PostMapping.
 
 
3. Implementação da camada de segurança com Spring Security
 
 
Camada de segurança
Autenticação e autorização
O framework Spring traz um componente denominado Spring Security, que simplifica todas as tarefas 
relacionadas à manutenção da segurança.
 Para que um usuário possa acessar um sistema com acesso controlado, primeiramente deve ser autenticado, ou 
seja, através de algum processo de identificação, como login e senha, provedor OAuth 2.0, ou integração com Ac
tive Directory, entre outros, precisa provar que é um usuário autêntico para o sistema.
 Neste contexto, é importante compreender a diferença entre:
 
 
 
Codificação X Criptografia
 
Codificação e Criptografia
A palavra codificação significa transformação ou modificação de formato, como na tradução de um algoritmo em 
uma linguagem de programação. Um destaque, para o armazenamento e transmissão de dados, é a codificação 
para Base64. Qualquer codificação deve utilizar uma função de transformação reversível, para a obtenção da 
representação desejada, onde a recuperação do dado original é conhecida como decodificação.
 Na criptografia, precisamos de uma chave para efetuar as transformações, garantindo o sigilo. Temos dois tipos 
de criptografia: 
Criptografia simétrica
 
Utilizamos uma mesma chave para efetuar tanto 
a criptografia quanto a decriptografia.
 
Criptografia assimétrica
 
Utilizamos um par de chaves. As chaves 
costumam ser geradas a partir de grandes 
números primos.
 
Vamos entender um pouco mais sobre as chaves. Enquanto a chave privada é armazenada de forma segura, a ch
ave pública é distribuída, permitindo o envio de informações criptografadas por qualquer pessoa, mas que só 
poderão ser abertas pela chave privada do destinatário. No caminho contrário, apenas a chave privada é capaz 
de assinar um documento, enquanto a chave pública permite conferir a assinatura.
 
 
 
Ainda temos a criptografia destrutiva, também conhecida como hash, onde ocorre a perda de 
fragmentos dos dados originais, impedindo a decriptografia, o que a torna útil para guarda de senhas, 
tendo como exemplos comuns os algoritmos MD5 e SHA1. 
 
Existem dois níveis de autorização que devem ser considerados:
Relacionado à funcionalidade 
ou serviço
 
Por exemplo, o cadastro de aluno.
 
Relacionado aos dados de 
domínio
 
Por exemplo, como um aluno pode ver apenas 
suas próprias notas.
 
As de primeiro nível precisam apenas da identificação de recursos e definição de direitos de acesso aos 
mesmos. Como seria complexo atribuir um grande conjunto de direitos a cada usuário, definimos perfis com 
conjuntos de direitos, e associamos os usuários aos perfis.
 De forma geral, a biblioteca Spring Security irá viabilizar a autenticação e a autorização de primeiro nível, 
enquanto um segundo nível seria mais complexo e envolveria regras próprias do sistema. 
Sistemas Web com Spring Security
Arquitetura do Spring Security
Sistemas criados na plataforma Java para Web sempre trabalham com base em componentes do tipo Servlet, 
mesmo quando utilizamos páginas JSP.
 
 
 
Para que a segurança seja efetiva, é necessário interceptar a chamada HTTP antes do tratamento pelo 
Servlet, e como as rotas definem o acesso aos recursos, tornam-se o local ideal para a configuração 
de regras de acesso.
 
Um padrão de desenvolvimento utilizado para o tratamento da requisição é o Intercept Filter, definindo um filtro 
para interceptação, tratamento e direcionamentodo fluxo de execução, o qual permite sua inclusão na 
arquitetura, sem a modificação dos demais componentes que compartilham o ambiente. Podemos ainda utilizar 
uma sequência de filtros, por onde a requisição deverá passar, antes de chegar ao Serlvet, formando o que é 
conhecido como Filter Chain, e alguns deles podem atuar nas ações de autenticação e autorização.
 A arquitetura do Spring Security é completamente baseada no padrão Filter Chain, mas como existem 
diferentes formas de autenticação, além de diferentes rotas, utilizamos um filtro de segurança principal, do tipo D
elegatingFilterProxy, o qual faz um desvio temporário para uma ou mais cadeias de filtros, do tipo SecurityFilterC
hain, responsáveis pela avaliação de cada regra de acesso adotada no sistema. 
Utilização do padrão Filter Chain pelo Spring Security.
 
 
 
Saiba mais
 
Para saber mais sobre a utilização do padrão Filter Chain pelo Spring Security, coloque no seu site 
de busca “docs.spring.io/spring-security/reference/servlet/architecture” e clique na primeira opção 
que surgir.
 
 
Cada componente do tipo SecurityFilterChain será responsável pelo tratamento de uma rota específica, sendo 
composto por uma grande sequência de filtros do Spring Security, onde estão incluídos elementos como CorsFilt
er, para verificação de regras de acesso cruzado, LogoutFilter, para efetuar a desconexão do sistema, OAuth2Lo
ginAuthenticationFilter, relacionado ao uso de autenticação via OAuth 2.0, entre diversos outros.
Um filtro que merece atenção especial, e que fica posicionado próximo ao final da sequência, é o ExceptionTransl
ationFilter, responsável por interpretar os erros detectados nos filtros anteriores e direcionar o fluxo para o 
endereço de resposta correto para cada tipo de erro.
O processamento efetuado por ExceptionTranslationFilter envolve três passos:
 
 
 Primeiro passo
Inicialmente, é invocado doFilter, com passagem da requisição e reposta, para 
invocar o processamento do resto da aplicação quando não ocorrem exceções.
 
 
 
 
 
 Segundo passo
No caso de uma exceção de segurança do tipo AuthenticationException, é iniciado 
um contexto para autenticação, ou seja, o contexto de segurança é limpo, a 
requisição atual é armazenada em cache para a continuidade do fluxo após o login, 
e o ponto de entrada para autenticação (AuthenticationEntryPoint) é invocado, 
podendo ser uma página de login, verificação por OAuth 2.0 ou através do protocolo 
HTTP, entre outros.
 
 
 
 
 
 Terceiro passo
Para uma exceção do tipo AccessDeniedException, ocorre o desvio para o 
tratamento de erros relacionados à autorização de acesso.
 
 
 
A imagem apresentada a seguir permite visualizar o fluxo de execução descrito para o filtro do tipo ExceptionTras
lationFilter.
Funcionamento do SecurityFilterChain.
 
 
Saiba mais
 
 Para saber mais sobre o funcionamento do SecurityFilterChain, coloque no seu site de busca 
“docs.spring.io/spring-security/reference/servlet/architecture” e clique na primeira opção que surgir. 
 
 
Exemplo com Spring Web
Com base nos recursos do Spring Security, a autenticação em um projeto Web tradicional envolve algumas 
definições em arquivos XML ou uma classe para a configuração do acesso. Vamos voltar ao primeiro exemplo 
com Spring Web (ExemploWebSpring01), que executa sobre o servidor Tomcat, e efetuar todas as modificações 
necessárias.
 Precisamos baixar as bibliotecas necessárias, e adicioná-las ao projeto através do clique com o botão direito na 
divisão Libraries, e escolha da opção Add JAR/Folder. Todas as bibliotecas são oferecidas no repositório Maven 
do Spring Framework, segundo os endereços indicados a seguir, onde foi adotada a versão 4.2.9 do conjunto de 
bibliotecas:
Spring-security-web
 
Endereço para download:
https://repo1.maven.org/maven2/org/
springframework/security/spring-security-web/
4.2.9.RELEASE/
 
Spring-security-config
 
Endereço para download:
 
https://repo1.maven.org/maven2/org/
springframework/security/spring-security-config/
4.2.9.RELEASE/
 
Spring-security-core
 
Endereço para download: 
https://repo1.maven.org/maven2/org/
springframework/security/spring-security-core/
4.2.9.RELEASE/
 
O repositório permite navegação ao estilo FTP (File Transfer Protocol), onde devemos buscar os arquivos de 
extensão jar para cada uma das bibliotecas. Podemos observar o acesso da primeira biblioteca para download 
na figura seguinte.
Download de biblioteca do Spring Security.
Após adicionar as bibliotecas ao projeto, vamos trabalhar apenas com elementos de configuração na sintaxe XM
L. Criaremos o arquivo security.xml, na pasta WEB-INF.
python
 
Temos a definição de dois usuários, usu1 e usu2, com respectivas senhas e perfis, onde aqui são definidos ROLE
_GUEST e ROLE_USER, no trecho user-service, interno às tags para definição do gerenciador de autenticação, 
além da interceptação dos endereços relacionados a produtos, por meio da tag intercept-url, condicionando o 
acesso para usuários com perfil USER.
 Precisamos efetuar alterações no arquivo web.xml, com o acréscimo do novo arquivo de configuração entre os 
elementos de contexto, e a definição de um filtro para interceptação das requisições. A listagem seguinte 
apresenta as inserções. 
 
 
 
 
 
 
 
 
 
 
 
python
 
Além de incorporar as configurações de segurança anteriores, temos a definição do componente DelegatingFilter
Proxy, descrito anteriormente em nossa análise da arquitetura do Spring Security. As configurações efetuadas 
são suficientes para o bloqueio da página com a listagem dos produtos, mas ainda precisamos de modificações 
nos arquivos JSP para garantir a navegabilidade do sistema.
 A alteração em listaProdutos.jsp envolve o acréscimo de um link para o índice, antes da tabela com os produtos. 
Vejamos o trecho modificado.
 
 contextConfigLocation
 
 /WEB-INF/applicationContext.xml
 /WEB-INF/security.xml
 
 
 
 
 org.springframework.web.context.ContextLoaderListener
 
 
 
 
 
 springSecurityFilterChain
 
 org.springframework.web.filter.DelegatingFilterProxy
 
 
 
 springSecurityFilterChain
 /*
 
python
 
Uma alteração levemente mais complexa será feita no arquivo index.jsp, onde apresentaremos o nome do 
usuário logado, além de um botão para efetuar o logout, mas apenas quando ocorre uma autenticação anterior.
 
 
Lista de Produtos Cadastrados
 Página Inicial (../)
 
../
../
python
 
O código começa com o teste do usuário logado, reconhecido pelo atributo remoteUser, e se tiver ocorrido a 
autenticação, criamos um form para chamada do endereço de logout, com a passagem de alguns campos 
escondidos com o token da autenticação. Temos a exibição do nome do usuário logado, junto ao botão que 
efetua o logout.
 Executando o sistema, e clicando no link para a listagem de produtos, somos redirecionados para a tela de 
login, sendo utilizada a tela padrão do Spring Security, mas podemos personalizar a página utilizada através de 
algumas configurações nos arquivos XML. 
 
 
 
 
 Usuário Logado: 
 
 
 
 
 
 
 
 
Produtos (produtos/listaProdutos)
 
produtos/listaProdutos
produtos/listaProdutos
Login padrão.
Entrando com os dados de usu1, será liberado o acesso à listagem de produtos, onde podemos clicar no link 
para retorno ao índice, verificando onome do usuário logado. A partir daí, poderemos efetuar a desconexão (logo
ut) do sistema.
Índice do sistema com usuário logado.
Podemos efetuar o logout do sistema, e entrar com o usuário usu2, com perfil GUEST. Veremos um bloqueio por 
falta de direitos, ou seja, erro 403, representando um usuário não autorizado.
Exemplo de acesso não autorizado.
Por questões de simplicidade, utilizamos usuários predefinidos, representados em memória, mas como ainda 
não estamos criptografando as senhas, a alteração necessária para utilizar uma tabela de usuários pode ser 
feita modificando o arquivo security.xml.
python
 
Foi definido um bean para acesso ao banco de dados, com o nome dataSourceSec, configurado para utilizar o 
banco de exemplo que temos adotado desde o início do tema; temos como parâmetros o endereço do banco, 
classe para acesso, usuário e senha.
 Já no gestor de autenticação, passamos a utilizar a tag jdbc-user-service, fazendo referência ao bean de 
conexão definido, com o nome dataSourceSec. Especificamos as instruções SQL para consulta ao usuário pelo 
nome, no atributo users-by-username-query, e para a consultar o perfil do usuário, com base no atributo authorit
ies-by-username-query. A tabela deverá ser criada no banco de dados. 
Criação da tabela de usuários.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Precisamos alimentar a tabela com os mesmos dados dos usuários em memória, que foram utilizados na 
configuração inicial, e executar o sistema novamente.
Usuários cadastrados na tabela.
Segurança no REST
Modelo de Segurança do REST
Quando trabalhamos com REST, temos acesso aos serviços pelo protocolo HTTP, sem uma tela de login, como 
ocorria para um sistema Web padrão, o que nos leva à necessidade de um meio alternativo para autenticação, 
diretamente pelo protocolo. Além disso, serviços não gerenciam estados, o que exige a passagem das 
credenciais a cada chamada efetuada.
 
 
 
Na prática, o que temos é um token de acesso, com os dados necessários para a autenticação, que 
deve ser fornecido através do cabeçalho da requisição.
 
Para exemplificar o modelo de segurança do REST, modificaremos nosso servidor de exemplo ServicoSpring02, 
construído anteriromente. Começamos com o acréscimo da dependência necessária no arquivo pom.xml, 
conforme o fragmento seguinte.
python
 
Pode ser necessário ativar a resolução de problemas, com o clique do botão direito sobre o nome do projeto e 
escolha da opção Resolve Project Problems.
 Podemos executar nosso projeto e acessar o endereço localhost:8080, onde já será verificada a atuação do 
sistema de login. 
Tela padrão de login para o Spring Boot.
Vamos começar a configurar os aspectos de segurança, desta vez, através do conjunto de anotações do Spring 
Security. Criaremos a classe ConfigSeguranca a seguir no pacote unesa.security.
 org.springframework.boot
 spring-boot-starter-security
java
 
Criptografia com REST
No exemplo com REST passaremos a adotar criptografia, tendo como base um bean do tipo BCryptPasswordEnc
oder. Ele fará a criptografia de senha dos usuários, e embora utilizemos aqui para usuários em memória, seria 
declarado e invocado da mesma forma ao nível de um controlador associado à persistência em banco de dados.
 O método userDetailsService será responsável pelo retorno do bean padrão para gerência de usuários, onde 
aqui temos apenas o usuário usu1, com senha criptografada e perfil USER, mas sendo possível incluir usuários 
na sequência do builder. Ao final, é retornado o gerenciador em memória, instanciado como um objeto do tipo In
MemoryUserDetailsManager, tendo como parâmetro nosso usuário gerado no passo anterior.
 Finalmente, temos a sobrescrita do método configure, onde são definidas as regras de acesso para o sistema, 
sempre a partir de http, do tipo HttpSecurity. Seguindo o fluxo de chamadas, é exigida autenticação, mas com 
livre acesso para raiz e índice (permitAll), enquanto o caminho produtos é restrito ao perfil USER (hasRole), o 
que é concatenado com o meio de autenticação, diretamente pelo protocolo HTTP (httpBasic). Como o objetivo 
será autenticar via requisição, será necessário desabilitar a proteção padrão de sistemas Web, utilizando csrf e di
@Configuration
@EnableWebSecurity
public class ConfigSeguranca extends WebSecurityConfigurerAdapter {
 @Bean
 @Override
 public UserDetailsService userDetailsService() {
 UserDetails user = User.builder()
 .username("usu1")
 .password(passwordEncoder().encode("1234"))
 .roles("USER").build();
 return new InMemoryUserDetailsManager(user);
 }
 @Bean
 public PasswordEncoder passwordEncoder() {
 return new BCryptPasswordEncoder();
 }
 @Override
 protected void configure(final HttpSecurity http) 
 throws Exception {
 http.authorizeRequests()
 .antMatchers("/", "/index").permitAll()
 .antMatchers("/produtos/**").hasRole("USER")
 .anyRequest().authenticated()
 .and()
 .httpBasic();
 http.csrf().disable();
 }
}
sable.
 Criaremos uma classe para respostas de texto, com o nome MensagemSimples, no pacote unesa.model, a qual 
será utilizada na resposta padrão, ao nível da raiz. 
java
 
Definimos uma classe para representar respostas do servidor, com o título e a mensagem, que será utilizada 
pelo controlador mapeado para a raiz. Em seguida, a criação do controlador, com o nome IndexController, no 
pacote unesa.controller.
public class MensagemSimples {
 String titulo;
 String mensagem;
 public MensagemSimples(String titulo, String mensagem) {
 this.titulo = titulo;
 this.mensagem = mensagem;
 }
 public String getTitulo() { return titulo; }
 public void setTitulo(String titulo) { this.titulo = titulo; }
 public String getMensagem() { return mensagem; }
 public void setMensagem(String mensagem) { 
 this.mensagem = mensagem;
 }
}
java
 
O controlador concentra os mapeamentos para a raiz e para o endereço index, ambos com a mesma resposta 
padrão. Já que o acesso para esses caminhos foi definido como livre (permitAll), podemos executar o sistema e 
acessar a raiz, sem autenticar, obtendo a resposta a seguir.
Resposta padrão do servidor REST autenticado.
Ao acessar o endereço localhost:8080/produtos, será solicitada a autenticação via HTTP, com a apresentação 
do login padrão do navegador.
Solicitações HTTP do Retrofit
Vamos ajustar o cliente REST para trabalhar com autenticação, fornecendo as credenciais nas solicitações HTTP 
do Retrofit.
 Retornando ao projeto ClienteREST, acrescentar uma dependência no pom.xml, referente ao objeto necessário 
para interceptar a requisição HTTP. 
@RestController
@CrossOrigin(origins = "http://localhost:3000")
@RequestMapping("/")
public class IndexController {
 @GetMapping
 public MensagemSimples acessar(){
 return new MensagemSimples("Status",
 "Conexão efetuada com sucesso");
 }
 @GetMapping("index")
 public MensagemSimples acessar2(){
 return acessar();
 }
}
python
 
Após recarregar a configuração do Maven e solicitar a resolução de problemas do projeto, estaremos aptos a 
utilizar a biblioteca para interceptação de requisições HTTP. Para tal, vamos criar a classe InterceptadorLogin, 
no pacote unesa.security, com o código a seguir. 
java
 
O funcionamento da classe é baseado no método intercept, como implementação de Interceptor. A partir da 
cadeia de execução (chain), obtemos a requisição corrente, geramos uma nova requisição a partir da original, 
com a inclusão do token de autorização no header, e procedemos com a execução da nova requisição. Como 
podemos observar, tudo o que a nova classe faz é inserir as informações de autenticação no cabeçalho da 
requisição, sendo que o token deve ser fornecido no construtor.
 Criaremos a classe GestorServico, no