Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Dúvida Vraptor4 + Paginação

Olá a todos, Eu implementei um esquema de paginação utilizando o Vraptor4 com o Bootstrap, tentei fazer algo próximo(pelo menos a lógica) que o Spring Data utiliza para realizar a paginação dos registros, para isso criei as classes Pageable e Page.

Tudo funcionou perfeitamente, até o momento que coloquei uma busca na página, ou seja se eu pesquisar todos os usuários por nome “Maria”, se a consulta trouxer por exemplo 5 páginas, cada uma com 10 resultados, ao clicar na página 2, eu devo manter o parâmetro nome na requisição, ou seja, nos links do objeto de paginação devem ficar como no formato abaixo:

http://localhost:8080/seguranca/lista?page=0&nome=Maria http://localhost:8080/seguranca/lista?page=1&nome=Maria http://localhost:8080/seguranca/lista?page=2&nome=Maria http://localhost:8080/seguranca/lista?page=3&nome=Maria http://localhost:8080/seguranca/lista?page=4&nome=Maria

Para fazer esse tipo de tarefa no Spring utilizamos o componente UriComponentsBuilder, para enviar o parâmetro nome e substituir o parâmetro page.

Para manter esses parâmetros, tanto o page quanto o nome na requisição eu tentei utilizar um recurso da própria JSTL, tentei fazer assim

Sem sucesso, provavelmente porque eu estava fazendo errado mesmo.

Então parti para a solução atual, novamente implementar algo parecido com oque existe no Spring, criei meu próprio UriBuilder com a ajuda da biblioteca Http Components da apache, a cada click nos componentes de paginação envio a url atual e adiciono os parâmetros( código de paginação abaixo)

Minha dúvida é se essa forma de implementação é correta, se impacta alguma coisa na performance ou segurança da aplicação ou se existe alguma outra forma de implementar a paginação e manter o filtro nas páginas? A solução abaixo está funcionando mas fico meio receioso, os caras lá do Spring devem ter quebrado a cabeça pra implementar o UriComponentsBuilder, fazer vários testes complexos, bem ao contrário do meu que é bem simples. Ou então se existe alguma alternativa no Vraptor ou mesmo no CDI para fazer o build de urls ? Como vocês fazem paginação com filtros?

@Get("/usuario")
@Controller
public class UsuarioController {

    @Inject
    private UsuarioDAO repository;

    @Inject
    private Result result;

    @Get
    @Path("/lista")
    public void lista(Pageable pageable, String nome){
        Page<Usuario> pagina = repository.buscarPorNome(pageable,nome);
        result.include("page",pagina);    
    }
}
@Convert(Pageable.class)
public class RequestConverter implements Converter<Pageable>{

    @Inject
    private  HttpServletRequest request;

    @Override
    public Pageable convert(String arg0, Class<? extends Pageable> arg1) {
        Pageable pageable = new  Pageable(request);
        return pageable;
    }

}
public class Pageable {

    private int pageNumber;
    private int pageSize;
    final private String queryString;
    final private String urlRequested;

    public Pageable(HttpServletRequest request) {

        this.pageSize = 10;    
        String page = request.getParameter("page");
        Integer currentPage = (page == null) ? 0 : Integer.valueOf(page);
        this.pageNumber = currentPage;
        this.queryString = request.getQueryString();
        this.urlRequested = request.getRequestURL().toString();
    }

    public void setPageNumber(Integer page) {
        this.pageNumber = page;
        this.pageSize = 10;
    }

    public int getPageNumber() {
        return pageNumber;
    }

    public int getPageSize() {
        return pageSize;
    }

    public int getOffSet(){
        return pageNumber * pageSize;
    }

    public void setPageNumber(int pageNumber) {
        this.pageNumber = pageNumber;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize;
    }

    public String construirUrl(int page) throws URISyntaxException{
        HttpGet httpget = new HttpGet(urlRequested);
        URI uri = httpget.getURI();
        URIBuilder builder = new URIBuilder(uri);
        if (queryString != null && !queryString.isEmpty()) {
            final List<NameValuePair> params =   URLEncodedUtils.parse(queryString, StandardCharsets.UTF_8);
            for (final NameValuePair param : params) {
                builder.setParameter(param.getName(),param.getValue());    
            }
        }
        builder.setParameter("page",String.valueOf(page));
        httpget = new HttpGet(builder.build());
        return httpget.getURI().toString();
    }
}
public class Page<T> {

    private List<T> lista;
    private Long total;
    private Pageable pageable;

    public Page(List<T> lista,Pageable pageable, Long total) {

        this.lista = lista;
        this.total = total;
        this.pageable = pageable;
    }

    public  List<T> getLista() {
        return lista;
    }

    public Long getTotal() {
        return total;
    }

    public int getTotalPages() {
        return total == 0 ? 1 : (int) Math.ceil((double) total / (double) 10);
    }

    public int getPageNumber(){
        return this.pageable.getPageNumber();
    }

    public boolean isFirst() {
        return this.pageable.getPageNumber() == 0;
    }

    public boolean isLast(){
        return this.pageable.getPageNumber() == getTotalPages() -1;
    }

    public String buildUrl(int page) throws URISyntaxException{
        return this.pageable.construirUrl(page);

    }

}
@Stateless
public class UsuarioDAO {

    @Inject
    private EntityManager manager;

    public Page<Usuario> buscarPorNome(Pageable pageable, String nome){

        CriteriaBuilder builder = manager.getCriteriaBuilder();
        CriteriaQuery<Usuario> usuarioQuery = builder.createQuery(Usuario.class);
        Root<Usuario> usuarioRoot = usuarioQuery.from(Usuario.class); 
        Path<String> nomePath = usuarioRoot.<String>get("nome");
        Predicate predicate = builder.and();
        if(nome != null && !nome.trim().equals("")){
            predicate = builder.and(predicate,builder.like(nomePath,"%"+nome+"%"));
        }
        TypedQuery<Usuario> query = manager.createQuery(usuarioQuery.where(predicate));
        query.setFirstResult(pageable.getOffSet());
        query.setMaxResults(pageable.getPageSize()).getResultList();
        return new  Page<Usuario>(query.getResultList(),pageable,total(nome));
    }

    private Long total(String nome) {

        CriteriaBuilder builder = manager.getCriteriaBuilder();
        CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
        CriteriaQuery<Usuario> cqEntity = builder.createQuery(Usuario.class);
        Root<?> entityRoot = criteriaQuery.from(cqEntity.getResultType());
        Path<String> path = entityRoot.<String>get("nome");
        criteriaQuery.select(builder.count(entityRoot));
        Predicate predicate = builder.and();
        if(nome != null && !nome.trim().equals("")){
            predicate = builder.and(predicate,builder.like(path,"%"+nome+"%"));
        }
        return manager.createQuery(criteriaQuery.where(predicate)).getSingleResult();
    }

}
<%@taglib tagdir="/WEB-INF/tags/template" prefix="template"%>
<!DOCTYPE html>
<html>
<head>
<script src="<c:url value='/assets/js/jquery-2.1.4.min.js'/>"></script>
<script src="<c:url value='/assets/js/bootstrap.min.js'/>"></script>
<script src="<c:url value='/assets/js/jquery.jqpagination.js'/>"></script>
<link rel="stylesheet"
    href="<c:url value='/assets/css/pagination/jqpagination.css'/>" />
<link rel="stylesheet"
    href="<c:url value='/assets/css/bootstrap.min.css'/>">
<link rel="stylesheet"
    href="<c:url value='/assets/css/bootstrap-theme.min.css'/>">
<link rel="stylesheet" href="<c:url value='/assets/css/index.css'/>">
<link rel="stylesheet" href="<c:url value='/assets/css/forms.css'/>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
    <div>
        <div class="container min-container">
            <h2 class="basic-title">Listar Usuários</h2>
            <div class="container-fluid">
                <form method="GET">
                    <div class="row">
                        <div class="form-group  col-sm-6">
                            <label class="control-label" for="nome">Nome</label> <input
                                type="text" name="nome" value="${param.nome}" /> <input
                                type="submit" value="Pesquisar">
                        </div>
                    </div>
                </form>
            </div>
            <div class="well">
                <table
                    class="table table-condensed table-bordered table-striped table-hover">
                    <thead>
                        <tr>
                            <td>id</td>
                            <td>Nome</td>
                            <td>matricula <span class="dropup"><span
                                    class="caret"></span></span>
                            </td>
                            <td>actions</td>
                        </tr>
                    </thead>
                    <tbody>
                        <c:forEach items='${page.lista}' var='object'>
                            <tr>
                                <td><a href="<c:url value='/usuario'/>/${object.usuarioId}">${object.usuarioId}</a></td>
                                <td>${object.nome}</td>
                                <td>${object.matricula}</td>
                                <td><a
                                    href="<c:url value='/usuario/remove'/>/${object.usuarioId}">Remove</a></td>
                            </tr>
                        </c:forEach>
                    </tbody>
                </table>
                <div class="col-sm-12 text-center">
                    <nav>
                        <ul class="pagination pagination-sm">
                            <c:if test="${!page.first}">
                                <li><a href="${page.buildUrl(page.pageNumber-1)}"><span>&laquo;</span></a></li>
                            </c:if>
                            <c:forEach begin="1" end="${page.totalPages}" var="index">
                                <c:set var="pagina" value="${index-1}" />
                                <c:set var="link" value="${pagina}" />
                                <li
                                    class="${page.pageNumber eq (index-1) ? 'active' : 'nonactive'}">
                                    <a href="${page.buildUrl(link)}">${index}</a>
                                </li>
                            </c:forEach>
                            <c:if test="${!page.last}">
                                <li><a href="${page.buildUrl(page.pageNumber+1)}"> <span>&raquo;</span>
                                </a></li>
                            </c:if>
                        </ul>
                    </nav>
                </div>
            </div>
        </div>
    </div>
</body>
</html>
1 resposta
solução!

Não vi nenhum problema com sua solução, mandou bem. Provavelmente vc nem precisaria usar as classes que fazem requisições reais.. Mas como vc não faz nenhuma, acho que não impacta em nada..

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software