Primeiras aulas do curso Spring Boot API Rest: Segurança da API, Cache e Monitoramento

Spring Boot API Rest: Segurança da API, Cache e Monitoramento

Paginação e ordenação de recursos - Introdução

Bem-vindos ao segundo treinamento de API REST com Spring Boot. Meu nome é Rodrigo Ferreira e também vou ser o instrutor que vai ministrar este treinamento para vocês.

No primeiro treinamento de Spring Boot, nós saímos com nossa API do fórum da Alura. Conseguimos implementar a parte do cadastro, listagem, exclusão, alteração e detalhes de um tópico. Saímos com a API totalmente funcional. Fizemos os testes pelo Postman, conseguimos listar, cadastrar, fazer todas as operações. Fizemos o cadastro usando validação, seguimos algumas boas práticas do modelo REST, e fizemos a parte de persistência usando o Spring Boot data JPA, para fazer o acesso ao banco de dados.

Porém nossa API ficou um pouco incompleta, faltando recursos importantes, como segurança. Vamos ver justamente essa parte que está faltando neste curso. Vamos aprender a usar o Spring security para proteger nossa aplicação, com autenticação tradicional e depois migrando para utilizar o JSON web token, para fazer a autenticação de maneira stateless, que é a boa prática do mundo REST. Vamos ver também sobre a parte de paginação e ordenação, porque fizemos a listagem, mas ela devolve todos os registros. Vamos ver como limitar, para ordenar os resultados por data, id, título, de maneira crescente ou decrescente.

Também vamos ver sobre cash, como utilizar para melhorar a performance da nossa aplicação em alguns pontos. E também a parte de documentação. Como estamos construindo uma API que vai ser consumida por diversos clientes é importante fornecer uma documentação que explique quais são os endereços da nossa API, os parâmetros, o que é obrigatório, o que é opcional, o que ela devolve, para que assim elas consigam consumir nossa API tranquilamente.

Todos esses recursos vamos ver neste segundo treinamento. Com isso, vamos deixar nossa API mais interessante, pronta para ir para a produção, com essas coisas que ficaram faltando.

Espero que vocês gostem deste treinamento e espero vocês no primeiro vídeo, onde vamos começar com a parte de paginação e coordenação.

Paginação e ordenação de recursos - Paginação

Vamos começar então. No último curso montamos nossa API REST usando Spring Boot. Basicamente, o que fizemos foi o CRUD, cadastro, listagem, alteração e exclusão de tópicos que são postados no fórum da Alura. Basicamente, a principal classe que temos é o TopicosController, e dentro está toda a lógica para fazer o CRUD do recurso de tópico. Temos vários métodos com as operações.

Na aula de hoje, vamos fazer uma mudança no método lista. Esse método devolve todos os tópicos cadastrados no banco de dados. O problema é que no nosso banco de dados só temos três registros, por causa daquele arquivo que está no source/main/Resources, data.sql, que toda vez que rodamos o projeto o Spring executa. Eu tinha deixado fixo para ele sempre cadastrar três tópicos no banco de dados.

Mas imagine que o banco de dados começa a crescer e daqui a pouco tem milhares de registros. Toda vez que esse método lista for chamado, vamos devolver todas essas informações do banco de dados, e com muitos registros pode começar a ficar lento.

Para resolver esse problema, o pessoal usa a ideia de paginação, onde posso controlar. Ao invés de devolver todos os registros, posso devolver de pouco em pouco.

Tínhamos colocado um parâmetro no método lista, que é o nome do curso, onde eu podia filtrar o curso pelo nome. Podemos seguir a mesma ideia. Já tenho que um parâmetro aqui, posso ter outros parâmetros, que no caso serão usados para paginação. Posso ter um parâmetro int pagina, em que vou dizer em que página estou, e também preciso dizer a quantidade, quantos elementos quero por página. Se eu estiver na página um e a quantidade for dez, ele vai trazer os registros do primeiro ao décimo.

Um detalhe importante. Nesse tipo de método, cujo mapeamento é do tipo GET, e temos parâmetros, que são aqueles parâmetros de url, diferente do método POST, que tem um parâmetro, mas está com @RequestBody, ou seja, o parâmetro vem no corpo da requisição, no formato JSON, no método lista esses parâmetros não vêm no corpo da requisição. Eles vêm na própria url, como parâmetros de url.

No geral, para esse tipo de parâmetro é interessante colocar uma anotação, que é o @RequestParam, para avisar ao Spring que é um parâmetro de request. Automaticamente, quando você coloca essa anotação, o Spring considera que o parâmetro é obrigatório. Se chamarmos esse endereço e não passarmos o parâmetro, o Spring vai jogar um erro 400 para o cliente dizendo que tem um parâmetro obrigatório que ele não enviou.

Só que no caso, o nome do curso vai ser opcional. Então, nessa anotação tem um atributo chamado required, que vai ser igual a falso.

Já o int página e int quantidade também vou colocar o request param, para avisar para o Spring que são parâmetros de url, mas vou colocar como obrigatórios. Quero obrigar o cliente que está chamando a API a sempre passar os parâmetros de página e quantidade, para sempre termos a paginação.

Nosso método agora tem três parâmetros, o nome do curso, a página e a quantidade. Na consulta não mudamos nada na implementação. Os parâmetros vão chegar, mas ele vai ignorar. Como faço para pegar esses parâmetros e na hora de chamar o repository, chamar o findall, ou o findbycurso, quero fazer a paginação.

Se você já trabalhou com JPA, ela tem suporte para paginação. Se você usa aquela API do entitymanager, na hora de criar sua query tem métodos para setar o maxResult, firstResult, e aí você consegue controlar qual o primeiro registro e qual o número máximo de registros. Dessa maneira, você faria a paginação com JPA na mão. Mas aqui estamos usando o Spring data. Lembre-se que ele abstrai algumas coisinhas para nós, inclusive paginação.

Se quisermos fazer paginação, o Spring data já tem um esquema pronto para facilitar nossa vida. Para fazer paginação, precisamos criar uma variável do tipo pageable, que é uma classe do Spring data que serve justamente para fazer paginação. Vou criar essa variável, vou chamar de paginação = page.

Para criar essa interface pageable, vou precisar importar. Mas cuidado, tem três opções. A que queremos é a do org.springframework.data. Para criar esse cara, usamos outra classe chamada pageRequest. Nela, tem um método estático chamado of, em que passamos a página e a quantidade. Com isso, ele cria um objeto do tipo pageable.

E aí o que eu faço com esse objeto pageable que está na minha variável paginação? Se você olhar o método findall, você vai ver que na verdade existem vários findall. Dentre eles têm um que recebe um pageable como parâmetro. Então, podemos passar esse paginação como parâmetro para o método, que aí o Spring data automaticamente vai saber que você quer fazer paginação e vai usar os parâmetros página e quantidade para saber qual o primeiro registro e quantos registros ele vai carregar para você. Então, não precisamos implementar nada da consulta com paginação. Ele faz isso automaticamente.

Porém, como você pode observar, deu um erro de compilação. Quando usamos paginação, o retorno do método findall não é mais um list, porque o list apenas traz a lista com todos os tópicos, mas quando usamos paginação é interessante sabermos em qual página estamos no momento, quantas tenho no total, quantos registros tenho. Pense no cliente da nossa API REST. Ele dispara uma requisição usando paginação, mas recebe só os registros daquela paginação. Ele pode ficar meio perdido. Esse tipo de informação é muito útil para o cliente. Por isso o Spring não devolve um list. Ele devolve outra classe chamada page, que tem um generics para você dizer qual é o tipo de classe com que esse page vai trabalhar.

Dentro desse page tem a lista com os registros. Além dela, tem essas informações do número de páginas, qual a página atual, quantos elementos tem no total. Ele já dispara umas consultas para fazer o count de quantos registros tem no banco sozinho.

Isso se entrou no if, se eu não trouxe o parâmetro do nome do curso. Se eu trouxer, nessa consulta também tenho que passar a paginação. Só que esse findbycursonome fomos nós que criamos. Então, vou entrar na classe tópicoRepository. Como é um método que nós definimos, temos que receber como parâmetro um pageable, que vou chamar de paginação. Já vou alterar o retorno, que não é mais list, é page. Vou importar o pageable e o page. Volto para o meu controller.

Só que agora temos um problema. No dto o método converter não recebe um page de tópico. Ele recebe um list. Só que agora, como está usando paginação, vamos ter que alterar o método. Vou entrar no método, e ao invés de receber um list, vou trocar para receber um page. O retorno do método também vai mudar. Não posso devolver mais um list, tem que ser um page.

Dá um problema na implementação, porque estávamos usando o API de strings, e agora não vai mais ficar assim. Só que aquela API de string vem do list do Java, mas agora estou recebendo um page. O pessoal do Spring também pensou nisso, e no tópicos existe um método chamado map, que é o mesmo map de strings do Java 8, e aí posso passar para ele que é para fazer um map utilizando o topicoDto::new. Ele vai pegar cada um dos registros que está dentro do page de tópico e transformar em um page de topicoDto.

Faltou mudar o retorno do método, que agora não vai ser mais um list, vai ser um page.

Vou iniciar o projeto. Sem nenhum erro, iniciou normalmente. No Postman, vamos fazer os testes. Vou disparar uma requisição do tipo GET para tópicos sem passar nenhum parâmetro. Ele me dá erro, como deveria, porque o parâmetro página é obrigatório. Eu tenho que passar topicos?pagina=1&qtd=1. Por exemplo, estou na página um e quero trazer apenas um registro. Vou disparar a requisição. Ele me devolve um JSON com content, e nesse content estão os dados. Vem outro parâmetro no JSON, pageable, com as informações da paginação.

O cliente pode ler essas informações do JSON e montar o esquema de paginação automático, os números da página, tudo certo, que além dos dados ele tem as informações da paginação.

Só um detalhe. Na verdade, o registro que veio coloquei quantidade um, então só veio um registro. Mas não veio o primeiro registro, veio o segundo, porque coloquei página um. Na verdade, ele começa no zero.

Não deu erro no parâmetro nome curso porque coloquei como opcional. Se eu não filtrar pelo nome do curso, não tem problema, não é obrigatório. Só é obrigatório fazer o filtro pela paginação.

Com isso, conseguimos fazer nossa paginação usando Spring Boot, Spring data, de maneira relativamente simples, nosso código ficou tranquilo, usando esse tal de pageable, e devolvendo page ao invés de list. No próximo vídeo vamos aprender a fazer ordenação também. Os registros estão voltando de acordo com a ordem que vem do banco de dados, pela chave primeira, mas e se eu quiser ordenar pela data, pelo status, ou pelo autor? No próximo vídeo vamos aprender como fazer ordenação usando Spring data.

Paginação e ordenação de recursos - Ordenação

No último vídeo vimos como fazer paginação usando as classes do Spring page, pageable, pageRequest e passando o pageable como parâmetro para o repository, que os métodos do Spring já sabem que quando chega um pageable é para fazer a paginação via JPA e a lógica de paginação é feita automaticamente.

Além de paginação, outra coisa comum nos projetos é que às vezes o cliente quer controlar em que ordem virão os registros. Além de paginar, quero ordenar por algum atributo específico. Como nós não definimos nada, no momento está vindo de ordem crescente pelo id, pela chave primária, conforme vem do banco de dados. Mas na aula de hoje vamos mudar isso, vamos flexibilizar, deixar que o cliente consiga controlar também qual ordem ele quer, por qual atributo do tópico ele quer ordenar os registros.

Para fazer isso, mais um parâmetro que podemos colocar no nosso método. No caso, vou criar um parâmetro chamado ordenação, que vai ser uma string. A ideia vai ser que além de passar a página e a quantidade de registros, o cliente também vai ter que passar qual o campo que ele quer ordenar. A ideia dessa string é passar o nome do campo, que seria o atributo da nossa classe tópico. Pode ser id, data, status ou qualquer outro atributo da nossa classe tópico.

Eu declarei só um atributo, mas preciso alterar a lógica para utilizar o novo parâmetro que está chegando no método. Como eu faço isso? Na própria classe pageable, o Spring também embutiu essa questão de ordenação. Se dermos uma olhada no método of, vamos ver que tem várias versões. Tem um, que estamos utilizando, que só recebe a página e a quantidade de elementos, outro que recebe um sort, e o terceiro recebe um tal de Direction e um string properties, que são as propriedades que você quer ordenar. É justamente o que eu quero utilizar. Mas aí tenho que passar mais dois parâmetros, o Direction, para dizer qual a direção, se é crescente ou decrescente. Eu quero que seja crescente.

Depois da vírgula, ele recebe o parâmetro ordenação. A princípio é só isso. Só eu passar mais um parâmetro por paginação que o Spring sabe que além de ter a paginação, tem também ordenação, pelo campo que foi passado como parâmetro.

Vou salvar e vamos ver se não precisa mexer em mais nada. Vamos testar no Postman. Vou disparar a requisição novamente sem passar o campo ordenação. Ele já dá erro. Agora, além de passar paginação, vou aumentar a quantidade, para trazer os três registros. Vou colocar a ordenação por id, que já é o padrão. Vamos ver se funciona. Eu configurei por padrão para vir de maneira crescente.

Vamos alterar para outro campo. Quero ordenar pela data de criação. Veio ordenado, porque a data também está ordenada. Vou alterar agora para mensagem.

Os registros que eu deixei no banco já estão todos ordenados de maneira crescente. Só para ver se vai funcionar certinho vou mudar a ordenação para ser decrescente.

Agora vimos que está funcionando certinho. Um parâmetro a mais na url, que chamei de ordenação, e passo o atributo que quero fazer a ordenação. No nosso código, recebemos como um parâmetro no console, e o page request passamos o campo e a ordem.

Poderíamos também deixar a ordem flexível. Eu poderia receber mais um parâmetro para dizer qual é a direção, se é crescente ou decrescente, mas eu teria que fazer um if else. Só para não complicar, vou deixar desse jeito, mas é totalmente possível também controlar isso.

Tem só uma questão importante aqui. Tenho que passar o nome do atributo. E se eu passar o nome do atributo errado? Se eu passar, por exemplo, o atributo data. O nome do atributo é data criação. O que acontece? Dá um erro. Se você passar o nome de um atributo que não existe, o Spring joga um exception e devolve erro 500. Ele reclama que não encontrou o campo.

Por hoje, a aula era essa. Na próxima aula vamos ver como melhorar algumas coisas, porque podemos fazer a paginação dessa maneira, mas isso é meio que manual. Tem outro jeito mais simples, mais fácil ainda de controlar a paginação usando outros recursos do Spring, mas no próximo vídeo descobrimos como fazer isso.

Sobre o curso Spring Boot API Rest: Segurança da API, Cache e Monitoramento

O curso Spring Boot API Rest: Segurança da API, Cache e Monitoramento possui 216 minutos de vídeos, em um total de 72 atividades. Gostou? Conheça nossos outros cursos de Java em Programação, ou leia nossos artigos de Programação.

Matricule-se e comece a estudar com a gente hoje! Conheça outros tópicos abordados durante o curso:

Aprenda Java acessando integralmente esse e outros cursos, comece hoje!

  • 1241 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

Premium

  • 1241 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$75
à vista R$900
Matricule-se

Premium Plus

  • 1241 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$100
à vista R$1.200
Matricule-se

Max

  • 1241 cursos

    Cursos de programação, UX, agilidade, data science, transformação digital, mobile, front-end, marketing e infra.

  • Certificado de participação

    Certificado de que assistiu o curso e finalizou as atividades

  • App para Android e iPhone/iPad

    Estude até mesmo offline através das nossas apps Android e iOS em smartphones e tablets

  • Projeto avaliado pelos instrutores

    Projeto práticos para entrega e avaliação dos professores da Alura com certificado de aprovação diferenciado

  • Acesso à Alura Start

    Cursos de introdução a tecnologia através de games, apps e ciência

  • Acesso à Alura Língua

    Reforço online de inglês e espanhol para aprimorar seu conhecimento

12X
R$120
à vista R$1.440
Matricule-se
Procurando planos para empresas?

Acesso por 1 ano

Estude 24h/dia onde e quando quiser

Novos cursos todas as semanas