Sistema de E-commerce para Petshop: Arquitetura SpringBoot, Vue.js e UniApp

Introdução

Este artigo apresenta o desenvolvimento de um sistema completo de e-commerce para petshop, utilizando uma arquitetura moderna baseada em SpringBoot para o backend, Vue.js para o frontend web e UniApp para aplicações móveis. O sistema oferece funcionalidades completas de gerenciametno de produtos, carrinho de compras, controle de usuários e administração do sistema.

Arquitetura do Sistema

A arquitetura proposta segue o padrão MVC (Model-View-Controller) separando claramente as responsabilidades entre as camadas de apresentação, negócio e persistência. O backend utiliza o framework SpringBoot que oferece configuração automática e servidor embarcado, enquanto o frontend Vue.js proporciona uma experiência reactiva e responsiva ao usuário.

Backend com SpringBoot

O SpringBoot representa uma evolução significativa no desenvolvimento de aplicações Java empresariais. Este framework elimina a necessidade de configuração manual de servidores como Tomcat ou Jetty, pois já inclui um servidor embarcado. A funcionalidade de auto-configuração detecta automaticamente as dependências presentes no projeto e configura os componentes necessários, reduzindo drasticamente o tempo de desenvolvimento.

Além disso, o SpringBoot integra-se perfeitamante com projetos como Spring Data para acesso a dados, Spring Security para autenticação e autorização, além de oferecer excelente suporte para testes unitários e de integração.

A seguir, apresentamos um exemplo de configuração básica de uma aplicação SpringBoot:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class PetshopApplication {

    public static void main(String[] args) {
        SpringApplication.run(PetshopApplication.class, args);
    }

    @GetMapping("/api/saudacao")
    public String obterSaudacao() {
        return "Bem-vindo ao Sistema de Petshop!";
    }
}

Este código demonstra a estrutura básica de um endpoint RESTful utilizando as anotações do SpringBoot. A anotação @SpringBootApplication combina as funcionalidades de @Configuration, @EnableAutoConfiguration e @ComponentScan, enquanto @RestController indica que esta classe menangani requisições HTTP e retorna dados diretamente no corpo da resposta.

Frontend com Vue.js

O Vue.js destaca-se no desenvolvimento de interfaces web modernas devido ao seu sistema de reatividade automatizada. Quando o estado dos dados muda, a interface é automaticamente atualizada sem necessidade de manipulação manual do DOM. O Virtual DOM permite atualizações eficientes minimizando operações custosas no DOM real.

A arquitetura baseada em componentes do Vue.js facilita a reutilização de código e a manutenção do sistema. Cada componente encapsula sua própria lógica, estilos e estrutura, tornando o desenvolvimento mais organizado e escalável.

Exemplo de implementação básica com Vue.js:


<html>
<head>
    <title>Loja de Petshop</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        <h2>{{ mensagem }}</h2>
        <button @click="alterarMensagem">Atualizar</button>
    </div>

    <script>
        var aplicacao = new Vue({
            el: '#app',
            data: {
                mensagem: 'Bem-vindo à nossa Loja de Petshop!'
            },
            methods: {
                alterarMensagem: function() {
                    this.mensagem = 'Obrigado por visitar nossa loja!';
                }
            }
        });
    </script>
</body>
</html>

Camada de Persistência com MyBatis

O MyBatis constitui um framework de mapeamento objeto-relacional que simplifica significativamente a interação com bancos de dados relacionais. Diferente de outros frameworks ORM, o MyBatis permite escrever SQL puro mantendo total controle sobre as consultas exectuadas.

As principais vantagens do MyBatis incluem:

  • Separação clara entre código SQL e lógica de negócio
  • Suporte a SQL dinâmico para construção de queries condicionais
  • Cache de primeira e segunda nível para otimização de performance
  • Arquitetura de plugins extensível

Modelo de Dados

A estrutura do banco de dados para o sistema de petshop foi projetada considerando escalabilidade e normalização adequada. A tabela de produtos exemplifica esta estrutura:

-- Estrutura da tabela de produtos
DROP TABLE IF EXISTS `produto`;
CREATE TABLE `produto` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Identificador único',
  `nome` varchar(100) NOT NULL COMMENT 'Nome do produto',
  `preco` decimal(10, 2) NOT NULL COMMENT 'Preço do produto',
  `descricao` varchar(200) DEFAULT NULL COMMENT 'Descrição detalhada',
  `quantidade_estoque` int(11) NOT NULL COMMENT 'Quantidade disponível',
  `data_criacao` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `data_atualizacao` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Esta tabela armazena informações essenciais sobre cada produto disponível na loja, incluindo controle de datas de criação e atualização automática.

Sistema de Autenticação e Autorização

O sistema implementa autenticação baseada em tokens JWT para garantir segurança nas requisições. O processo de login valida as credenciais do usuário e gera um token de acesso temporário:

// Anotação para ignorar validação de autenticação
@IgnoreAuth
@PostMapping(value = "/autenticar")
public R autenticar(String username, String password, String captcha, HttpServletRequest request) {
   // Consultar informações do usuário
   UsuarioEntity usuario = usuarioService.selecionarUm(new EntityWrapper<UsuarioEntity>().eq("nome_usuario", username));
   
   // Validar existência e senha
   if(usuario == null || !usuario.getSenha().equals(password)) {
      return R.erro("Credenciais inválidas");
   }
   
   // Gerar token de acesso
   String token = tokenService.gerarToken(usuario.getId(), username, "usuarios", usuario.getFuncao());
   return R.ok().put("token", token);
}

// Método para geração de token
@Override
public String gerarToken(Long idUsuario, String nomeUsuario, String nomeTabela, String funcao) {
   // Verificar token existente
   TokenEntity tokenExistente = this.selecionarUm(new EntityWrapper<TokenEntity>()
      .eq("idusuario", idUsuario).eq("funcao", funcao));
   
   // Criar token aleatório
   String token = CommonUtil.gerarStringAleatoria(32);
   
   // Configurar expiração para 1 hora
   Calendar cal = Calendar.getInstance();   
   cal.setTime(new Date());   
   cal.add(Calendar.HOUR_OF_DAY, 1);
   
   if(tokenExistente != null) {
      // Atualizar token existente
      tokenExistente.setToken(token);
      tokenExistente.setDataExpiracao(cal.getTime());
      this.atualizarPorId(tokenExistente);
   } else {
      // Inserir novo registro de token
      this.inserir(new TokenEntity(idUsuario, nomeUsuario, nomeTabela, funcao, token, cal.getTime()));
   }
   return token;
}

O interceptor de autorização valida automaticamente cada requisição verificando a presença e validade do token nos cabeçalhos HTTP:

/**
 * Interceptor para validação de autenticação
 */
@Component
public class InterceptadorAutorizacao implements HandlerInterceptor {

    public static final String CHAVE_TOKEN = "Token";

    @Autowired
    private ServicoToken servicoToken;
    
    @Override
    public boolean preHandle(HttpServletRequest requisicao, HttpServletResponse resposta, Object manipulador) {
        // Configurar cabeçalhos CORS
        resposta.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        resposta.setHeader("Access-Control-Max-Age", "3600");
        resposta.setHeader("Access-Control-Allow-Credentials", "true");
        resposta.setHeader("Access-Control-Allow-Headers", "x-requested-with,request-source,Token, Origin");
        
        // Tratar requisição OPTIONS para CORS
        if (requisicao.getMethod().equals(RequestMethod.OPTIONS.name())) {
            resposta.setStatus(HttpStatus.OK.value());
            return false;
        }
        
        // Verificar anotação de exemptionsão de autenticação
        AnotacaoIgnorarAuth anotacao;
        if (manipulador instanceof HandlerMethod) {
            anotacao = ((HandlerMethod) manipulador).getMethodAnnotation(AnotacaoIgnorarAuth.class);
        } else {
            return true;
        }

        // Recuperar token do cabeçalho
        String token = requisicao.getHeader(CHAVE_TOKEN);
        
        // Permitir acesso sem autenticação quando especificado
        if(anotacao != null) {
            return true;
        }
        
        // Validar token
        EntidadeToken entidadeToken = null;
        if(StringUtils.isNotBlank(token)) {
            entidadeToken = servicoToken.obterEntidadeToken(token);
        }
        
        if(entidadeToken != null) {
            // Armazenar informações do usuário na sessão
            requisicao.getSession().setAttribute("idUsuario", entidadeToken.getIdUsuario());
            requisicao.getSession().setAttribute("funcao", entidadeToken.getFuncao());
            requisicao.getSession().setAttribute("nomeTabela", entidadeToken.getNomeTabela());
            requisicao.getSession().setAttribute("nomeUsuario", entidadeToken.getNomeUsuario());
            return true;
        }
        
        // Retornar erro de autenticação
        resposta.setCharacterEncoding("UTF-8");
        resposta.setContentType("application/json; charset=utf-8");
        PrintWriter writer = null;
        try {
            writer = resposta.getWriter();
            writer.print(JSONObject.toJSONString(R.erro(401, "Autenticação necessária")));
        } finally {
            if(writer != null) {
                writer.close();
            }
        }
        return false;
    }
}

Testes do Sistema

A fase de testes garante que todas as funcionalidades implementadas atendam aos requisitos estabelecidos. O processo de teste inclui verificação de funcionalidades, validação de dados de entrada e confirmação de respostas do sistema.

Os testes de funcionalidade verificam se cada módulo opera conforme esperado. Para o módulo de autenticação, por exemplo, são testados cenários como credenciais corretas, senha incorreta, código de verificação inválido e campos obrigatórios não preenchidos.

Os casos de teste para autenticação demonstram a validação completa do processo:

Entrada Resultado Esperado Resultado Obtido
Usuário: admin, Senha: 123456, Código: válido Login bem-sucedido Login realizado com sucesso
Usuário: admin, Senha: senha123, Código: válido Erro de senha Mensagem de senha incorreta
Usuário: admin, Senha: 123456, Código: inválido Erro de verificação Mensagem de código incorreto
Usuário: vazio, Senha: 123456, Código: válido Campo obrigatório Mensagem informando campo obrigatório

Conclusão

O sistema de e-commerce para petshop desenvolvido demonstra a integração eficaz de tecnologias modernas como SpringBoot, Vue.js e UniApp. A arquitetura proposta oferece escalabilidade, manutenibilidade e performance adequadas para aplicações comerciais. Os testes realizados confirmam que o sistema atende aos requisitos funcionais e não-funcionais estabelecidos, proporcionando uma experiência confiável para os usuários finais.

Tags: SpringBoot Vue.js MyBatis java web-development

Publicado em 6-21 16:00