Paginação com Vraptor + Bootstrap

0 respostas
webdesenvolvimentoprogramaçãoboostrapjava
johannsen

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

<c:set var=“link” value="?${pageContext.request.queryString}&page=${pagina}" />

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{
@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 {

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();
}

}


<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>
Criado 18 de janeiro de 2017
Respostas 0
Participantes 1