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');