Buscar

Arquitetura de MicroServices com Spring Cloud e Spring Boot

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 53 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 53 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 53 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

Arquitetura de MicroServices 
com Spring Cloud e Spring Boot 
 
 
Sumário 
 
1. Introdução 
2. Implementando o Config Server. 
3. Subindo um Eureka Server e conectando-o ao Config Server. 
4. Construindo um Servidor de Autorização OAuth2. 
5. Implementando Serviço de Pedidos. 
Introdução 
 
Fala pessoal, estou começando hoje uma série de Stories onde vamos abordar a construção de 
uma Arquitetura de MicroServices utilizando os frameworks Spring Cloud e Spring Boot da 
Pivotal. 
Antes de começar decidi fazer uma breve introdução sobre as diferenças entre a Arquitetura 
de MicroServices e a Monolítica assim como reiterar alguns conceitos que surgem quando se 
utiliza a mesma. 
Serão stories semanais e o sumário estará presente em todas para facilitar a navegação entre 
os tópicos. Então chega de enrolação e vamos ao que interessa! 
 
Servidor de Configuração 
 
 
 
Como agora não teremos mais só uma aplicação, mas varias espalhadas por diversos 
servidores é necessário centralizar a configuração de todas as aplicações em um só lugar. 
A Pivotal possui um projeto chamado Spring Cloud Config que possibilita a criação de uma 
configuração externalizada em um sistema distribuído. Com o Config Server você tem um lugar 
central, um repositório git por exemplo, para gerenciar os arquivos de configuração de cada 
aplicativo que se encontram rodando em outros ambientes. 
As aplicações consultarão o Config Server para obter suas configurações na hora da 
inicialização. Podem ser desde configurações de acesso ao banco de dados até mesmo a porta 
em que desejamos que a aplicação suba. 
Service Registry 
 
 
 
Quando se tem muitas aplicações rodando em diferentes ambientes é difícil controlar qual o 
host ou porta onde cada um se encontra e se a mesma está online ou não. 
O Service Registry é um banco de dados preenchido com informações sobre como enviar 
pedidos para instâncias de microservice. Cada instância que sobe se cadastra no Service 
Registry informando que está Online para receber requisições. 
Além de deter as informações de acesso as instâncias, o Service Registry também realizará 
checagens de saúde da aplicação e o balanceamento de carga de instâncias da mesma 
aplicação. 
Para realizar essa função iremos utilizar o Eureka da Netflix. 
Circuit Braker 
 
 
 
Em uma aplicação distribuída é comum que haja chamadas entre diversos servidores na rede. 
Diferente da chamada em memória, as chamadas remotas podem falhar ou ficarem pendentes 
se o host destino estiver indisponível até que um tempo limite seja atingido. 
Se vários clientes tentarem acessar esse mesmo recurso indisponível podemos ter uma falha 
crítica e isso pode afetar o funcionamento de todo o sistema. 
O Circuit Break ficou popular por evitar esse tipo de cascata. Basicamente a request a um host 
que pode falhar é envolta em um Circuit Breaker e se essa chamada começar a falhar é 
retornado um erro conhecido e registrada alguma métrica informando que a request está 
falhando naquele local. 
Tendo métricas em mãos dos locais exatos onde a aplicação está falhando, se torna menos 
complicada a busca pela resolução de erros ou gargalos na aplicação. 
Para essa série de stories iremos utilizar o Hystrix da Netflix para tratar o Circuit Braker. 
Gateway 
 
 
 
Imagine que cada instância de um microservice sobe com uma porta diferente, e se você não 
tem um ponto de entrada único para sua aplicação como um todo, isso pode se tornar um 
caos na hora fornecer os recursos para um cliente web ou mobile. 
O gateway funciona como uma porta de entrada da sua aplicação, todo o trafego passa por ele 
antes de ser encaminhado para o microservice específico respeitando as rotas que são 
configuradas no mesmo. 
O Gateway geralmente recebe a requisição desejada pelo cliente e consulta no Service Registry 
qual instância de microservice responde por aquela rota. Se for uma rota segura, ele também 
irá realizar a autenticação junto ao servidor de autorização antes de fazer o redirecionamento. 
Implementando o Config Server 
 
Vamos criar nosso Servidor de Configuração, que tem o objetivo de centralizar toda a 
configuração da nossa rede de Microservices em um só lugar. 
Todos os arquivos de configuração do nosso sistema estarão em um repositório git e o 
Servidor de Configuração será o responsável por ler as informações no repositório e fornece-
las às aplicações através de requests HTTP. 
Gerando a aplicação no Spring Initializr 
Acesse o site do Spring Initializr e preencha as configurações como na imagem. Basicamente 
escolhemos qual vai ser o gerenciador de dependências (Maven), a linguagem de programação 
(Java), as dependências necessárias para o projeto (Web, Actuator e Config Server) e 
configuramos os metadados do Maven. Por fim geramos o projeto clicando em Generate 
Project, Ctrl + Enter ou Command + Enter. (Atenção para a versão do Spring, estamos usando 
a 1.5 nesse projeto) 
 
 
Spring Initializr preenchido para gerar o Config Server 
 
Agora você deve ter em mãos um delivery-config-server.zip. Descompacte-o em uma pasta 
chamada delivery, onde ficaram todos os seus Microservices criados nesse projeto. 
 
 
Pasta principal do projeto 
 
Importe o projeto em sua IDE de preferência, aqui estou usando o Intellj. Como podemos ver 
na imagem abaixo essa é a estrutura de projeto padrão gerada pelo Spring Initialzr. 
 
 
Arvore de diretórios do Projeto 
Os arquivos listados abaixo podem ser descartados por não serem importantes para o projeto, 
ou seja ficamos com uma raiz de projeto tendo somente a pata src e o pom.xml 
 
1. Diretório .mvn (Configurações específicas do maven); 
2. Diretório static (Arquivos estáticos para uso em paginas web); 
3. Diretório templates (Templates do Spring MVC); 
4. Arquivo .gitignore (Arquivos ignorados pelo git, teremos um na pasta raiz do projeto 
delivery); 
5. Arquivo mvnw (Usar versão e parâmetros expecíficos do maven); 
6. mvnw.cmd (Usar versão e parâmetros específicos do maven no Windows); 
 
 
Arvore de diretórios do Projeto sem arquivos desnecessários 
Agora que já estamos com o projeto importado, vou abrir os arquivos gerados e explicar em 
detalhes cada um. 
Vamos começar pelo pom.xml. 
 
<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 <groupId>com.coderef</groupId> 
 <artifactId>delivery-config-server</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <packaging>jar</packaging> 
 <name>delivery-config-server</name> 
 <description>Config Server</description> 
 <parent> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-parent</artifactId> 
 <version>1.5.4.RELEASE</version> 
 <relativePath/> <!-- lookup parent from repository --> 
 </parent> 
 <properties> 
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
 <project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding> 
 <java.version>1.8</java.version> 
 <spring-cloud.version>Dalston.SR1</spring-cloud.version> 
 </properties> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-actuator</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-config-server</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-web</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-test</artifactId> 
 <scope>test</scope> 
 </dependency> 
 </dependencies> 
 <dependencyManagement> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-dependencies</artifactId> 
 <version>${spring-cloud.version}</version><type>pom</type> 
 <scope>import</scope> 
 </dependency> 
 </dependencies> 
 </dependencyManagement> 
 <build> 
 <plugins> 
 <plugin> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-maven-plugin</artifactId> 
 </plugin> 
 </plugins> 
 </build> 
</project> 
 
Vou abordar aqui só configurações específicas do projeto, para mais informações sobre o 
Maven consulte a documentação oficial aqui. 
Vemos logo de cara que possuímos o spring-boot-starter-parent como nosso parent. Por ser 
um projeto spring-boot existem uma série de configurações que são previamente feitas nesse 
projeto fazendo com que você não se preocupe com configuração e sim com a implementação 
de seu produto. Todas as configurações impostas pelo Spring Boot podem ser sobrepostas 
extendendo a classe que a implementa ou em casos mais simples usando o application.yml. 
Logo abaixo temos a declaração das dependências do projeto, explicarei cada uma delas 
abaixo: 
 
 spring-boot-actuator: Se trata de um sub projeto do Spring Boot. Ele adiciona vários 
serviços de qualidade de produção à sua aplicação com pouco esforço de sua parte 
como o famoso /health por exemplo. 
 spring-boot-starter-web: Essa dependência é uma das mais importantes. Usando-a 
você já tem um projeto totalmente configurado para trabalhar com qualquer serviço 
web, como fornecer recursos REST e um tomcat embedded por padrão para subir o 
projeto. 
 spring-cloud-config-server: Aqui está a dependência mágica que irá transformar nosso 
MicroService em um Servidor de Configuração sem muito esforço adicional, apenas 
algumas configurações no application.yml. 
 spring-boot-starter-test: Por último, e não menos importante, a dependência de 
testes do Spring. Ela torna nosso projeto apto para a implementação de testes 
unitários, de API, integração, carga entre diversos outros. 
 
Como eu disse acima cada dependência dessa fornece tudo que o seu projeto precisa para 
tratar de um certo nicho de frameworks. O Spring Boot hoje é bem completo, e você consegue 
encontrar quase todo tipo de framework pré inicializado para utilizar em sua aplicação. 
Hoje em nosso projeto, temos apenas uma classe chamada 
DeliveryConfigServerApplication.java, e acredite se quiser, é só dela que vamos precisar para 
montar nosso Servidor de Configuração. Essa classe é responsável por subir a nossa aplicação 
usando a seguinte linha de código encapsulada dentro de um método main : 
SpringApplication.run(DeliveryConfigServerApplication.class, args); 
Para que nosso projeto seja reconhecido como um Aplicativo Spring Boot precisamos adicionar 
também a anotação @SpringBootApplication. 
Nós queremos que essa aplicação seja um Servidor de Configuração, e nada mais fácil que 
informar isso utilizando uma anotação. Isso é possível utilizando a anotação 
@EnableConfigServer. 
http://maven.apache.org/guides/
Veja abaixo como fica a classe completa. 
 
package com.coderef.delivery; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.cloud.config.server.EnableConfigServer; 
 
@SpringBootApplication 
@EnableConfigServer 
public class DeliveryConfigServerApplication { 
 
 public static void main(String[] args) { 
 SpringApplication.run(DeliveryConfigServerApplication.class, args); 
 } 
} 
 
Para finalizar precisamos configurar nosso o application.yml e o bootstrap.yml. 
 
 application.yml: Aqui são declaradas as configurações que você gostaria de substituir 
no starter do Spring boot e serão usadas no seu projeto. 
 bootstrap.yml: Esse arquivo é usado para realizar algumas configurações de 
inicialização do nosso parent, como o nome da aplicação no ecosistema do Spring 
Cloud e a conexão com um Servidor de Configuração. 
 
Como não há como o Servidor de Configuração utilizar ele mesmo para descrever sua 
configuração, ele será o único que descreveremos um application.yml. 
Obs:. Como optamos pelo padrão de arquivos .yml podemos deletar o arquivo 
application.properties. 
 
Crie o arquivo application.yml no diretório delivery-config-server/src/main/resources. 
 
server: 
 port: 9090 
 
spring: 
 cloud: 
 config: 
 server: 
 git: 
 uri: https://github.com/rafaelcam/delivery-configs 
 
Aqui configuramos a porta em que a aplicação irá subir e qual o repositório git que será usado 
para fornecer os arquivos que o nosso Servidor de Configuração irá disponibilizar para os 
outros Microservices via HTTP. 
Esse repositório pode ser remoto ou local, eu estou utilizando um repositório remoto e 
público. Para configurar um repositório local, ou obter mais informações sobre como usar um 
repositório privado consulte a documentação do Spring Cloud Config. 
No arquivo bootstrap.yml vamos informar somente o nome da aplicação. Como estamos 
tratando de uma aplicação distribuída com o Spring Cloud, essa informação é muito 
importante porque funcionará como um DNS quando uma instância dessa aplicação for 
http://cloud.spring.io/spring-cloud-static/spring-cloud-config/1.3.1.RELEASE/
registrada no Service Registry. Os outros MicroServices também consultarão o Service Registry 
utilizando este nome, pois o host da instância pode ser dinâmico. 
Crie o arquivo bootstrap.yml no diretório delivery-config-server/src/main/resources. 
 
spring: 
 application: 
 name: educafacil-config-server 
 
OK! Nosso Servidor de Configuração está pronto, agora vamos realizar um teste simples para 
ver se tudo está funcionando corretamente. 
Antes de subir a aplicação vamos adicionar um arquivo de exemplo no repositório de 
configurações chamado sample-config-app.yml com uma propriedade qualquer. 
 
delivery: 
 maxOrders: 10 
 minOrders: 1 
 
Depois de efetuar o commit e o push para o GitHub nosso repositório de configuração está 
assim. 
 
 
Arquivo de configuração foi adicionado ao repositório remoto. 
 
Agora sim! Suba a aplicação no Tomcat embedded executando a classe principal do projeto, 
ela deverá estar em pé na porta 9090 que nós configuramos no application.yml. 
 
 
Executando a classe principal para subir a aplicação no Tomcat Embedded 
 
Se você está vendo no log da aplicação a mensagem Tomcat started on port(s): 9090 (http) 
quer dizer que está tudo certo. Abra um navegador qualquer e acesse a seguinte URL. 
http://localhost:9090/delivery-sample-config/default 
Você deve estar vendo na resposta do navegador a seguinte resposta contendo todas as 
propriedades que configuramos no sample-config-app.yml . 
 
{ 
 "name": "delivery-sample-config", 
 "profiles": [ 
 "default" 
 ], 
 "label": null, 
 "version": null, 
 "state": null, 
 "propertySources": [ 
 { 
 "name": "https://github.com/rafaelcam/delivery-configs/delivery-sample-config.yml", 
 "source": { 
 "delivery.maxOrders": 10, 
 "delivery.minOrders": 1 
 } 
 } 
 ] 
} 
 
É isso ai galera, era isso que eu tinha pra mostrar hoje. No proximo POST vamos continuar com 
a série de stories criando um Service Registry (Eureka) e o conectando ao Config Server que 
criamos hoje. 
http://localhost:9090/delivery-sample-config/default
https://github.com/rafaelcam/delivery-configs/delivery-sample-config.yml
Subindo um Eureka Server e 
conectando-o ao Config Server 
 
Olá pessoal, hoje vamos criar nosso Service Registry, que será responsável por gerenciar o 
status e a localização dos Microservices em nossa rede. Para isso usaremos o Eureka, uma 
ferramenta desenvolvida pela Netflix e disponibilizada para a comunidade. 
O Eureka é um serviço REST (Representational State Transfer) que é usado principalmente na 
nuvem AWS (Amazon Web Services) para localizar serviços com o objetivo de balanceamento 
de carga e failover de servidores. 
O conjunto de ferramentas Spring Cloud possui uma implementação do Eureka para que 
possamos subir um Eureka Server utilizando uma aplicação Spring Boot. 
Gerando a aplicação no Spring Initializr 
 
Acesse o site do Spring Initializre preencha as configurações como na imagem. Escolhemos 
qual vai ser o gerenciador de dependências (Maven), a linguagem de programação (Java), as 
dependências necessárias para o projeto (Web, Actuator, Config Client e Eureka Server) e 
configuramos os metadados do Maven. Por fim geramos o projeto clicando em Generate 
Project, Ctrl + Enter ou Command + Enter. (Atenção para a versão do Spring, estamos usando 
a 1.5 nesse projeto) 
 
 
 
Você se lembra da pasta delivery, que criamos para colocar o nosso config server? Então, é lá 
que iremos descompactar o nosso Eureka Server. 
 
 
Implementando a Aplicação 
 
Como na parte 2 dessa série de stories já entramos em detalhes sobre os arquivos que são 
gerados e os que são desnecessários não falaremos mais disso para que essa story fique mais 
concentrada no conteúdo proposto. 
Vamos direto ao ponto, observando o pom.xml e explicando as dependências inéditas. 
 
<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 <groupId>com.coderef</groupId> 
 <artifactId>delivery-eureka-server</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <packaging>jar</packaging> 
 <name>delivery-eureka-server</name> 
 <description>Eureka Server</description> 
 <parent> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-parent</artifactId> 
 <version>1.5.4.RELEASE</version> 
 <relativePath/> <!-- lookup parent from repository --> 
 </parent> 
 <properties> 
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
 <project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding> 
 <java.version>1.8</java.version> 
 <spring-cloud.version>Dalston.SR1</spring-cloud.version> 
 </properties> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-actuator</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-eureka-server</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-config</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-web</artifactId> 
 </dependency> 
 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-test</artifactId> 
 <scope>test</scope> 
 </dependency> 
 </dependencies> 
 <dependencyManagement> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-dependencies</artifactId> 
 <version>${spring-cloud.version}</version> 
 <type>pom</type> 
 <scope>import</scope> 
 </dependency> 
 </dependencies> 
 </dependencyManagement> 
 <build> 
 <plugins> 
 <plugin> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-maven-plugin</artifactId> 
 </plugin> 
 </plugins> 
 </build> 
</project> 
 
Comparando com o projeto do Config Server, temos apenas duas novas dependências. 
Explicarei elas abaixo: 
 
 spring-cloud-starter-config: Como estamos utilizando um Config Server para centralizar 
nossa aplicação, o Spring fornece esta biblioteca para que a conexão com esse servidor 
seja simples, somente configurando no arquivo bootstrap.yml qual o host do Config 
Server. 
 spring-cloud-starter-eureka-server: Essa dependência é a mais importante. Ela torna 
possível transformar a aplicação Spring Boot em um Servidor Eureka somente com 
algumas configurações nos properties e uma anotação na classe principal. 
 
Como já sabemos, toda aplicação Spring Boot tem uma classe principal, temos que adicionar a 
ela a anotação @EnableEurekaServer para que seja iniciado um Servidor do Eureka. 
 
package com.coderef.delivery; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 
 
@SpringBootApplication 
@EnableEurekaServer 
public class DeliveryEurekaServerApplication { 
 
 public static void main(String[] args) { 
 SpringApplication.run(DeliveryEurekaServerApplication.class, args); 
 } 
} 
 
Agora precisamos configurar o nosso bootstrap.yml. Como disse anteriormente já entramos 
em detalhes para que serve cada arquivo nas stories anteriores, portanto irei somente explicar 
o conteúdo. 
Como a configuração da aplicação ficará no repositório do Config Server precisamos criar 
somente o bootstrap.yml localmente. 
Crie o arquivo bootstrap.yml no diretório delivery-eureka-server/src/main/resources. 
 
spring: 
 application: 
 name: delivery-eureka-server 
 cloud: 
 config: 
 uri: http://localhost:9090 
 
A configuração do nome da aplicação nós já conhecemos, porém temos algo novo neste 
bootstrap.yml. Configuramos a propriedade spring.cloud.config.uri que indica o host do 
Config Server e para que na hora da inicialização a aplicação peça a ele suas propriedades. 
Mas como o Config Server sabe qual é o arquivo em seu repositório que representa as 
configurações específicas dessa aplicação que está se conectando? 
Bem, é ai que entra uma das responsabilidades da propriedade spring.application.name. 
Quando a aplicação delivery-eureka-server estiver iniciando ela consultará a aplicação 
delivery-config-server, perguntando a ela se existe em seu repositório um arquivo com o 
nome configurado em spring.application.name e com a extensão properties ou yml. 
Mas espera um pouco, não criamos esse arquivo no repositório do Config Server ainda, estão 
vamos lá. 
No repositório de configurações do Config Server, no mesmo local onde criamos o sample-
config-app.yml na parte 2 dessa série, crie o arquivo delivery-eureka-server.yml com o 
conteúdo abaixo: 
http://a-de-microservices-com-spring-cloud-e-spring-boot-parte-2-ff03d8d45dba/
 
server: 
 port: 9091 
 
eureka: 
 instance: 
 hostname: localhost 
 client: 
 registerWithEureka: true 
 fetchRegistry: false 
 serviceUrl: 
 defaultZone: http://${eureka.instance.hostname}:${server.port}/eureka/ 
 server: 
 wait-time-in-ms-when-sync-empty: 3000 
 
Neste arquivo temos varias configurações novas, vamos passar uma a uma para descobrirmos 
do que se trata: 
 
 eureka.instance.hostname: Host onde o será iniciado o servidor do Eureka. 
 eureka.client.registerWithEureka: Mesmo sendo um Servidor do Eureka, essa 
aplicação não deixa de ser um Microservice como os outros, portanto ele deve se auto 
registrar no eureka. 
 eureka.client.fetchRegistry: Os clientes do Eureka obtêm as informações de registro 
do servidor e as armazenam no local. Depois disso, os clientes usam essa informação 
para encontrar outros serviços. Como essa aplicação é o próprio Servidor do Eureka, 
desabilitamos esta busca. 
 eureka.client.serviceUrl.defaultZone: Nada mais do que a localização do Eureka 
Server, já que essa aplicação vai se auto registrar. 
 eureka.server.wait-time-in-ms-when-sync-empty: Tempo em milissegundos que o 
Eureka Server irá esperar entre as sincronizações com os clientes. 
 
Agora temos dois arquivos de configuração em nosso repositório, como você pode ver abaixo. 
 
 
Certo! Como você já deve ter percebido temos uma dependência entre nossos dois 
Microservices criados até agora. Dependência em uma Arquitetura de Microservices não é 
uma coisa boa, porém se trata de um servidor de configuração que futuramente será 
clusterizado na nuvem e não iremos mais subir ele localmente. 
Mas por enquanto sempre que quisermos subir Eureka Server precisamos antes iniciar o 
Config Server. 
Para testarmos se já esta tudo funcionando corretamente, inicie o Config Server e depois o 
Eureka Server executando a classe principal, comovimos na story anterior. 
Observe o log da inicialização do Eureka Server e confira se contém essas duas linhas: 
Fetching config from server at: http://localhost:9090 (Início do Log) 
Tomcat started on port(s): 9091 (http) (Fim do Log) 
Isso significa que o Eureka Server está iniciado e funcionando. Acesse o endereço 
http://localhost:9091/ e confira se o painel do Eureka aparece. 
 
 
 
Aqui temos muita informação, tanto de serviços registrados quanto do consumo da maquina 
host e etc. 
A seção mais importante para nós no momento é a Instances currently registered with 
Eureka. Aqui obtemos informações preciosas dos nossos Microservices registrados no Eureka, 
como por exemplo: 
 
O Status UP ou DOWN. 
Quantidade de instâncias do mesmo Microservice registradas. Importante lembrar que o 
próprio Eureka irá realizar o load balancer entre elas quando for solicitada uma instância pelo 
Gateway por exemplo. 
Host e Porta onde a instância está escutando. 
Como só temos o Microservice do próprio Eureka Server registrado, não temos uma visão do 
quanto essa tela é importante ainda, mas de agora pra frente todo Microservice que nós 
implementarmos será registrado no Eureka, revelando assim todo o seu poder. 
http://localhost:9090/
http://localhost:9091/%60
O Servidor de Autorização 
 
Olá pessoal, dando continuidade a nossa sequência de stories sobre Microservices, hoje vamos 
criar nosso servidor de autorização que vai ser responsável por controlar a autenticação e 
autorização de nossos recursos. Nessa story vamos utilizar o Spring Security OAuth uma 
ferramenta poderosa disponibilizada pela Pivotal. Antes de iniciar a implementação do nosso 
Servidor de Autorização, vamos conhecer alguns conceitos importantes, isso é necessário para 
entendermos como funciona e qual o objetivo das tecnologias utilizadas. Vamos lá? 
OAuth2 
 
O Spring Security OAuth2 tem como base o OAuth2 um framework de 
autenticação e autorização aberto, poderoso e flexivel permitindo que 
sua aplicação não fique manipulando diretamente as credenciais dos 
usuários. 
Em um modelo tradicional de autenticação o cliente entra com suas 
credenciais diretamente e obtém acesso ao recurso protegido. Ficar 
trafegando as credenciais do usuário em cada requisição pode causar 
vários problemas e limitações, exemplo: 
 
 Aplicações de terceiros terão que armazenar as credenciais do usuário para solicitar 
um acesso no futuro. 
 O servidor de recursos tem que garantir e se preocupar sempre com um bom suporte 
a autenticação. 
 Alteração das credenciais dos usuários no servidor de recursos afetará todas as 
aplicações de terceiros. 
 
O OAuth2 busca solucionar esses problemas definindo papéis e criando uma camada 
intermediária de autenticação, com isso a aplicação cliente solicita uma concessão de 
autorização ao usuário e caso seja concedida ela é enviada ao servidor de autorização, esse 
por sua vez autentica e valida o usuário, se tudo estiver correto um token é emitido para que o 
cliente possa acessar o servidor de recursos. Confuso, não é mesmo? Calma, vamos identificar 
e explicar passo a passo o fluxo abaixo: 
 
 Resource Owner é o proprietário do recurso, ou seja, o usuário que irá entrar com as 
credenciais de acesso. 
 Client é a aplicação que irá acessar o servidor de recursos. Ela pode ser uma aplicação 
mobile, desktop, etc. 
 Authorization server é o servidor autenticação e autorização. É o que nós vamos 
implementa-lo nessa story. 
 Resource server são os recursos protegidos. 
 
 
Fluxo do Oauth2 
Fluxo de Autenticação 
 
 O Client solicita autorização ao Resource Owner. 
 O Client recebe uma concessão de autorização do Resource Owner, que é uma 
crendencial seguindo um dos padrões definidos pelo oAuth2. 
 O Client solicita um token de acesso ao Authorization Server Authorization Server. 
 O Authorization Server autentica o Client e valida a credencial informada pelo 
Resource Owner. Se for válida, um token de acesso é emitido.. 
 O Client solicita o acesso ao recurso protegido do Resource Server informando o Token 
de acesso. 
 O Resource Server valida o token de acesso. Se for válido ele atende a solicitação. 
 
Agora que deixamos claro o funcionamento de um Servidor de Autorização com oAuth2, 
vamos implementa-lo. 
Gerando a aplicação no Spring Initializr 
 
Acesse o site do Spring Initializr e preencha as configurações como na imagem. Escolhemos 
qual vai ser o gerenciador de dependências (Maven), a linguagem de programação (Java), as 
dependências necessárias para o projeto (Cloud OAuth2, Actuator, Config Client e Eureka 
Discovery, JPA, MySql) e configuramos os metadados do Maven. Por fim geramos o projeto 
clicando em Generate Project, Ctrl + Enter ou Command + Enter. (Atenção para a versão do 
Spring, estamos usando a 1.5 nesse projeto) 
 
https://start.spring.io/
 
Vamos descompactar esse projeto na pasta delivery, onde está o Config Server e o Eureka 
Server. 
 
 
Implementando a Aplicação 
 
Como de costume, não vamos discutir as configurações que já foram vistas nas stories 
anteriores, assim o conteúdo fica mais objetivo. 
Abaixo está o pom.xml gerado, vamos analisar as dependências inéditas. 
 
<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 <groupId>com.coderef</groupId> 
 <artifactId>delivery-auth-server</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <packaging>jar</packaging> 
 <name>delivery-auth-server</name> 
 <description>Oauth Server</description> 
 <parent> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-parent</artifactId> 
 <version>1.5.4.RELEASE</version> 
 <relativePath/> <!-- lookup parent from repository --> 
 </parent> 
 <properties> 
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
 <project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding> 
 <java.version>1.8</java.version> 
 <spring-cloud.version>Dalston.SR2</spring-cloud.version> 
 </properties> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-actuator</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-config</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-eureka</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-oauth2</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-data-jpa</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>mysql</groupId> 
 <artifactId>mysql-connector-java</artifactId> 
 <scope>runtime</scope> 
 </dependency> 
 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-test</artifactId> 
 <scope>test</scope> 
 </dependency> 
 </dependencies> 
 <dependencyManagement> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-dependencies</artifactId> 
 <version>${spring-cloud.version}</version> 
 <type>pom</type> 
 <scope>import</scope> 
 </dependency> 
 </dependencies> 
 </dependencyManagement> 
 <build> 
 <plugins> 
 <plugin> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-maven-plugin</artifactId> 
 </plugin> 
 </plugins> 
 </build> 
</project> 
 
Comparando com os projetos anteriores, temos apenas 3 dependências que ainda não vimos, 
são elas: 
 
 spring-cloud-starter-oauth2: Essa é a principal dependência desse projeto. Ela oferece 
toda a implementação necessária para a aplicação funcionar como servidorde 
autorização Oauth2. 
 spring-boot-starter-data-jpa: Como o próprio nome diz, usaremos essa dependência 
para trabalhar com nossa camada de persistência. Ela ja fornece tudo que precisamos 
como por exemplo: spring-data-jpa, spring-orm e o hibernate. 
 mysql-connector-java: Aqui temos o driver JDBC do MySql(Banco de Dados que vamos 
utilizar). 
 
Antes de implementarmos as classes do projeto, vamos criar os arquivos de configuração, 
neles serão definidas algumas propriedades importantes que serão utilizadas na nossa 
aplicação. Vamos começar criando nosso bootstrap.yml, salve esse arquivo em delivery-auth-
server/src/main/resouces. 
 
spring: 
 application: 
 name: delivery-auth-server 
 cloud: 
 config: 
 uri: http://localhost:9090 
 
Nele definimos a propriedade spring.cloud.config.uri com o host do Config Server onde a 
aplicação irá buscar as propriedades de configuração durante a inicialização com base no valor 
de spring.application.name como vimos na parte 3. 
Após criar o bootstrap.yml vamos criar o arquivo de configuração no repositório do Config 
Server assim como vimos na parte 2. Crie o arquivo delivery-auth-server.yml com o conteúdo 
abaixo: 
https://coderef.com.br/arquitetura-de-microservices-com-spring-cloud-e-spring-boot-parte-3-b84b3dce13a0
server: 
 port: 9092 
 
eureka: 
 instance: 
 hostname: localhost 
 port: 9091 
 client: 
 registerWithEureka: true 
 fetchRegistry: false 
 serviceUrl: 
 defaultZone: http://${eureka.instance.hostname}:${eureka.instance.port}/eureka/ 
 server: 
 wait-time-in-ms-when-sync-empty: 3000 
 
security: 
 oauth2: 
 client: 
 access-token-validity-seconds: 1800 
 authorized-grant-types: password,refresh_token 
 client-id: coderef 
 client-secret: $2a$10$p9Pk0fQNAQSesI4vuvKA0OZanDD2 
 resource-ids: resources 
 scope: read,write 
 
spring: 
 datasource: 
 data: classpath:/sql/data.sql 
 driver-class-name: com.mysql.jdbc.Driver 
 password: '1234' 
 platform: mysql 
 schema: classpath:/sql/schema.sql 
 url: 
jdbc:mysql://localhost/oauth?verifyServerCertificate=false&useSSL=false&requireSSL=false 
 username: root 
 jpa: 
 database-platform: org.hibernate.dialect.MySQLDialect 
 generate-ddl: false 
 hibernate: 
 ddl-auto: none 
 show-sql: true 
 
Como podemos perceber existem algumas configurações que ainda não conhecemos, primeiro 
vamos ver as relacionadas com a parte de segurança depois vamos conferir as configurações 
de persistência: 
Configurações de segurança: 
 
 security.oauth2.client.access-token-validity-seconds: Tempo, em segundos, de 
duração do token de acesso. 
 security.oauth2.client.authorized-grant-types: Qual o tipo do pedido de concessão de 
acesso. Se o Client vai solicitar um token utilizando usuário e senha ou se vai renovar 
um token já existente. 
 security.oauth2.client.client-id: Identificador único que será usado pelo Client para 
solicitar concessão de acesso. 
 security.oauth2.client.client-secret: Uma senha usada em conjunto com o client-id 
como autenticação básica do client que está tentando obter um token de acesso. 
 security.oauth2.client.resource-ids: Identificador dos recursos disponíveis, se 
especificado aqui também deve ser especificado no servidor de recursos. 
 security.oauth2.client.scope: Os escopos que o Client terá acesso. 
Configurações para o JPA: 
 spring.datasource.data: Um arquivo .sql que será executado na inicialização da 
aplicação, ele será executado após a propriedade schema. 
 spring.datasource.driver-class-name: Classe do driver JDBC. 
 spring.datasource.password: Senha de acesso ao banco de dados. 
 spring.datasource.platform: Plataforma de persistência. 
 spring.datasource.schema: Arquivo com a estrutura do banco de dados. Como as 
classes que mapeiam os dados de segurança então nas bibliotecas do Spring, elas não 
são criadas automaticamente pelo JPA. 
 spring.datasource.url: Url de acesso ao banco de dados. 
 spring.datasource.username: Usuário de acesso ao banco de dados. 
 spring.datasource.jpa.database-platform: Classe que possui a implementação que 
possibilita a geração SQL para a plataforma de persistência especificada, para que todo 
o SQL gerado pelo JPA seja compatível com o banco de dados escolhido. 
 spring.datasource.jpa.generate-ddl: Informar se durante a inicialização será 
necessário gerar as estruturas do banco de dados com base nas anotações JPA. 
 spring.datasource.jpa.hibernate.ddl-auto: Caso a propriedade generate-ddl esteja 
marcada como true, aqui deverá ser informada qual a política de geração do schema 
do banco de dados. 
 spring.datasource.jpa.hibernate.show-sql: Se habilitada, será gerado um log com o sql 
gerado pelo JPA. Use somente em Homologação. 
 
Agora temos 3 arquivos de configuração no repositório: 
 
Bom, retornando a nossa aplicação. Se você percebeu durante nossa análise do arquivo de 
configuração delivery-auth-server.yml nós configuramos as propriedades 
spring.datasource.data e spring.datasource.schema que fazem referência a um arquivo .sql. 
para hospedar esses dois arquivos vamos criar uma pasta sql no mesmo lugar onde colocamos 
o arquivo bootstrap.yml. Primeiro vamos criar o arquivo que conterá a estrutura do nosso 
banco de dados de autenticação, além de possuir algumas tabelas importantes que serão 
utilizadas pelo Spring para gerenciar a sessão do usuário logado. Crie um arquivo schema.sql 
com o seguinte conteúdo: 
 
CREATE TABLE IF NOT EXISTS user ( 
 username VARCHAR(50) NOT NULL PRIMARY KEY, 
 email VARCHAR(50), 
 password VARCHAR(500), 
 activated BOOLEAN DEFAULT FALSE, 
 activationkey VARCHAR(50) DEFAULT NULL, 
 resetpasswordkey VARCHAR(50) DEFAULT NULL 
); 
 
CREATE TABLE IF NOT EXISTS authority ( 
 name VARCHAR(50) NOT NULL PRIMARY KEY 
); 
 
CREATE TABLE IF NOT EXISTS user_authority ( 
 username VARCHAR(50) NOT NULL, 
 authority VARCHAR(50) NOT NULL, 
 FOREIGN KEY (username) REFERENCES user (username), 
 FOREIGN KEY (authority) REFERENCES authority (name), 
 UNIQUE INDEX user_authority_idx_1 (username, authority) 
); 
 
CREATE TABLE IF NOT EXISTS oauth_access_token ( 
 token_id VARCHAR(256) DEFAULT NULL, 
 token BLOB, 
 authentication_id VARCHAR(256) DEFAULT NULL, 
 user_name VARCHAR(256) DEFAULT NULL, 
 client_id VARCHAR(256) DEFAULT NULL, 
 authentication BLOB, 
 refresh_token VARCHAR(256) DEFAULT NULL 
); 
 
CREATE TABLE IF NOT EXISTS oauth_refresh_token ( 
 token_id VARCHAR(256) DEFAULT NULL, 
 token BLOB, 
 authentication BLOB 
); 
 
CREATE TABLE IF NOT EXISTS oauth_client_details ( 
 client_id VARCHAR(255) PRIMARY KEY, 
 resource_ids VARCHAR(255), 
 client_secret VARCHAR(255), 
 scope VARCHAR(255), 
 authorized_grant_types VARCHAR(255), 
 web_server_redirect_uri VARCHAR(255), 
 authorities VARCHAR(255), 
 access_token_validity INTEGER, 
 refresh_token_validity INTEGER, 
 additional_information VARCHAR(4096), 
 autoapprove VARCHAR(255) 
); 
 
Agora vamos criar o arquivo que ira apagar os Clients salvos e inserir os dados do primeiro 
usuário da aplicação, o administrador. Criaremos um arquivo com o nome data.sql com o 
seguinte conteúdo: 
 
DELETE FROM oauth_client_details; 
 
INSERT INTO user (username, email, password, activated) 
SELECT * FROM (SELECT 'admin', 'admin@admin.com', 
'$2a$10$r0RFDmpneBVryx.ihHK9gu6FFJQi4nTxQUqzdSTvrPpaKZMxigqpy', true) AS tmp 
WHERE NOT EXISTS ( 
 SELECT username FROM user WHERE username = 'admin' 
) LIMIT 1; 
 
INSERT INTO authority (name) 
SELECT * FROM (SELECT 'ROLE_USER') AS tmp 
WHERE NOT EXISTS ( 
 SELECT name FROM authority WHERE name = 'ROLE_USER' 
) LIMIT 1; 
 
INSERT INTO authority (name) 
SELECT * FROM (SELECT 'ROLE_ADMIN') AS tmp 
WHERE NOT EXISTS ( 
 SELECT name FROM authority WHERE name = 'ROLE_ADMIN' 
) LIMIT 1; 
 
INSERT INTO user_authority (username, authority)SELECT * FROM (SELECT 'admin', 'ROLE_USER') AS tmp 
WHERE NOT EXISTS ( 
 SELECT username, authority FROM user_authority WHERE username = 'admin' and authority 
= 'ROLE_USER' 
) LIMIT 1; 
 
INSERT INTO user_authority (username, authority) 
SELECT * FROM (SELECT 'admin', 'ROLE_ADMIN') AS tmp 
WHERE NOT EXISTS ( 
 SELECT username, authority FROM user_authority WHERE username = 'admin' and authority 
= 'ROLE_ADMIN' 
) LIMIT 1; 
 
Após criar esses dois arquivos temos a seguinte estrutura: 
 
 
 
Considerando que você já tenha importado o projeto na sua IDE vamos criar os seguintes 
pacotes e classes: 
 
 
 
Agora vamos implementar cada classe e ver seu conteúdo. 
AuthorizationServerConfiguration 
package com.coderef.delivery.config; 
 
import javax.sql.DataSource; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.beans.factory.annotation.Qualifier; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.security.authentication.AuthenticationManager; 
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; 
import org.springframework.security.crypto.password.PasswordEncoder; 
import 
org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfig
urer; 
import 
org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServer
ConfigurerAdapter; 
import 
org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizatio
nServer; 
import 
org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerE
ndpointsConfigurer; 
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore; 
 
import com.coderef.delivery.domain.Authorities; 
 
 
@Configuration 
@EnableAuthorizationServer 
public class AuthorizationServerConfiguration extends 
 AuthorizationServerConfigurerAdapter { 
 
 private static PasswordEncoder encoder; 
 
 @Value("${security.oauth2.client.client-id}") 
 private String clientId; 
 
 @Value("${security.oauth2.client.authorized-grant-types}") 
 private String[] authorizedGrantTypes; 
 
 @Value("${security.oauth2.client.resource-ids}") 
 private String resourceIds; 
 
 @Value("${security.oauth2.client.scope}") 
 private String[] scopes; 
 
 @Value("${security.oauth2.client.client-secret}") 
 private String secret; 
 
 @Value("${security.oauth2.client.access-token-validity-seconds}") 
 private Integer accessTokenValiditySeconds; 
 
 @Autowired 
 DataSource dataSource; 
 
 @Autowired 
 @Qualifier("authenticationManagerBean") 
 private AuthenticationManager authenticationManager; 
 
 @Bean 
 public JdbcTokenStore tokenStore() { 
 return new JdbcTokenStore(dataSource); 
 } 
 
 @Override 
 public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
 throws Exception { 
 endpoints.authenticationManager(this.authenticationManager).tokenStore(tokenStore()); 
 } 
 
 @Override 
 public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
 clients.jdbc(dataSource) 
 .withClient(clientId) 
 .authorizedGrantTypes(authorizedGrantTypes) 
 .authorities(Authorities.names()) 
 .resourceIds(resourceIds) 
 .scopes(scopes) 
 .secret(secret) 
 .accessTokenValiditySeconds(accessTokenValiditySeconds); 
 } 
 
 @Bean 
 public PasswordEncoder passwordEncoder() { 
 if (encoder == null) { 
 encoder = new BCryptPasswordEncoder(); 
 } 
 return encoder; 
 } 
} 
 
Nessa classe vimos a anotação @Configuration que diz ao Spring que essa classe é uma classe 
de configuração e ela deverá ser instanciada na inicialização da aplicação. A anotação 
@EnableAuthorizationServer que habilita o AuthorizationServer, disponibilizando um 
AuthorizationEndpoint e um TokenEndpoint. Vimos também que injetamos nossas 
propriedades que definimos anteriormente. Temos dois métodos configure o primeiro define 
o gerenciador de autenticação do AuthorizationEndpoint e o segundo registra um Client, 
segundo as configurações que definimos. 
CorsFilterConfiguration 
 
package com.coderef.delivery.config; 
 
import org.springframework.boot.web.servlet.FilterRegistrationBean; 
import org.springframework.context.annotation.Bean; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.core.Ordered; 
import org.springframework.web.cors.CorsConfiguration; 
import org.springframework.web.cors.UrlBasedCorsConfigurationSource; 
import org.springframework.web.filter.CorsFilter; 
 
@Configuration 
public class CorsFilterConfiguration { 
 
 @Bean 
 public FilterRegistrationBean corsFilter() { 
 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); 
 CorsConfiguration config = new CorsConfiguration(); 
 config.setAllowCredentials(true); 
 config.addAllowedOrigin("*"); 
 config.addAllowedHeader("*"); 
 config.addAllowedMethod("*"); 
 source.registerCorsConfiguration("/**", config); 
 FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source)); 
 bean.setOrder(Ordered.HIGHEST_PRECEDENCE); 
 return bean; 
 } 
 
} 
 
Esse Filter será invocado no inicio de uma requisição ao Servidor de autorização, ele permite 
que uma requisição chegue ao Servidor independente das crendenciais, origin, header e 
method. 
ResourceServerConfiguration 
 
package com.coderef.delivery.config; 
 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.http.HttpMethod; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import 
org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceSer
ver; 
import 
org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConf
igurerAdapter; 
import 
org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurit
yConfigurer; 
 
 
@Configuration 
@EnableResourceServer 
public class ResourceServerConfiguration extends 
 ResourceServerConfigurerAdapter { 
 
 @Value("${security.oauth2.client.resource-ids}") 
 private String RESOURCE_ID; 
 
 @Override 
 public void configure(ResourceServerSecurityConfigurer resources) { 
 resources.resourceId(RESOURCE_ID); 
 } 
 
 @Override 
 public void configure(HttpSecurity http) throws Exception { 
 http.requestMatchers() 
 .antMatchers("/**") 
 .and() 
 .authorizeRequests() 
 .anyRequest() 
 .authenticated() 
 .antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')") 
 .antMatchers(HttpMethod.OPTIONS, "/**").access("#oauth2.hasScope('read')") 
 .antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')") 
 .antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')") 
 .antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')") 
 .antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')"); 
 } 
} 
 
Aqui definimos a anotação @EnableResourceServer que habilita um FilterSpring Security que 
autentica as requisições com base no token OAuth2 recebido. Temos um método configure 
que restringe as requisições com base nos escopos disponíveis. 
WebSecurityConfig 
 
package com.coderef.delivery.config; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.boot.autoconfigure.security.SecurityProperties; 
import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration; 
import org.springframework.core.annotation.Order; 
import org.springframework.security.authentication.AuthenticationManager; 
import 
org.springframework.security.config.annotation.authentication.builders.AuthenticationManag
erBuilder; 
import org.springframework.security.config.annotation.web.builders.WebSecurity; 
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; 
import 
org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAda
pter; 
import org.springframework.security.crypto.password.PasswordEncoder; 
 
import com.coderef.delivery.service.UserDetailsService; 
 
@Configuration 
@EnableWebSecurity 
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 
 
 @Autowired 
 private UserDetailsService userDetailsService; 
 
 @Autowired 
 PasswordEncoder passwordEncoder; 
 
 @Override 
 protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
 auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); 
 } 
 
 @Override 
 @Bean 
 public AuthenticationManager authenticationManagerBean() throws Exception { 
 return super.authenticationManagerBean(); 
 } 
 
 @Override 
 public void configure(WebSecurity web) throws Exception { 
 web.ignoring().antMatchers("/oauth/register"); 
 } 
} 
 
O Spring já possui uma classe interna anotada com @EnableWebSecurity para sobrescrever as 
configurações dessa classe anotamos a nossa com a mesma anotação e colocamos também a 
anotação @Order com a propriedade ACCESS_OVERRIDER_ORDER. Definimos também dois 
métodos configure um responsável pela codificação da senha que será informada pelo usuário 
a Aplicação Client e outro informando ao Spring Security que torne o endpoint 
/oauth/register público. 
 
AuthController 
 
package com.coderef.delivery.controller; 
 
import java.security.Principal; 
 
import org.springframework.web.bind.annotation.RequestMapping; 
import org.springframework.web.bind.annotation.RestController; 
 
@RestController 
@RequestMapping("/") 
public class AuthController { 
 
 @RequestMapping("/user") 
 public Principal getCurrentLoggedInUser(Principal user) { 
 return user; 
 } 
} 
 
Aqui implementamos uma Controller muito importante, pois ela será consultada sempre pelo 
Client para validar se o token informado ainda é válido, caso não tenha acesso ou o token 
informado seja inválido uma mensagem de não autorizado é retornada. 
Authorities 
 
package com.coderef.delivery.domain; 
 
public enum Authorities { 
 
 ROLE_USER, 
 ROLE_ADMIN; 
 
 public static String[] names() { 
 String[] names = new String[values().length]; 
 for(int index = 0; index < values().length; index++) { 
 names[index] = values()[index].name(); 
 } 
 
 return names; 
 } 
} 
 
Nesse ENUM colocamos as duas regras de acesso que estamos utilizando na aplicação. 
 
Authority 
 
package com.coderef.delivery.model; 
 
import java.io.Serializable; 
 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.validation.constraints.NotNull; 
import javax.validation.constraints.Size; 
 
@Entity 
public class Authority implements Serializable { 
 
 private static final long serialVersionUID = 1L; 
 
 @Id 
 @NotNull 
 @Size(min = 0, max = 50) 
 private String name; 
 
 public String getName() { 
 return name; 
 } 
 
 public void setName(String name) { 
 this.name = name; 
 } 
} 
 
Aqui implementamos a classe que representa nossa tabela de regras no banco de dados. 
User 
 
package com.coderef.delivery.model; 
 
 
import java.io.Serializable; 
import java.util.Set; 
 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.JoinTable; 
import javax.persistence.ManyToMany; 
import javax.validation.constraints.Size; 
 
import org.hibernate.validator.constraints.Email; 
 
@Entity 
public class User implements Serializable { 
 
 private static final long serialVersionUID = 1L; 
 
 @Id 
 @Column(updatable = false, nullable = false) 
 private String username; 
 
 @Size(min = 0, max = 500) 
 private String password; 
 
 @Email 
 @Size(min = 0, max = 50) 
 private String email; 
 
 private boolean activated; 
 
 @Size(min = 0, max = 100) 
 @Column(name = "activationkey") 
 private String activationKey; 
 
 @Size(min = 0, max = 100) 
 @Column(name = "resetpasswordkey") 
 private String resetPasswordKey; 
 
 @ManyToMany 
 @JoinTable( 
 name = "user_authority", 
 joinColumns = @JoinColumn(name = "username"), 
 inverseJoinColumns = @JoinColumn(name = "authority")) 
 private Set<Authority> authorities; 
 
 public User() { 
 } 
 
 public User(String username, String password, String email, 
 boolean activated, String firstName, String lastName, 
 String activationKey, String resetPasswordKey, 
 Set<Authority> authorities) { 
 this.username = username; 
 this.password = password; 
 this.email = email; 
 this.activated = activated; 
 this.activationKey = activationKey; 
 this.resetPasswordKey = resetPasswordKey; 
 this.authorities = authorities; 
 } 
 
 public String getUsername() { 
 return username; 
 } 
 
 public void setUsername(String username) { 
 this.username = username; 
 } 
 
 public String getPassword() { 
 return password; 
 } 
 
 public void setPassword(String password) { 
 this.password = password; 
 } 
 
 public String getEmail() { 
 return email; 
 } 
 
 public void setEmail(String email) { 
 this.email = email; 
 } 
 
 public boolean isActivated() { 
 return activated; 
 } 
 
 public void setActivated(boolean activated) { 
 this.activated = activated; 
 } 
 
 public String getActivationKey() { 
 return activationKey; 
 } 
 
 public void setActivationKey(String activationKey) { 
 this.activationKey = activationKey; 
 } 
 
 public String getResetPasswordKey() { 
 return resetPasswordKey; 
 } 
 
 public void setResetPasswordKey(String resetPasswordKey) { 
 this.resetPasswordKey = resetPasswordKey; 
 } 
 
 public Set<Authority> getAuthorities() { 
 return authorities; 
 } 
 
 public void setAuthorities(Set<Authority> authorities) { 
 this.authorities = authorities; 
 } 
} 
 
Essa classe será a representação da tabela de usuários que criamos anteriormente via SQL 
onde ficarão salvas as credenciais dos usuários. 
AuthorityRepository 
 
package com.coderef.delivery.repository; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
 
import com.coderef.delivery.model.Authority; 
 
public interface AuthorityRepository extends JpaRepository<Authority, String>{ 
 
 Authority findByName(String name); 
 
} 
 
Esse repository será responsável pelas consultas das regras do usuário no banco de dados. 
UserRepository 
 
package com.coderef.delivery.repository; 
 
import java.util.Optional; 
 
import org.springframework.data.jpa.repository.JpaRepository; 
import org.springframework.data.jpa.repository.Query; 
import org.springframework.data.repository.query.Param; 
 
import com.coderef.delivery.model.User; 
 
public interface UserRepository extends JpaRepository<User, String> { 
 
 @Query("SELECT u FROM User u WHERE LOWER(u.username) = 
LOWER(:username)") 
 Optional<User> findByUsername(@Param("username") String username); 
 
} 
 
Aqui definimos as consultas referentes aos usuários. 
 
UserDetailsService 
 
package com.coderef.delivery.service; 
 
import java.util.ArrayList;import java.util.Collection; 
import java.util.Optional; 
 
import javax.transaction.Transactional; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.security.core.GrantedAuthority; 
import org.springframework.security.core.authority.SimpleGrantedAuthority; 
import org.springframework.security.core.userdetails.UserDetails; 
import org.springframework.security.core.userdetails.UsernameNotFoundException; 
import org.springframework.stereotype.Service; 
 
import com.coderef.delivery.model.Authority; 
import com.coderef.delivery.model.User; 
import com.coderef.delivery.repository.UserRepository; 
 
@Service 
@Transactional 
public class UserDetailsService implements 
org.springframework.security.core.userdetails.UserDetailsService{ 
 
 UserRepository userRepository; 
 
 @Override 
 public UserDetails loadUserByUsername(String username) throws 
UsernameNotFoundException { 
 return userRepository.findByUsername(username) 
 .map(user -> 
new org.springframework.security.core.userdetails.User(user.getUsername(), 
user.getPassword(), getGrantedAuthorities(user))) 
 
 .orElseThrow(() -> new UsernameNotFoundException("User "+username+" Not 
found")); 
 } 
 
 @Autowired 
 public void setUserRepository(UserRepository userRepository) { 
 this.userRepository = userRepository; 
 } 
 
 private Collection<GrantedAuthority> getGrantedAuthorities(User user){ 
 Collection<GrantedAuthority> grantedAuthorities = new ArrayList<>(); 
 for (Authority authority : user.getAuthorities()) { 
 GrantedAuthority grantedAuthority = new 
SimpleGrantedAuthority(authority.getName()); 
 grantedAuthorities.add(grantedAuthority); 
 } 
 
 return grantedAuthorities; 
 } 
} 
 
Aqui implementamos um @Service. O Spring Security fornece uma interface utilizada 
internamente chamada UserDetailsService que precisamos implementar quando queremos 
alterar o comportamento do UserDetail utilizado. 
DeliveryAuthServerApplication 
 
package com.coderef.delivery; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 
 
@SpringBootApplication 
@EnableEurekaClient 
public class DeliveryAuthServerApplication { 
 
 public static void main(String[] args) { 
 SpringApplication.run(DeliveryAuthServerApplication.class, args); 
 } 
} 
 
Por último implementamos nossa classe principal, que será responsável por inicializar nossa 
aplicação Spring Boot como vimos na parte 2. Aqui temos uma anotação nova a 
@EnableEurekaClient. Essa anotação torna nossa aplicação visível ao Eureka Server com base 
nas configurações que definimos no application.yml . 
Subindo a aplicação 
 
Agora chegou a hora subir o nosso Authorization Server para saber se tudo está funcionando 
corretamente. Antes de inciar nosso servidor de autorização será necessário subir o Config 
Server e depois o Eureka Server. Quando os dois estiverem online vamos executar a classe 
DeliveryAuthServerApplication.java. Finalizado, acesse o endereço http://localhost:9091/ 
nosso servidor vai aparecer listado no Eureka Server: 
 
https://coderef.com.br/arquitetura-de-microservices-com-spring-cloud-e-spring-boot-parte-3-b84b3dce13a0
 
Solicitando um Token de Acesso 
 
O framework Oauth2 define um padrão para a solicitação do token e um a resposta. Para 
solicitar um token o Client deverá estar registrado no servidor de autorização e deve enviar o 
client-id e o secret que configuramos no application.yml codificado no formato Base 64, 
respeitando o padrão client-id:secret. Para fazer essa requisição teremos que enviar os 
seguintes dados: 
 
 Authorization: 
Basic Y29kZXJlZjokMmEkMTAkcDlQazBmUU5BUVNlc0k0dnV2S0EwT1phbkREMg== 
(verifique a imagem abaixo). 
 URL: 
http://localhost:9092/oauth/token?grant_type=password&username=admin&passwo
rd=123456 
 Method: POST. 
 Content-Type: application/json. 
 
Para facilitar vamos utilizar o Postman, uma ferramenta poderosa com uma interface simples e 
fácil de manipular. Após instalar e abrir o Postman, os dados acima serão inseridos, tal como 
abaixo: 
 
 
 
http://localhost:9092/oauth/token?grant_type=password&username=admin&password=123456
http://localhost:9092/oauth/token?grant_type=password&username=admin&password=123456
Após clicar em Send um json será recebido: 
 
 
 
O Oauth2 tem um padrão de resposta, vou detalhar abaixo o que significa cada propriedade do 
JSON: 
 
 access_token: token de acesso que o Client irá utilizar para solicitar acesso aos 
recursos protegidos. 
 token_type: O tipo de token que o Client deverá enviar no Header das requisições para 
os recursos. 
 refresh_token: A cada interação entre client e o resource server esse token pode ser 
utilizado para renovar o token sendo utilizado atualmente. Isso evita que o token 
expire enquanto o usuário ainda está interagindo com o site. 
 expire_in: Tempo de vida do token, em segundos. 
 scope: Escopo de permissão que o token terá para acessar os recursos. 
 
 
Microserviço de Pedido 
 
Olá pessoal, enfim voltamos com nossas publicações. Dando continuação a nossa sequencia de 
stories sobre microservice, nessa storie vamos criar nosso microserviço de pedido, que será 
responsável por criar, listar e apagar um pedido criado. Veremos também como integrar esse 
microserviço ao servidor de autorização criado na storie anterior, então bora lá. 
Gerando o Projeto 
 
Acesse o site do Spring Initializr e preencha as configurações como na imagem. Escolhemos 
qual vai ser o gerenciador de dependências (Maven), a linguagem de programação (Java), as 
dependências necessárias para o projeto (Cloud OAuth2, Actuator, Config Client e Eureka 
Discovery, JPA, MySql, web)e configuramos os metadados do Maven. Por fim geramos o 
projeto clicando em Generate Project, Ctrl + Enter ou Command + Enter. (Atenção para a 
versão do Spring, estamos usando a 1.5 nesse projeto) 
 
 
 
Vamos descompactar o projeto na pasta delivery, assim como fizemos antes. 
 
 
Implementando a aplicação 
 
Como sempre fazemos, iremos abrir o pom.xml e ver as dependências geradas, a maioria já 
conhecemos, mas vou frizar uma: 
 
<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd"> 
 <modelVersion>4.0.0</modelVersion> 
 <groupId>com.coderef</groupId> 
 <artifactId>delivery-order-service</artifactId> 
 <version>0.0.1-SNAPSHOT</version> 
 <packaging>jar</packaging> 
 <name>delivery-order-service</name> 
 <description>Delivery order service</description> 
 <parent> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-parent</artifactId> 
 <version>1.5.9.RELEASE</version> 
 <relativePath/> <!-- lookup parent from repository --> 
 </parent> 
 <properties> 
 <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
 <project.reporting.outputEncoding>UTF-
8</project.reporting.outputEncoding> 
 <java.version>1.8</java.version> 
 <spring-cloud.version>Edgware.RELEASE</spring-cloud.version> 
 </properties> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-actuator</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-eureka</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-oauth2</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-data-jpa</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-web</artifactId> 
 </dependency> 
 <dependency><groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-starter-config</artifactId> 
 </dependency> 
 <dependency> 
 <groupId>mysql</groupId> 
 <artifactId>mysql-connector-java</artifactId> 
 <scope>runtime</scope> 
 </dependency> 
 <dependency> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-starter-test</artifactId> 
 <scope>test</scope> 
 </dependency> 
 </dependencies> 
 <dependencyManagement> 
 <dependencies> 
 <dependency> 
 <groupId>org.springframework.cloud</groupId> 
 <artifactId>spring-cloud-dependencies</artifactId> 
 <version>${spring-cloud.version}</version> 
 <type>pom</type> 
 <scope>import</scope> 
 </dependency> 
 </dependencies> 
 </dependencyManagement> 
 <build> 
 <plugins> 
 <plugin> 
 <groupId>org.springframework.boot</groupId> 
 <artifactId>spring-boot-maven-plugin</artifactId> 
 </plugin> 
 </plugins> 
 </build> 
</project> 
 
 spring-cloud-starter-oauth2: Colocamos novamente essa dependência e iremos 
colocá-la novamente em projetos futuros, pois ela será necessária para 
implementarmos a conexão com o authorization server. 
 
Vamos criar os arquivos de configuração, neles serão definidas algumas propriedades 
importantes que serão utilizadas na nossa aplicação. Vamos começar criando nosso 
bootstrap.yml, salve esse arquivo em delivery-order-service/src/main/resouces. 
 
spring: 
 application: 
 name: delivery-order-service 
 cloud: 
 config: 
 uri: http://localhost:9090 
Como vimos na parte 3, nossa aplicação terá que buscar as configurações no Config Server, 
para isso especificamos novamente a propriedade spring.cloud.config.uri . Após criado nosso 
bootstrap.yml vamos criar nosso arquivo de configuração no repositório que o Config Server 
está usando tal, como vimos na parte 2, crie delivery-order-service.yml com: 
 
server: 
 port: 9093 
 
eureka: 
 instance: 
 hostname: localhost 
 port: 9091 
 client: 
 registerWithEureka: true 
 fetchRegistry: false 
 serviceUrl: 
 defaultZone: http://${eureka.instance.hostname}:${eureka.instance.port}/eureka/ 
 server: 
 wait-time-in-ms-when-sync-empty: 3000 
 
spring: 
 datasource: 
 driver-class-name: com.mysql.jdbc.Driver 
 password: '1234' 
 platform: mysql 
 url: jdbc:mysql://localhost/delivery-
order?verifyServerCertificate=false&useSSL=false&requireSSL=false 
 username: root 
 jpa: 
 database-platform: org.hibernate.dialect.MySQLDialect 
 generate-ddl: false 
 hibernate: 
 ddl-auto: create 
 show-sql: true 
 
authserver: 
 hostname: http://localhost:9092 
security: 
 oauth2: 
 resource: 
 userInfoUri: ${authserver.hostname}/user 
 
Vamos repassar algumas configurações que são novidades para nós até o momento: 
 
 authserver.hostname: Parâmetro apenas para ser reutilizado em userInfoUri. 
 security.oauth2.resource.userInfoUri: Url que o spring irá utilizar para validadar o 
token recebido na requisição. 
 
 
Agora temos 4 arquivos no repositório de configuração contando com o arquivo de exemplo: 
 
 
 
Considerando que você já esteja com o projeto aberto na sua IDE favorita, vamos criar a 
seguinte estrutura de pacotes com as seguintes classes: 
 
 
Desconsidere os diretórios .idea e .mvn . 
Agora vamos implementar cada classe e ver seu conteúdo. 
 
Order 
 
package com.coderef.delivery.model; 
 
import org.hibernate.validator.constraints.NotEmpty; 
 
import javax.persistence.*; 
import javax.validation.constraints.NotNull; 
import java.io.Serializable; 
 
@Entity 
@Table(name = "`order`") 
public class Order implements Serializable { 
 
 private static final long serialVersionUID = 1L; 
 
 @Id 
 @GeneratedValue(strategy = GenerationType.AUTO) 
 private Integer id; 
 
 @NotEmpty(message = "Product required") 
 private String product; 
 
 @NotNull(message = "Price required") 
 private Double price; 
 
 public Integer getId() { 
 return id; 
 } 
 
 public void setId(Integer id) { 
 this.id = id; 
 } 
 
 public String getProduct() { 
 return product; 
 } 
 
 public void setProduct(String product) { 
 this.product = product; 
 } 
 
 public Double getPrice() { 
 return price; 
 } 
 
 public void setPrice(Double price) { 
 this.price = price; 
 } 
} 
Entidade que representará nosso pedido, iremos utilizar as anotações @NotEmpty e @NotNull 
na classe OrderService para validar as propriedades do nosso pedido. 
OrderRepository 
 
Essa interface será responsável por fazer a “ponte” entre nossa camada de negócio e o banco 
de dados, podemos ver que ela está estendendo a Interface CrudRepository ela é uma 
interface do Spring Data JPA que fornece uma funcionalidade CRUD completa para a entidade 
que está sendo gerenciada. 
 
package com.coderef.delivery.repository; 
 
import com.coderef.delivery.model.Order; 
import org.springframework.data.repository.CrudRepository; 
 
public interface OrderRepository extends CrudRepository<Order, Integer> { 
} 
OrderService 
 
Aqui estará nosso @Service nele poderíamos implementar ou chamar um fluxo de negócio 
relativo a nossa entidade. 
 
package com.coderef.delivery.service; 
 
import com.coderef.delivery.model.Order; 
import com.coderef.delivery.repository.OrderRepository; 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.stereotype.Service; 
import org.springframework.validation.annotation.Validated; 
 
@Service 
public class OrderService { 
 
 @Autowired 
 private OrderRepository orderRepository; 
 
 public Order save(@Validated Order order) { 
 return orderRepository.save(order); 
 } 
 
 public Order findById(Integer id){ 
 return orderRepository.findOne(id); 
 } 
 
 public Iterable<Order> findAll(){ 
 return orderRepository.findAll(); 
 } 
 
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
 public void delete(Integer id) { 
 orderRepository.delete(id); 
 } 
} 
ExceptionHandlerController 
 
Essa controller será responsável por interceptar e tratar as exceções lançadas pela nossa 
aplicação: 
 
package com.coderef.delivery.exception; 
 
import org.springframework.http.HttpStatus; 
import org.springframework.http.ResponseEntity; 
import org.springframework.web.bind.annotation.ControllerAdvice; 
import org.springframework.web.bind.annotation.ExceptionHandler; 
 
import javax.validation.ConstraintViolationException; 
import java.util.stream.Collectors; 
 
@ControllerAdvice 
public class ExceptionHandlerController { 
 
 @ExceptionHandler(ConstraintViolationException.class) 
 public ResponseEntity<?> validateError(ConstraintViolationException ex){ 
 return ResponseEntity.badRequest().body(ex.getConstraintViolations().stream().map(cv -> 
cv.getMessage()).collect(Collectors.toList())); 
 } 
 
 @ExceptionHandler(Exception.class) 
 public ResponseEntity<?> otherErrors(Exception ex){ 
 return 
ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(ex.getMessage()); 
 } 
} 
SecurityConfiguration 
 
Essa classe vai ativar nosso Resource Server e mapear cada role para seu method especifico: 
 
package com.coderef.delivery.security; 
 
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; 
import org.springframework.context.annotation.Configuration; 
import org.springframework.http.HttpMethod; 
import org.springframework.security.config.annotation.web.builders.HttpSecurity; 
import 
org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceSer
ver; 
import 
org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConf
igurerAdapter; 
import 
org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurit
yConfigurer; 
 
 
@Configuration 
@EnableResourceServerpublic class SecurityConfiguration extends ResourceServerConfigurerAdapter { 
 
 private final static String resourceId = "resources"; 
 
 @Override 
 public void configure(HttpSecurity http) throws Exception { 
 http.requestMatchers() 
 .antMatchers("/**") 
 .and() 
 .authorizeRequests() 
 .anyRequest() 
 .authenticated() 
 .antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')") 
 .antMatchers(HttpMethod.OPTIONS, "/**").access("#oauth2.hasScope('read')") 
 .antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')") 
 .antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')") 
 .antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')") 
 .antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')"); 
 } 
 
 @Override 
 public void configure(ResourceServerSecurityConfigurer resources){ 
 resources.resourceId(resourceId); 
 } 
} 
DeliveryOrderServiceApplication 
 
Por último implementamos nossa classe principal, que será responsável por inicializar nossa 
aplicação Spring Boot como vimos na parte 2. Aqui temos uma anotação nova a 
@EnableEurekaClient. Essa anotação torna nossa aplicação visível ao Eureka Server com base 
nas configurações que definimos no application.yml . 
 
package com.coderef.delivery; 
 
import org.springframework.boot.SpringApplication; 
import org.springframework.boot.autoconfigure.SpringBootApplication; 
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; 
import org.springframework.cloud.netflix.eureka.EnableEurekaClient; 
 
https://coderef.com.br/arquitetura-de-microservices-com-spring-cloud-e-spring-boot-parte-3-b84b3dce13a0
@SpringBootApplication 
@EnableEurekaClient 
public class DeliveryOrderServiceApplication { 
 
 public static void main(String[] args) { 
 SpringApplication.run(DeliveryOrderServiceApplication.class, args); 
 } 
} 
Subindo a aplicação 
 
Agora chegou a hora subir o nosso MicroService, antes de iniciar será necessário subir o Config 
Server, Eureka Server e o Authorization Server. Quando os três estiverem online vamos 
executar a classe DeliveryOrderServiceApplication.java. Finalizado, acesse o endereço 
http://localhost:9091/ nosso servidor vai aparecer listado no Eureka Server: 
 
 
Criando um Pedido 
 
Antes de fazermos a requisição para o nosso MicroService, será necessário solicitarmos um 
token para nosso Authorization Server. Vamos abrir o Postman e criar uma nova requisição: 
 
 
 
http://localhost:9091/%60
https://www.getpostman.com/
 URL: 
http://localhost:9092/oauth/token?grant_type=password&username=admin&passwo
rd=123456 
 Authorization: 
Basic Y29kZXJlZjokMmEkMTAkcDlQazBmUU5BUVNlc0k0dnV2S0EwT1phbkREMg== 
 Method: POST. 
 Content-Type: application/json. 
 
Clique em Send. Uma resposta similar a imagem abaixo será retornada: 
 
 
 
Copiaremos o access_token e o token_type, pois será eles que iremos utilizar na próxima 
requisição. 
Agora que já temos um token vamos criar nosso primeiro pedido. Vamos até o Postman 
novamente e preencher: 
 
 
 
 URL: http://localhost:9093/api/orders 
 Mehod: POST 
 
Clique em Headers e preencha com: 
 
 
 
http://localhost:9092/oauth/token?grant_type=password&username=admin&password=123456
http://localhost:9092/oauth/token?grant_type=password&username=admin&password=123456
http://localhost:9093/api/orders
 Content-Type: application/json. 
 Authorizarion: cole o token_type e o access_token com um espacinho entre os dois. 
 
Clique em body, depois em raw e selecione JSON(application/json), preencha o TextArea com 
um json similar ao conteúdo abaixo: 
 
{ 
 "product": "Apple", 
 "price": "1.25" 
} 
 
Clique em Send, um pedido com id será retornado na requisição representando que o pedido 
foi criado com sucesso. 
 
 
 
Pronto, agora podemos realizar os mesmo passos para os endpoints de busca e apagar, não 
podemos esquecer que alguns possuem parâmetros na requisição e que se não forem 
passados pode ocorrer erro. 
Referências 
http://projects.spring.io/spring-security-oauth/ 
https://tools.ietf.org/pdf/draft-ietf-oauth-v2-31.pdf 
https://docs.spring.io/spring-data/data-
commons/docs/1.6.1.RELEASE/reference/html/repositories.html 
Repositório 
https://github.com/diegosilva13/delivery 
 
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html
https://docs.spring.io/spring-data/data-commons/docs/1.6.1.RELEASE/reference/html/repositories.html

Continue navegando