Projeto e Implementação de um Sistema de Apoio Agrícola e Combate à Pobreza com SpringBoot, Vue e uniapp

Arquitetura do Sistema

O sistema é construído com uma pilha de tecnologia moderna, dividida em camadas de backend, frontend e aplicativo móvel. O backend utiliza SpringBoot para fornecer APIs RESTful robustas, enquanto o frontend emprega Vue.js para uma interface de usuário responsiva. O aplicativo móvel é desenvolvido com uniapp, garantindo compatibilidade multiplataforma. A persistência de dados é gerenciada pelo MyBatis-Plus, que simplifica as operações de banco de dados.

Pilares Tecnológicos

Backend com SpringBoot

SpringBoot facilita o desenvolvimento de aplicações Java ao fornecer configuração automática, servidores integrados e suporte a plugins como Spring Data e Spring Security. Isso permite criar aplicações escaláveis com mínima configuração manual, acelerando o desenvolvimento e a integração com outros sistemas.

Frontend com Vue.js

Vue.js utiliza o conceito de DOM virtual e data binding reativo para atualizar a interface de forma eficiente. A abordagem baseada em componentes promove a reutilização de código e manutenção simplificada, permitindo que os desenvolvadores se concentrem na lógica de negócios em vez de manipulação manual do DOM.

Persistência de Dados com MyBatis-Plus

MyBatis-Plus é uma extensão do MyBatis que reduz a necessidade de código SQL manual. Ele oferece recursos como consulta dinâmica, paginação e geração de código automática, suportando múltiplos bancos de dados como MySQL e PostgreSQL. Isso otimiza a camada de acesso a dados e melhora a produtividade.

Testes do Sistema

Objetivos dos Testes

Os testes visam identificar defeitos e garantir que o sistema atenda aos requisitos funcionais e não funcionais. Simulações de cenários reais são conduzidas para verificar a usabilidade, segurança e desempenho, assegurando uma experiência de usuário confiável.

Testes Funcionais

Testes de caixa negra são aplicados para validar módulos como autenticação e gerenciamento de usuários. Por exemplo, a funcionalidade de login é testada com entradas válidas e inválidas, verificando mensagens de erro e flluxos de autenticação.

Dados de Entrada Resultado Esperado Resultado Atual
Usuário: admin, Senha: correta, Captcha: correto Login bem-sucedido Sistema acessado
Usuário: admin, Senha: incorreta, Captcha: correto Erro de credenciais Mensagem de senha inválida
Usuário: vazio, Senha: correta, Captcha: correto Erro de campo obrigatório Solicitação de nome de usuário

Testes de gerenciamento de usuários incluem operações CRUD, com validações para campos obrigatórios e exclusão segura. Os testes confirmam que o sistema responde adequadamente a entradas válidas e inválidas.

Conclusão dos Testes

Os testes concluídos demonstram que o sistema satisfaz os requisitos de design, com funcionalidades operando corretamente sob condições diversas. A análise de resultados permite refinamentos contínuos para aprimorar a robustez.

Exemplos de Código

Autenticação e Autorização

O código de backend implementa endpoints para login e geração de tokens. A autenticação é realizada verificando credenciais no banco de dados, e tokens JWT são gerados para sessões seguras.


@IgnorarAutenticacao
@RequestMapping(value = "/autenticar", method = RequestMethod.POST)
public ResponseEntity<Map<String, Object>> autenticar(@RequestParam String nomeUsuario, @RequestParam String senha, @RequestParam String captcha, HttpServletRequest requisicao) {
    Usuario usuario = servicoUsuario.obterPorNome(nomeUsuario);
    if (usuario == null || !verificarSenha(senha, usuario.getSenhaHash())) {
        return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(Collections.singletonMap("erro", "Credenciais inválidas"));
    }
    String token = servicoToken.criarToken(usuario.getId(), nomeUsuario, "tabela_usuarios", usuario.getPapel());
    Map<String, Object> resposta = new HashMap<>();
    resposta.put("token", token);
    return ResponseEntity.ok(resposta);
}

@Override
public String criarToken(Long idUsuario, String nomeUsuario, String tabela, String papel) {
    Token tokenExistente = repositorioToken.obterPorUsuarioEidPapel(idUsuario, papel);
    String valorToken = GeradorUtil.gerarStringAleatoria(32);
    Date dataExpiracao = new Date(System.currentTimeMillis() + 3600000); // 1 hora
    if (tokenExistente != null) {
        tokenExistente.setValor(valorToken);
        tokenExistente.setDataExpiracao(dataExpiracao);
        repositorioToken.atualizar(tokenExistente);
    } else {
        Token novoToken = new Token(idUsuario, nomeUsuario, tabela, papel, valorToken, dataExpiracao);
        repositorioToken.inserir(novoToken);
    }
    return valorToken;
}

Um interceptor de autorização verifica tokens em requisições HTTP, permitindo acesso a rotas protegidas ou retornando erro 401 para autenticação necessária.


@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 {
        resposta.setHeader("Access-Control-Allow-Origin", requisicao.getHeader("Origin"));
        if ("OPTIONS".equalsIgnoreCase(requisicao.getMethod())) {
            resposta.setStatus(HttpStatus.OK.value());
            return false;
        }

        if (manipulador instanceof HandlerMethod) {
            IgnorarAutenticacao anotacao = ((HandlerMethod) manipulador).getMethodAnnotation(IgnorarAutenticacao.class);
            if (anotacao != null) {
                return true;
            }
        }

        String token = requisicao.getHeader(CABECALHO_TOKEN);
        if (StringUtils.hasText(token)) {
            Token tokenEntity = servicoToken.obterPorValor(token);
            if (tokenEntity != null) {
                requisicao.getSession().setAttribute("idUsuario", tokenEntity.getIdUsuario());
                requisicao.getSession().setAttribute("papel", tokenEntity.getPapel());
                return true;
            }
        }

        resposta.setStatus(HttpStatus.UNAUTHORIZED.value());
        resposta.getWriter().write("{\"erro\": \"Autenticação requerida\"}");
        return false;
    }
}

Estrutura do Banco de Dados

O esquema de banco de dados inclui tabelas para armazenar tokens de autanticação, com campos para expiração e metadados de usuário.


-- Tabela para tokens de sessão
CREATE TABLE sessao_token (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    id_usuario BIGINT NOT NULL,
    nome_usuario VARCHAR(100) NOT NULL,
    tabela_origem VARCHAR(100),
    papel VARCHAR(50),
    valor_token VARCHAR(255) NOT NULL,
    data_criacao TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    data_expiracao TIMESTAMP NOT NULL
);

Dados de exemplo demonstram registros de tokens para diferentes usuários e papéis.

Tags: SpringBoot Vue.js MyBatis-Plus java uniapp

Publicado em 7-19 16:25