Sistema de Gestión de Personal Militar Universitario basado en SpringBoot + Vue + uniapp: Diseño y Implementación Detallados (Código Fuente + Documentación + Guía de Despliegue)

Este sistema está diseñado para gestionar el proceso de incorporación de estudiantes universitarios al servicio militar, integrando una arquitectura moderna con tecnologías backend y frontend avanzadas. El sistema permite registrar, verificar, supervisar y controlar el estado de los estudiantes que participan en programas de reclutamiento militar, facilitando una gestión eficiente desde el nivel institucional.

Tecnologías Utilizadas

Backend: Spring Boot

Spring Boot proporciona un entorno de desarrollo rápido y robusto, incluyendo servidores embebidos como Tomcat o Undertow. Su capacidad de configuración automática simplifica la inicialización del proyecto, reduciendo el tiempo de configuración manual. Además, ofrece integración nativa con herramientas como Spring Data para acceso a datos, Spring Security para control de acceso y Spring Cloud para escalamiento distribuido. Esto permite desarrollar aplicaciones empresariales altamente escalables y mantenibles.

Frontend: Vue.js

Vuе.js se centra en el manejo reactivo de datos mediante el uso de un DOM virtual, lo que optimiza las actualizaciones de interfaz. Gracias a su sistema de enlace de datos bidireccional, componentes reutilizables y directivas personalizadas, los desarrolladores pueden crear interfaces dinámicas con bajo esfuerzo. La arquitectura modular también favorece el mantenimiento y la evolución del código a lo largo del tiempo.

Acceso a Datos: MyBatis-Plus

MyBatis-Plus extiende las funcionalidades de MyBatis, eliminando gran parte del código repetitivo relacionado con SQL. Ofrece anotaciones para mapeo de entidades, generación automática de CRUD, soporte para paginación, consultas dinámicas y bloqueo optimista. Con sus herramientas de generación de código, se puede crear rápidamente el modelo de datos, repositorios y archivos XML asociados, acelerando significativamente el desarrollo de capas de acceso a datos.

Pruebas del Sistema

Objetivos de Prueba

El objetivo principal de las pruebas es identificar errores funcionales antes de la puesta en producción. Se evalúa si el sistema cumple con los requisitos especificados, asegurando que cada módulo funcione correctamente bajo condiciones reales. Las pruebas se realizan desde la perspectiva del usuario final, validando flujo de trabajo, validaciones de entrada y comportamiento ante casos límite.

Pruebas Funcionales

Funcionalidad de Inicio de Sesión

Se validan escenarios de autenticación con credenciales correctas, incorrectas, campos vacíos y captchas mal ingresados. Los resultados deben coincidir con las expectativas definidas en el diseño.

Datos de Entrada Resultado Esperado Resultado Real Análisis
Usuario: admin, Contraseña: 123456, Captcha: válido Inicio exitoso Iniciado con éxito Coherente
Usuario: admin, Contraseña: 999999, Captcha: válido Error de contraseña Contraseña incorrecta Coherente
Usuario: vacío, Contraseña: 123456, Captcha: inválido Debe indicar campo obligatorio Ingrese nombre de usuario Coherente

Gesttión de Usuarios

Se prueban operaciones como alta, edición, eliminación y búsqueda. Se verifica la validación de campos obligatorios y el manejo de duplicados.

Entrada Resultado Esperado Resultado Real Análisis
Agregar usuario con todos los campos completos Registro exitoso Usuario aparece en lista Correcto
Intentar agregar un nombre de usuario ya existente Mostrar mensaje de duplicado Nombre de usuario ya registrado Correcto
Eliminar un usuario seleccionado Pregunta de confirmación → Eliminado Confirmado → No encontrado Correcto

Seguridad del Sistema

La autenticación se basa en tokens JWT ganerados tras el inicio de sesión. Cada token tiene una duración limitada (1 hora) y se almacena en una tabla de tokens activos. El sistema valida el token en cada solicitud protegida, verificando su validez y rol asignado. Si no hay token válido, se devuelve un error HTTP 401.

@Component
public class TokenValidationInterceptor implements HandlerInterceptor {

    private static final String AUTH_HEADER = "Authorization";

    @Autowired
    private TokenService tokenService;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // Permitir solicitudes CORS
        response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization, Origin, Cache-Control");

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

        if (handler instanceof HandlerMethod) {
            IgnoreAuth annotation = ((HandlerMethod) handler).getMethodAnnotation(IgnoreAuth.class);
            if (annotation != null) return true;
        }

        String token = request.getHeader(AUTH_HEADER);
        if (StringUtils.isBlank(token)) {
            sendErrorResponse(response, "Autenticación requerida");
            return false;
        }

        TokenEntity tokenEntity = tokenService.findByToken(token);
        if (tokenEntity == null || tokenEntity.getExpiryDate().before(new Date())) {
            sendErrorResponse(response, "Token expirado o inválido");
            return false;
        }

        request.setAttribute("userId", tokenEntity.getUserId());
        request.setAttribute("role", tokenEntity.getRole());
        request.setAttribute("username", tokenEntity.getUsername());

        return true;
    }

    private void sendErrorResponse(HttpServletResponse response, String message) throws IOException {
        response.setStatus(HttpStatus.UNAUTHORIZED.value());
        response.setContentType("application/json;charset=UTF-8");
        try (PrintWriter writer = response.getWriter()) {
            writer.write("{\"code\":401,\"msg\":\"" + message + "\"}");
        }
    }
}

Estructura de Base de Datos

La tabla token almacena los tokens activos con información sobre el usuario, rol, tabla asociada y tiempo de expiración.

-- Tabla de tokens de sesión
CREATE TABLE IF NOT EXISTS token (
    id BIGINT AUTO_INCREMENT PRIMARY KEY,
    user_id BIGINT NOT NULL COMMENT 'ID del usuario',
    username VARCHAR(100) NOT NULL,
    table_name VARCHAR(100) DEFAULT NULL COMMENT 'Tabla relacionada',
    role VARCHAR(50) NOT NULL COMMENT 'Rol del usuario',
    token VARCHAR(200) NOT NULL UNIQUE,
    create_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    expiry_time TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

-- Ejemplo de registro
INSERT INTO token (user_id, username, table_name, role, token, expiry_time)
VALUES (1, 'admin', 'users', 'admin', 'a1b2c3d4e5f6...', '2024-04-05 10:00:00');

Conclusión

El sistema demuestra una implementación sólida de arquitectura moderna, con separación clara entre capas, seguridad adecuada y flujo de trabajo bien definido. Tras pruebas exhaustivas, se confirma que todas las funciones cumplen con los requisitos iniciales. La solución es escalable, mantenible y lista para despliegue en entornos productivos.

Etiquetas: SpringBoot vue.js MyBatis-Plus JWT REST API

Publicado el 9-27 06:01