Desenvolvimento de Sistema de Gestão de Voluntários Universitários com Spring Boot e Vue

O sistema de gestão de voluntários universitários utiliza o framework Spring Boot para o backend e Vue.js para o frontend, combinados com MyBatis Plus para a camada de persistência.

Tecnologias Utilizadas

Backend - Spring Boot

Spring Boot simplifica a configuração do servidor, oferecendo integrações automáticas com diversos componentes, como Tomcat, Jetty e Undertow. Suas características incluem:

  • Configuração automática com base nas dependências do projeto.
  • Ferramentas prontas para uso, como Spring Data, Spring Security e Spring Cloud.
  • Facilidade na construção e escalabilidade de aplicações.

Frontend - Vue.js

Vue.js é um framework progressivo que utiliza a tecnologia de DOM virtual para renderização eficiente. Suas principais características são:

  • Binding de dados reativo.
  • Componentização para modularização do código.
  • Simplicidade e eficiência no desenvolvimento de interfaces de usuário.

Persistência - MyBatis Plus

MyBatis Plus é uma extensão do MyBatis que facilita a manipulação de bancos de dados. Suas funcionalidades incluem:

  • Geração de código para entidades, mapeadores e arquivos XML.
  • Suporte a múltiplos bancos de dados.
  • Funções adicionais como paginação, consultas dinâmicas e análise de desempenho.

Testes do Sistema

A realização de testes é essencial para identificar e corrigir defeitos no sistema, garantindo que ele atenda às expectativas dos usuários. Os principais objetivos incluem:

  • Validar a conformidade do sistema com os requisitos especificados.
  • Identificar falhas e áreas de melhoria.
  • Asegurar uma experiência de usuário positvia.

Teste de Funcionalidade - Login

Os casos de teste para a funcionalidade de login incluem:

Dados de Entrada Resultado Esperado Resultado Obtido Análise
Usuário: admin Senha: 123456 Código: correto Login bem-sucedido Login bem-sucedido Conforme esperado
Usuário: admin Senha: 111111 Código: correto Mensagem de erro de senha Mensagem de erro de senha Conforme esperado
Usuário: admin Senha: 123456 Código: incorreto Mensagem de erro de código Mensagem de erro de código Conforme esperado
Usuário: vazio Senha: 123456 Código: correto Mensagem de erro de campo obrigatório Mensagem de erro de campo obrigatório Conforme esperado
Usuário: admin Senha: vazio Código: correto Mensagem de erro de senha Mensagem de erro de senha Conforme esperado

Teste de Funcionalidade - Gestão de Usuários

Casos de teste para a gestão de usuários envolvem operações de criação, edição, exclusão e busca:

Dados de Entrada Resultado Esperado Resultado Obtido Análise
Dados válidos Usuário criado com sucesso Usuário criado com sucesso Conforme esperado
Edição de informações Informações atualizadas com sucesso Informações atualizadas com sucesso Conforme esperado
Selecionar e excluir usuário Confirmação de exclusão, usuário removido Confirmação de exclusão, usuário removido Conforme esperado
Criação sem nome de usuário Mensagem de erro de campo obrigatório Mensagem de erro de campo obrigatório Conforme esperado
Nome de usuário já existente Mensagem de erro de duplicidade Mensagem de erro de duplicidade Conforme esperado

Código de Exemplo


@IgnoreAuth
@PostMapping(value = "/entrar")
public Resposta entrar(String usuario, String senha, String codigo, HttpServletRequest requisicao) {
   UsuarioEntidade usuarioEncontrado = servicoUsuario.selecionarUm(new WrapperEntidade<UsuarioEntidade>().igualA("usuario", usuario));
   if(usuarioEncontrado == null || !usuarioEncontrado.getSenha().equals(senha)) {
      return Resposta.erro("Usuário ou senha inválidos");
   }
   String token = servicoToken.gerarToken(usuarioEncontrado.getId(), usuario, "usuarios", usuarioEncontrado.getPapel());
   return Resposta.sucesso().adicionar("token", token);
}

@Override
public String gerarToken(Long idUsuario, String usuario, String tabela, String papel) {
    TokenEntidade tokenEntidade = this.selecionarUm(new WrapperEntidade<TokenEntidade>().igualA("idUsuario", idUsuario).igualA("papel", papel));
    String token = UtilComum.getStringAleatoria(32);
    Calendar calendario = Calendar.getInstance();   
    calendario.setTime(new Date());   
    calendario.add(Calendar.HORA_DO_DIA, 1);
    if(tokenEntidade != null) {
        tokenEntidade.setToken(token);
        tokenEntidade.setDataExpiracao(calendario.getTime());
        this.atualizarPorId(tokenEntidade);
    } else {
        this.inserir(new TokenEntidade(idUsuario, usuario, tabela, papel, token, calendario.getTime()));
    }
    return token;
}

@Component
public class InterceptorAutorizacao implements HandlerInterceptor {

    public static final String CHAVE_TOKEN_LOGIN = "Token";

    @Autowired
    private ServicoToken servicoToken;
    
    @Override
    public boolean preProcessar(HttpServletRequest requisicao, HttpServletResponse resposta, Object manipulador) throws Exception {
        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,imgType, Content-Type, cache-control,postman-token,Cookie, Accept,authorization");
        resposta.setHeader("Access-Control-Allow-Origin", requisicao.getHeader("Origin"));

        if (requisicao.getMethod().equals(RequestMethod.OPTIONS.name())) {
            resposta.setStatus(HttpStatus.OK.value());
            return false;
        }

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

        String token = requisicao.getHeader(CHAVE_TOKEN_LOGIN);
        
        if(anotacao != null) {
            return true;
        }
        
        TokenEntidade tokenEntidade = null;
        if(StringUtils.isNotBlank(token)) {
            tokenEntidade = servicoToken.obterToken(token);
        }
        
        if(tokenEntidade != null) {
            requisicao.getSession().setAttribute("idUsuario", tokenEntidade.getIdUsuario());
            requisicao.getSession().setAttribute("papel", tokenEntidade.getPapel());
            requisicao.getSession().setAttribute("tabela", tokenEntidade.getTabela());
            requisicao.getSession().setAttribute("usuario", tokenEntidade.getUsuario());
            return true;
        }
        
        PrintWriter escritor = null;
        resposta.setCharacterEncoding("UTF-8");
        resposta.setContentType("application/json; charset=utf-8");
        try {
            escritor = resposta.getWriter();
            escritor.print(JSONObject.toJSONString(Resposta.erro(401, "Faça login primeiro")));
        } finally {
            if(escritor != null){
                escritor.close();
            }
        }
        return false;
    }
}

Estrutura do Banco de Dados


DROP TABLE IF EXISTS `token`;
CREATE TABLE `token` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Chave primária',
  `idUsuario` bigint(20) NOT NULL COMMENT 'ID do usuário',
  `usuario` varchar(100) NOT NULL COMMENT 'Nome do usuário',
  `tabela` varchar(100) DEFAULT NULL COMMENT 'Nome da tabela',
  `papel` varchar(100) DEFAULT NULL COMMENT 'Papel',
  `token` varchar(200) NOT NULL COMMENT 'Token',
  `dataAdicao` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Data de adição',
  `dataExpiracao` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Data de expiração',
  PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT COMMENT='Tabela de tokens';

INSERT INTO `token` VALUES ('9', '23', 'cd01', 'estudante', 'Estudante', 'al6svx5qkei1wljry5o1npswhdpqcpcg', '2023-02-23 21:46:45', '2023-03-15 14:01:36');
INSERT INTO `token` VALUES ('10', '11', 'xh01', 'estudante', 'Estudante', 'fahmrd9bkhqy04sq0fzrl4h9m86cu6kx', '2023-02-27 18:33:52', '2023-03-17 18:27:42');
INSERT INTO `token` VALUES ('11', '17', 'ch01', 'estudante', 'Estudante', 'u5km44scxvzuv5yumdah2lhva0gp4393', '2023-02-27 18:46:19', '2023-02-27 19:48:58');
INSERT INTO `token` VALUES ('12', '1', 'admin', 'usuarios', 'Administrador', 'h1pqzsb9bldh93m92j9m2sljy9bt1wdh', '2023-02-27 19:37:01', '2023-03-17 18:23:02');
INSERT INTO `token` VALUES ('13', '21', 'xiaohao', 'presidente', 'Presidente', 'zdm7j8h1wnfe27pkxyiuzvxxy27ykl2a', '2023-02-27 19:38:07', '2023-03-17 18:25:20');
INSERT INTO `token` VALUES ('14', '27', 'djy01', 'estudante', 'Estudante', 'g3teq4335pe21nwuwj2sqkrpqoabqomm', '2023-03-15 12:56:17', '2023-03-15 14:00:16');
INSERT INTO `token` VALUES ('15', '29', 'dajiyue', 'presidente', 'Presidente', '0vb1x9xn7riewlp5ddma5ro7lp4u8m9j', '2023-03-15 12:58:08', '2023-03-15 14:03:48');

Tags: SpringBoot vue MyBatisPlus TestesAutomatizados

Publicado em 9-9 19:57