Este sistema de gestão visa promover a reutilização e troca de itens usados dentro do ambiente universitário, com um módulo específico dedicado à troca de itens gratuitos. Desenvolvido sobre o framework Java Spring Boot, a plataforma facilita a publicação, navegação, troca e avaliação de itens que os estudantes desejam disponibilizar sem custo.
Arquitetura e Tecnologias Utilizadas
O desenvolvimento do sistema emprega uma pilha tecnológica moderna e robusta.
Backend com Spring Boot
O framework Spring Boot é utilizado como base para o desenvolvimento do backend. Sua configuração automática e suporte a servidores embutidos como Tomcat simplificam consideravelmente o processo de implantação e desenvolvimento. A integração nativa com módulos do ecossistema Spring, como Spring Security para autenticação e Spring Data para acesso a dados, permite a construção rápida de uma aplicação segura e escalável.
Frontend com Vue.js
A camada de apresentação é construída com o framework Vue.js. Sua abordagem reativa e baseada em componentes permite a criação de interfaces de usuário dinâmicas e responsivas. A utilização do Virtual DOM otimiza as operações de renderização, proporcionando uma experiência fluida ao usuário final, onde as alterações nos dados refletem-se automaticamente na interface.
Camada de Persistência com MyBatis-Plus
Para o mapeamento objeto-relacional (ORM), o sistema utiliza o MyBatis-Plus, uma extensão poderosa do MyBatis. Esta ferramenta reduz significativamente a necessidade de escrever código boilerplate SQL, oferecendo uma API avançada para operações CRUD, consultas dinâmicas e paginnação. O gerador de código integrado acelera ainda mais o desenvolvimento ao criar automaticamente as classes de entidade e interfaces de mapeamento.
Processo de Testes do Sistema
A fase de testes é crucial para assegurar a qualidade e confiabilidade da aplicação. O foco principal reside nos testes funcionais (caixa preta), verificando se cada módulo opera conforme as especificações.
Estratégia de Teste para Login
O cenário de autenticação é rigorosamente testado. Os casos de teste incluem a verificação de credenciais corretas, senhas incorretas, usuários inexistentes, campos obrigatórios vazios e validação de captcha. Os resultados são comparados com os outputs esperados para garantir a robustez do processo de login.
Estratégia de Teste para Gerenciamento de Usuários
As operações CRUD (Criar, Ler, Atualizar, Deletar) no módulo de usuários são alvo de testes específicos. Verifica-se a validação de campos únicos (como nome de usuário), a integridade das operações de edição e a confirmação em ações de remoção. O objetivo é garantir que todas as funcionalidades de gerenciamento operem corretamente e apresentem mensagens de erro claras ao usuário.
Conclui-se que uma suíte de testes bem elaborada é indispensável. Ela não apenas valida a aderência aos requisitos funcionais, como também simula cenários de uso real, elevando a qualidade final e a experiência do usuário com o sistema.
Exemplos de Implementação
A seguir, são apresentados trechos ilustrativos da implementação.
Endpoint de Autenticação (Login)
@IgnoreAuth
@PostMapping("/autenticar")
public Resposta autenticar(String loginUsuario, String senha, String captcha, HttpServletRequest requisicao) {
EntidadeUsuario usuario = servicoUsuario.buscarUm(new EnvolucroEntidade<EntidadeUsuario>().eq("login", loginUsuario));
if (usuario == null || !usuario.getSenha().equals(senha)) {
return Resposta.erro("Credenciais inválidas");
}
String jwtToken = servicoToken.gerarToken(usuario.getId(), loginUsuario, "usuarios", usuario.getPapel());
return Resposta.ok().colocar("token", jwtToken);
}
@Override
public String gerarToken(Long idUsuario, String nomeUsuario, String tabelaPapel, String papel) {
EntidadeToken tokenExistente = this.buscarUm(new EnvolucroEntidade<EntidadeToken>().eq("id_usuario", idUsuario).eq("papel", papel));
String novoToken = UtilidadeComum.gerarStringAleatoria(32);
Calendar calendario = Calendar.getInstance();
calendario.add(Calendar.HOUR_OF_DAY, 1); // Expira em 1 hora
Date dataExpiracao = calendario.getTime();
if (tokenExistente != null) {
tokenExistente.setToken(novoToken);
tokenExistente.setDataExpiracao(dataExpiracao);
this.atualizarPorId(tokenExistente);
} else {
this.inserir(new EntidadeToken(idUsuario, nomeUsuario, tabelaPapel, papel, novoToken, dataExpiracao));
}
return novoToken;
}
Interceptor de Autorização
@Component
public class InterceptorAutorizacao implements HandlerInterceptor {
private static final String CABECALHO_TOKEN = "Authorization";
@Autowired
private ServicoToken servicoToken;
@Override
public boolean preHandle(HttpServletRequest requisicao, HttpServletResponse resposta, Object manipulador) throws Exception {
// Configuração de CORS
resposta.setHeader("Access-Control-Allow-Origin", requisicao.getHeader("Origin"));
resposta.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS");
resposta.setHeader("Access-Control-Allow-Headers", CABECALHO_TOKEN + ", Content-Type");
resposta.setHeader("Access-Control-Allow-Credentials", "true");
// Pré-voo CORS (OPTIONS)
if ("OPTIONS".equalsIgnoreCase(requisicao.getMethod())) {
resposta.setStatus(HttpServletResponse.SC_OK);
return false;
}
// Verificar anotação @IgnoreAuth
if (manipulador instanceof HandlerMethod) {
IgnoreAuth anotacao = ((HandlerMethod) manipulador).getMethodAnnotation(IgnoreAuth.class);
if (anotacao != null) {
return true; // Ignora a autenticação
}
}
// Extrair e validar o token
String tokenCabecalho = requisicao.getHeader(CABECALHO_TOKEN);
if (StringUtils.isNotBlank(tokenCabecalho)) {
EntidadeToken tokenValido = servicoToken.validarToken(tokenCabecalho);
if (tokenValido != null) {
// Define atributos na requisição para uso nos controllers
requisicao.setAttribute("idUsuarioLogado", tokenValido.getIdUsuario());
requisicao.setAttribute("papelUsuario", tokenValido.getPapel());
return true;
}
}
// Resposta de erro de autenticação
resposta.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
resposta.setContentType("application/json;charset=UTF-8");
resposta.getWriter().write("{\"erro\": \"Autenticação necessária\"}");
return false;
}
}
Estrutura de Banco de Dados para Tokens
-- Tabela para armazenar tokens de autenticação
CREATE TABLE tokens_auth (
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'Chave primária',
id_usuario BIGINT NOT NULL COMMENT 'ID do usuário associado',
nome_usuario VARCHAR(100) NOT NULL COMMENT 'Nome de login do usuário',
tabela_papel VARCHAR(100) COMMENT 'Tabela de referência do papel (ex: usuarios, alunos)',
papel VARCHAR(50) COMMENT 'Papel do usuário no sistema',
token VARCHAR(255) NOT NULL UNIQUE COMMENT 'Token JWT gerado',
criado_em TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'Data de criação',
expira_em TIMESTAMP NOT NULL COMMENT 'Data e hora de expiração do token',
INDEX idx_token (token),
INDEX idx_usuario_papel (id_usuario, papel)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='Tabela de gerenciamento de tokens de sessão';