Descripción del Proyecto
Este proyecto involucra el desarrollo de una mini aplicación WeChat orientada al sector turístico de Sanya, permitiendo a los usuarios acceder a información sobre destinos, realizar reservas y gestionar itinerarios de forma intuitiva.
Arquitectura Técnica
Backend con Spring Boot
El backend se implementa utilizando Spring Boot, un framework que facilita la creación de aplicaciones basadas en Spring mediante configuraciones automáticas y una gestión simplificada de dependencias con Maven o Gradle. Esto reduce la necesidad de configuración manual y permite centrarse en la lógica de negocio.
Frontend con Vue.js
El front end emplea Vue.js, un framework JavaScript progresivo que ofrece enlace de datos bidireccional y un sistema de componentes modular. Su API intuitiva y los hooks de ciclo de vida permiten construir interfaces dinámicas y reactivas con facilidad.
Análisis de Viabilidad
El análisis de viabilidad examina aspectos técnicos, económicos y operativos. Técnicamente, el uso de tecnologías como Java y Spring Boot es viable debido a su estabilidad y ecosistema. Económicamente, se evalúa si los beneficios proyectados superan los costos de desarrollo. Operativamente, el sistema debe garantizar usabilidad y mantenimiento eficiente.
Estrategia de Pruebas
Las pruebas del sistema se realizan para identificar defectos y asegurar la conformidad con los requisitos. Se aplican pruebas funcionales, como validación de inicio de sesión y gestión de usuarios, mediante casos de prueba detallados.
| Datos de Entrada | Resultado Esperado | Resultado Observado | Evaluación |
|---|---|---|---|
| Usuario: admin, Contraseña: segura123, Captcha: válido | Acceso concedido al sistema | Acceso exitoso | Consistente con la expectativa |
| Usuario: admin, Contraseña: incorrecta, Captcha: válido | Notificación de credenciales inválidas | Alerta de error en autenticación | Consistente con la expectativa |
Diseño de Base de Datos
La base de datos almacena entidades clave como usuarios, mensajes y tokens de sesión. A continuación, se detalla un esquema simplificado de las tablas principales.
| Nombre de Columna | Tipo de Dato | Longitud | Restricción |
|---|---|---|---|
| id_usuario | entero | 11 | Clave primaria |
| fecha_creacion | marca de tiempo | - | Valor predeterminado: tiempo actual |
| nombre_usuario | cadena | 200 | No nulo, único |
| contraseña | cadena | 200 | No nulo |
| nombre_completo | cadena | 200 | Opcional |
Fragmento de Código Backend
El siguiente código muestra un controlador común adaptado, con nombres de variables y métodos modificados para ilustrar variaciones en la estructura.
@RestController
public class APIControlador {
@Autowired
private ServicioComun servicioComun;
@Autowired
private ServicioConfiguracion servicioConfig;
private static AipFace clienteReconocimiento = null;
private static String claveMapaBaidu = null;
@RequestMapping("/obtenerUbicacion")
public Respuesta obtenerUbicacion(String longitud, String latitud) {
if (claveMapaBaidu == null) {
claveMapaBaidu = servicioConfig.selectOne(new EntityWrapper<entidadconfig>().eq("nombre", "clave_mapa_baidu")).getValor();
if (claveMapaBaidu == null) {
return Respuesta.error("Configure la clave del mapa en el panel de administración");
}
}
Map<string string=""> datosCiudad = UtilidadBaidu.obtenerCiudadPorCoordenadas(claveMapaBaidu, longitud, latitud);
return Respuesta.exitosa().put("datos", datosCiudad);
}
@RequestMapping("/compararRostros")
public Respuesta compararRostros(String imagenRostro1, String imagenRostro2) {
if (clienteReconocimiento == null) {
String claveApi = servicioConfig.selectOne(new EntityWrapper<entidadconfig>().eq("nombre", "clave_api")).getValor();
String claveSecreta = servicioConfig.selectOne(new EntityWrapper<entidadconfig>().eq("nombre", "clave_secreta")).getValor();
String tokenAutenticacion = UtilidadBaidu.obtenerAutenticacion(claveApi, claveSecreta);
if (tokenAutenticacion == null) {
return Respuesta.error("Configure clave_api y clave_secreta correctamente");
}
clienteReconocimiento = new AipFace(null, claveApi, claveSecreta);
clienteReconocimiento.setConnectionTimeoutInMillis(2000);
clienteReconocimiento.setSocketTimeoutInMillis(60000);
}
JSONObject resultado = null;
try {
File archivo1 = new File(ResourceUtils.getFile("classpath:static/upload").getAbsolutePath() + "/" + imagenRostro1);
File archivo2 = new File(ResourceUtils.getFile("classpath:static/upload").getAbsolutePath() + "/" + imagenRostro2);
String imgCodificada1 = CodificadorBase64.codificar(ArchivoUtil.archivoABytes(archivo1));
String imgCodificada2 = CodificadorBase64.codificar(ArchivoUtil.archivoABytes(archivo2));
SolicitudComparacion solicitud1 = new SolicitudComparacion(imgCodificada1, "BASE64");
SolicitudComparacion solicitud2 = new SolicitudComparacion(imgCodificada2, "BASE64");
ArrayList<solicitudcomparacion> solicitudes = new ArrayList<>();
solicitudes.add(solicitud1);
solicitudes.add(solicitud2);
resultado = clienteReconocimiento.comparar(solicitudes);
} catch (ArchivoNoEncontradoException e) {
e.printStackTrace();
return Respuesta.error("Archivo no localizado");
} catch (IOException e) {
e.printStackTrace();
}
return Respuesta.exitosa().put("datos", com.alibaba.fastjson.JSONObject.parse(resultado.get("resultado").toString()));
}
}
</solicitudcomparacion></entidadconfig></entidadconfig></string></entidadconfig>
Script SQL de Ejemplo
Definición de tablas para el manejo de datos de la aplicación.
CREATE TABLE `usuarios` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Identificador único',
`fecha_creacion` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Fecha de registro',
`nombre_usuario` varchar(200) NOT NULL COMMENT 'Nombre de usuario',
`contrasena` varchar(200) NOT NULL COMMENT 'Contraseña',
`nombre` varchar(200) DEFAULT NULL COMMENT 'Nombre completo',
`genero` varchar(200) DEFAULT NULL COMMENT 'Género',
`foto_perfil` varchar(200) DEFAULT NULL COMMENT 'URL de foto de perfil',
`telefono` varchar(200) DEFAULT NULL COMMENT 'Número de teléfono',
`documento_identidad` varchar(200) DEFAULT NULL COMMENT 'Número de documento',
PRIMARY KEY (`id`),
UNIQUE KEY `nombre_usuario` (`nombre_usuario`)
) ENGINE=InnoDB AUTO_INCREMENT=5001 DEFAULT CHARSET=utf8mb3 COMMENT='Tabla de usuarios';
CREATE TABLE `mensajes` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Identificador del mensaje',
`fecha_creacion` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Fecha de envío',
`id_usuario` bigint NOT NULL COMMENT 'ID del usuario que envía',
`nombre_usuario` varchar(200) DEFAULT NULL COMMENT 'Nombre del usuario',
`contenido` longtext NOT NULL COMMENT 'Texto del mensaje',
`respuesta` longtext COMMENT 'Contenido de la respuesta',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6001 DEFAULT CHARSET=utf8mb3 COMMENT='Tabla de mensajes';
CREATE TABLE `sesiones` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT 'Identificador de sesión',
`id_usuario` bigint NOT NULL COMMENT 'ID del usuario',
`nombre_usuario` varchar(100) NOT NULL COMMENT 'Nombre del usuario',
`tabla_asociada` varchar(100) DEFAULT NULL COMMENT 'Tabla relacionada',
`rol` varchar(100) DEFAULT NULL COMMENT 'Rol del usuario',
`token_sesion` varchar(200) NOT NULL COMMENT 'Token de autenticación',
`fecha_creacion` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Fecha de creación',
`fecha_expiracion` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Fecha de expiración',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7001 DEFAULT CHARSET=utf8mb3 COMMENT='Tabla de tokens de sesión';