sexta-feira, 3 de maio de 2013

Spring MVC + Paginação

Salve galera!

Hoje vou postar um código  que uso para implementar paginação de dados nas requisições do Spring MVC.

Para fazer a paginação, a classe Paginator recebe:

  • pageSize: Tamanho da página
  • offset: Posição do registro
  • modelMap: Estrutura de dados do Spring MVC que faz o bind com a view
  • repository: JpaRepository do Spring para fazer a consulta
  • sort: Atributo para ordenação
  • BeanLoaderListener: Listener para carregamento de entidade, caso seja necessário procesar alguma referência.
Código do BeanLoaderListener

public interface BeanLoaderListener {

    void load(Object bean);
}

Código do Paginator


public class Paginator {

    public void list(Integer pageSize, Integer offset, ModelMap modelMap, JpaRepository repository, String sort, BeanLoaderListener listener) {

        if (offset == null || offset < 0) {
            offset = 0;
        }

        if (pageSize == null || pageSize == 0 || pageSize > 50) {
            pageSize = 10;
        }

        Pageable requestPage = sort == null ? new PageRequest(offset, pageSize) : new PageRequest(offset, pageSize, new Sort(sort));
        Page page = null;

        page = repository.findAll(requestPage);

        if (listener != null) {
            for (Object it : page.getContent()) {
                listener.load(it);
            }
        }

        modelMap.addAttribute("items", page.getContent());

        Integer next = offset + 1;
        Integer last = offset - 1;

        if (!page.hasNextPage() && page.hasPreviousPage()) {
            next = page.getTotalPages() - 1;
        } else if (!page.hasNextPage()) {
            next = 0;
        }

        if (page.isFirstPage()) {
            last = 0;
        }

        if (last == null && next == null) {
            modelMap.addAttribute("paginated", false);
        } else {
            modelMap.addAttribute("paginated", true);
            modelMap.addAttribute("next", next);
            modelMap.addAttribute("last", last);
        }

        List pages = new LinkedList<>();
        for (int i = 0; i < page.getTotalPages(); i++) {
            pages.add(i);
        }
        modelMap.addAttribute("pages", pages);
        modelMap.addAttribute("offset", offset);
        modelMap.addAttribute("hasNext", page.hasNextPage());
        modelMap.addAttribute("hasLast", page.hasPreviousPage());
        modelMap.addAttribute("pageSize", pageSize);

    }
}

E aqui um exemplo de uso:


    @RequestMapping(value = "/person/{pageSize}/{offset}", method = RequestMethod.GET)
    public String list(@PathVariable("pageSize") Integer pageSize, @PathVariable("offset") Integer offset, ModelMap modelMap) {        
        new Paginator().list(pageSize, offset, modelMap, repository, "name", null);
        return "person/list";
    }    

Aqui um resource jsp usado na paginação (yaml css): /extra/paginator.jsp



<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

     




E aqui usando o resource jsp dentro de uma tela de listagem:


    



E era isso gurizada! até a próxima ;)

2 comentários:

  1. Olá Ricardo ficou bem legal essa implementação, você poderia postar a implementação das classes Pageable e Page?

    ResponderExcluir
    Respostas
    1. Opa! Então, a Pegeable é uma classe utilitária do Spring, que tem como implementação a PageRequest, como tu pode ver nessa linha:

      Pageable requestPage = sort == null ? new PageRequest(offset, pageSize) : new PageRequest(offset, pageSize, new Sort(sort));

      Os imports são:

      import org.springframework.data.domain.PageRequest;
      import org.springframework.data.domain.Pageable;

      Já a Page vem dos repositórios padrão do Spring Data (JpaRepository), que me devolve um objeto pronto que implamenta essa interface com o resultada da consulta. Constumo usar Dynamic Finders do Spring Data, com IoC (injeção) dos repositórios nos controllers.

      Os imports são:
      import org.springframework.data.domain.Page
      import org.springframework.data.jpa.repository.JpaRepository

      Os repositórios do Spring Data são configurados via XML, no applicationContext com:


      Excluir