Sistema de Plataforma de Troca de Eletrônicos Usados para Universitários com Spring Boot

Objetivo

O sistema desenvolvido em Java com Spring Boot e MySQL permite que estudantes universitários publiqume, explorem, comprem e avaliem produtos eletrônicos usados. Alunos podem cadastrar itens, gerenciar estoque e acompanhar pedidos, enquanto compradores visualizam detalhes, realizam compras e deixam feedback. A plataforma resolve problemas de assimetria de informação e segurança em transações tradicionais, oferecendo um ambiente confiável para o comércio de eletrônicos recondicionados, além de incentivar a economia circular no campus.

Tecnologias Utilizadas

Backend – Spring Boot

O Spring Boot embute servidores como Tomcat e Jetty, eliminando configurações manuais. Sua auto-configuração baseada em dependências acelera o desenvolvimento. Recursos como Spring Data, Spring Security e Spring Cloud são integrados facilmente, permitindo criação rápida de aplicações robustas.

Frontend – Vue.js

Vue.js utiliza DOM virtual para renderização eficiente e reatividade. A ligação bidirecional de dados e o sistema de componentes simplificam a construção de interfaces dinâmicas e de fácil manutenção.

Persistência – MyBatis-Plus

MyBatis-Plus estende o MyBatis, reduzindo SQL manual por meio de anotações e API fluente. O gerador de código cria automaticamente entidades, mapeadores e XML. Recursos como paginação, bloqueio otimista e análise de desempenho são suportados, aumentando a produtividade no acesso a dados.

Testes do Sistema

Os testes validam a funcionalidade e a usabilidade. Foram realizados testes de caixa preta nos módulos de login e gerenciamento de usuários, utilizando casos de teste com valores válidos, inválidos e limites.

Teste de Login

Entrada Resultado esperado Resultado real Análise
usuário: admin, senha: 123456, captcha: correto Login bem-sucedido Login realizado OK
usuário: admin, senha: 111111, captcha: correto Senha incorreta Mensagem de erro exibida OK
usuário: admin, senha: 123456, captcha: errado Captcha inválido Alerta de captcha OK
usuário: vazio, senha: 123456, captcha: correto Usuário obrigatório Campo obrigatório OK

Teste de Gerenciamento de Usuários

Operação Resultado esperado Resultado real Análise
Inserir dados comlpetos Usuário adicionado Aparece na lista OK
Alterar informações Dados atualizados Lista reflete alterações OK
Excluir usuário Confirmação e remoção Confirma e usuário some OK
Adicionar sem nome Erro: nome obrigatório Mensagem exibida OK
Adicionar nome duplicado Falha: nome já existe Mensagem de conflito OK

Os testes confirmam que o sistema atende aos requisitos funcionais e de usabilidade, com fluxos corretos para login e CRUD de usuários.

Exemplo de Código

// Endpoint de login (ignorando autenticação)
@PostMapping("/login")
public Response login(@RequestParam String user, @RequestParam String pass, 
                      @RequestParam String captcha, HttpServletRequest req) {
    UserEntity usuario = userRepo.findOne(
        new QueryWrapper<UserEntity>().eq("username", user));
    if (usuario == null || !usuario.getPassword().equals(pass)) {
        return Response.error("Credenciais inválidas");
    }
    // Gera token
    String token = tokenService.createToken(
        usuario.getId(), user, "users", usuario.getRole());
    return Response.ok().put("token", token);
}

// Serviço de token
public String createToken(Long userId, String name, String table, String role) {
    TokenEntity tokenEntity = this.selectOne(
        new QueryWrapper<TokenEntity>()
            .eq("user_id", userId).eq("role", role));
    String newToken = CommonUtil.randomString(32);
    Calendar calendar = Calendar.getInstance();
    calendar.setTime(new Date());
    calendar.add(Calendar.HOUR_OF_DAY, 1);
    if (tokenEntity != null) {
        tokenEntity.setToken(newToken);
        tokenEntity.setExpiration(calendar.getTime());
        this.updateById(tokenEntity);
    } else {
        this.insert(new TokenEntity(userId, name, table, role, newToken, calendar.getTime()));
    }
    return newToken;
}

// Interceptador de autorização
@Component
public class AuthInterceptor implements HandlerInterceptor {
    private static final String HEADER_TOKEN = "Authorization";
    @Autowired
    private TokenService tokenService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
            return false;
        }

        IgnoreAuth ignore;
        if (handler instanceof HandlerMethod) {
            ignore = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
        } else {
            return true;
        }

        String token = request.getHeader(HEADER_TOKEN);
        if (ignore != null) {
            return true;
        }

        TokenEntity tokenEntity = null;
        if (token != null && !token.isEmpty()) {
            tokenEntity = tokenService.findByToken(token);
        }

        if (tokenEntity != null) {
            request.getSession().setAttribute("userId", tokenEntity.getUserId());
            request.getSession().setAttribute("role", tokenEntity.getRole());
            request.getSession().setAttribute("tableName", tokenEntity.getTableName());
            request.getSession().setAttribute("username", tokenEntity.getUsername());
            return true;
        }

        response.setContentType("application/json; charset=UTF-8");
        response.setCharacterEncoding("UTF-8");
        try (PrintWriter writer = response.getWriter()) {
            writer.print(JSON.toJSONString(Response.error(401, "Autenticação necessária")));
        }
        return false;
    }
}

Estrutura da Tabela (Exemplo)

-- Tabela de tokens
DROP TABLE IF EXISTS `token`;
CREATE TABLE `token` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `user_id` bigint(20) NOT NULL COMMENT 'ID do usuário',
  `username` varchar(100) NOT NULL COMMENT 'Nome de usuário',
  `table_name` varchar(100) DEFAULT NULL COMMENT 'Nome da tabela associada',
  `role` varchar(100) DEFAULT NULL COMMENT 'Papel/função',
  `token_value` varchar(200) NOT NULL COMMENT 'Valor do token',
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Data de criação',
  `expires_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Data de expiração',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=30 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='Tabela de tokens de autenticação';

-- Dados de exemplo
INSERT INTO `token` VALUES (1, 23, 'cd01', 'xuesheng', 'estudante', 'exemplo123abc', '2023-02-23 21:46:45', '2023-03-15 14:01:36');
INSERT INTO `token` VALUES (2, 1, 'admin', 'users', 'administrador', 'tokenAdmin456', '2023-02-27 19:37:01', '2023-03-17 18:23:02');

Tags: Spring Boot Vue.js MyBatis-Plus MySQL Autenticação JWT

Publicado em 6-1 06:53 por Thomas