Desenvolvimento de um Marketplace Acadêmico com Spring Boot e Vue.js

Esta plataforma de comércio eletrônico universitário foi projetada utilizando uma arquitetura distribuída e moderna para facilitar a negociação de produtos usados entre estudantes. O sistema adota o modelo B/S (Browser/Server), garantindo que os usuários possam acessar as funcionalidades através de qualquer navegador web, sem a necessidade de instalações locais complexas. A stack tecnológica foca em alta performance e escalabilidade, utilizando Spring Boot no back-end e Vue.js para a interface do usuário.

Arquitetura e Tecnologias Utilizadas

  • Back-end: Java com framework Spring Boot, utilizando Maven para gerenciamento de dependências e automação de builds.
  • Persistência de Dados: MyBatis como framework ORM para integração com o banco de dados relacional MySQL.
  • Front-end: Vue.js integrado ao ElementUI para fornecer uma interface responsiva e componentes de UI consistentes.
  • Ferramentas de Desenvolvimento: IntelliJ IDEA para o código Java e VS Code para o desenvolvimento front-end.

Implementação do Motor de Recomendação

Um diferencial deste sistema é a implementação de um algoritmo de Filtragem Colaborativa baseada em usuários (User-based Collaborative Filtering). Este componente analisa o comportamento de compra e as preferências para sugerir itens relevantes.


/**
* Motor de Recomendação Baseado em Filtragem Colaborativa
*/
public class EngineRecomendacao {
   private Map<String, Map<String, Double>> mapaAvaliacoes;
   private Map<String, List<String>> itensPorUsuario;
   private Map<String, Integer> idParaIndice;
   private Map<Integer, String> indiceParaId;
   private Long[][] matrizCoocorrencia;

   public EngineRecomendacao(Map<String, Map<String, Double>> avaliacoesIniciais) {
       this.mapaAvaliacoes = avaliacoesIniciais;
       this.itensPorUsuario = new HashMap<>();
       this.idParaIndice = new HashMap<>();
       this.indiceParaId = new HashMap<>();

       int index = 0;
       for (String userId : mapaAvaliacoes.keySet()) {
           Map<String, Double> notas = mapaAvaliacoes.get(userId);
           for (String item : notas.keySet()) {
               itensPorUsuario.computeIfAbsent(item, k -> new ArrayList<>()).add(userId);
           }
           idParaIndice.put(userId, index);
           indiceParaId.put(index, userId);
           index++;
       }

       inicializarMatrizSimilitude();
   }

   private void inicializarMatrizSimilitude() {
       int totalUsuarios = mapaAvaliacoes.size();
       this.matrizCoocorrencia = new Long[totalUsuarios][totalUsuarios];

       for (int i = 0; i < totalUsuarios; i++) {
           Arrays.fill(matrizCoocorrencia[i], 0L);
       }

       itensPorUsuario.values().forEach(usuarios -> {
           for (String u1 : usuarios) {
               for (String u2 : usuarios) {
                   if (!u1.equals(u2)) {
                       int idx1 = idParaIndice.get(u1);
                       int idx2 = idParaIndice.get(u2);
                       matrizCoocorrencia[idx1][idx2]++;
                   }
               }
           }
       });
   }

   public double calcularCosseno(String usrA, String usrB) {
       Integer i = idParaIndice.get(usrA);
       Integer j = idParaIndice.get(usrB);
       
       if (i == null || j == null) return 0.0;
       
       double magnitudeA = mapaAvaliacoes.get(indiceParaId.get(i)).size();
       double magnitudeB = mapaAvaliacoes.get(indiceParaId.get(j)).size();
       
       return matrizCoocorrencia[i][j] / Math.sqrt(magnitudeA * magnitudeB);
   }
}
   

Lógica de Sugestão de Itens

Após o cálculo da similaridade entre os perfis, o sistema identifica usuários com gostos semelhantes para extrair produtos que o usuário alvo ainda não interagiu.


public List<String> obterSugestoes(String usuarioAlvo, int limite) {
   Map<String, Double> scoresSimilaridade = new HashMap<>();

   mapaAvaliacoes.keySet().stream()
       .filter(u -> !u.equals(usuarioAlvo))
       .forEach(u -> scoresSimilaridade.put(u, calcularCosseno(usuarioAlvo, u)));

   List<String> usuariosSimilares = scoresSimilaridade.entrySet().stream()
       .sorted(Map.Entry.<String, Double>comparingByValue().reversed())
       .limit(limite)
       .map(Map.Entry::getKey)
       .collect(Collectors.toList());

   Map<String, Double> itensRecomendados = new HashMap<>();
   for (String u : usuariosSimilares) {
       Map<String, Double> itensDaqueleUsuario = mapaAvaliacoes.get(u);
       for (String item : itensDaqueleUsuario.keySet()) {
           if (!mapaAvaliacoes.get(usuarioAlvo).containsKey(item)) {
               itensRecomendados.put(item, itensDaqueleUsuario.get(item));
           }
       }
   }
   return new ArrayList<>(itensRecomendados.keySet());
}
   

Estrutura do Projeto e Metodologia

O desenvolvimento foi segmentado em fases críticas para garantir a robustez do software:

  1. Análise de Requisitos: Levantamento das necessidades funcionais, como cadastro de produtos, gestão de usuários e sistema de chat interno, além de requisitos não funcionais como segurança e tempo de resposta.
  2. Modelagem de Dados: Design do esquema relacional no MySQL, focando em integridade referencial e otimização de consultas para o catálogo de produtos.
  3. Desenvolvimento de API: Construção de endpoints RESTful com Spring Boot, utilizando controladores para gerenciar o fluxo de dados entre o banco e o front-end.
  4. Interface do Usuário: Criação de componentes dinâmicos em Vue.js, permitinod uma navegação fluida sem recarregamentos desnecessários de página (SPA).

Fase de Validação e Testes

O processo de garantia de qualidade anvolveu testes unitários para a lógica de recomendação e testes de integração para as rotas da API. A validação de interface foi realizada smiulando diferentes perfis de acesso (estudantes e administradores) para assegurar que as permissões de acesso e as funcionalidades de CRUD (Create, Read, Update, Delete) operem conforme o esperado em ambientes de produção.

Tags: Spring Boot Vue.js java MySQL MyBatis

Publicado em 7-2 19:20