go+iris+jwt+mysql+xorm+viper, una sala de chat sencilla para el proyecto iris, que incluye inicio de sesión, registro, chat privado y chat grupal.
Primero, eche un vistazo a la introducción del front-end debajo de este documento para saber cómo operarlo (debido a la energía limitada, la interfaz de usuario no es particularmente fácil de usar).
Acceda a la dirección de demostración. Si el estado del pequeño icono de arriba es normal, puede acceder a él. Es posible que entre en un estado inactivo y deba esperar unos segundos.
Actualmente, el proyecto solo escribe adaptaciones relacionadas con mysql, pero usando xorm, no es difícil admitir otras bases de datos. Se puede hacer, pero no es necesario, jajaja, si eres demasiado vago para ejecutarlo tú mismo, solo echa un vistazo. en la URL de demostración si está interesado. Nadie tiene mysql ahora.
Originalmente quería admitir sqlite, para que no fuera necesario configurar los parámetros de la base de datos, pero considerando que compilar sqlite en Windows requiere configurar el entorno gcc, lo cual es más problemático, pero no hay un efecto de inicio rápido y simplemente no está completo. , por lo que otras bases de datos no son compatibles por el momento (algún día agregue más cuando tenga tiempo).
Entonces el proyecto solo necesita configurar los siguientes parámetros
git clone https://github.com/JabinGP/demo-chatroom.git
cd demo-chatroom
// 复制config.toml.example 为 config.toml 并填写数据库信息,或者可选修改端口号
go run main.go
El valor predeterminado es el puerto 8888. Después del inicio, acceda http://localhost:8888
Usé reaccionar, pero no usé el marco de la interfaz de usuario. Muchos pequeños detalles no se realizan bien. La interfaz está hecha de acuerdo con el tamaño del teléfono móvil. Si abre la computadora, puede abrir f12. Conformémonos con ello. La atención se centra en este último extremo.
El cuadro de chat configura la ventana para que se desplace automáticamente hacia la parte inferior, pero la API la proporciona React y resulta incompatible con muchos navegadores. Este problema se puede resolver utilizando el navegador Chrome.
Después del registro, regrese manualmente y seleccione iniciar sesión. El nombre rojo en el cuadro de mensaje es para hablar en público y el nombre gris es para chat privado. Puede especificar el nombre del destinatario en el cuadro rojo. discurso público. Después de especificar, solo los usuarios correspondientes pueden ver la información.
Su nombre de usuario se muestra en el cuadro azul. Haga clic para cerrar sesión directamente.
El formato API se basa en un diseño tranquilo y la función de inicio de sesión se completa mediante jwt. Muchas interfaces requieren el estado de inicio de sesión y se debe llevar JWT al realizar la solicitud. Para obtener más detalles, consulte la práctica de jwt de golang iris. conveniente para realizar pruebas. El tiempo de validez de la emisión de JWT está establecido en solo 20 minutos. Debe iniciar sesión nuevamente.
El formato de solicitud de API es el mismo que el de la interfaz general. Get usa parámetros, y Post, Put, Delete, etc. usan Json en Body para pasar parámetros.
El formato de devolución es bastante controvertido. Lo he estado estudiando durante un tiempo. Algunas personas recomiendan usar el código de estado 200 http completo y agregar un código al contenido de la devolución para identificar el error, como este:
// 注册错误时
// http status 200
{
"code" : 40001 ,
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"code" : 200 ,
"msg" : "成功" ,
"data" : {
"username" : " JabinGP " ,
"id" : 3
}
}
Otros recomiendan utilizar códigos de estado http completos para indicar errores:
// 注册错误时
// http status 400
{
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
De hecho, ambos enfoques anteriores tienen sus pros y sus contras:
Según la situación anterior, combinaré los dos:
Cuando tenga éxito, devuelva el código de estado http 200
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
Cuando ocurre una falla, seleccione varios códigos de estado de uso común para expresar el error, 400 (error de solicitud), 500 (error interno del servidor), 404 (no encontrado), 401 (falla de autenticación), clasifique aproximadamente el error y luego regrese Personalizar un código, mensaje y detalle en los datos para representar la causa detallada del error:
// 注册失败
// http status 400
{
"code" : 6 ,
"msg" : "数据检验失败" ,
"detail" : "用户名已存在"
}
// 登录失效
// http status 401
{
"code" : 8 ,
"msg" : "未认证登录" ,
"detail" : " Token is expired "
}
Después de esta combinación, la devolución de llamada exitosa es exitosa y no es necesario escribir res.data.data repetidamente. La devolución de llamada de error solo maneja errores, que pueden juzgarse por el código de estado http y pueden codificarse más, mensajes y mensajes. detallado para manejar errores.
La lista de API es la siguiente. Reemplace localhost con mike.jabingp.cn o puede solicitarla directamente al backend de demostración:
Función | Método de solicitud | DIRECCIÓN |
---|---|---|
Obtener token de inicio de sesión | CORREO | http://localhost:8888/v1/iniciar sesión |
encontrar usuarios | CONSEGUIR | http://localhost:8888/v1/usuario |
registro | CORREO | http://localhost:8888/v1/usuario |
Los usuarios modifican la información ellos mismos. | PONER | http://localhost:8888/v1/usuario |
Usuario envía mensaje | CORREO | http://localhost:8888/v1/mensaje |
El usuario obtiene información | CONSEGUIR | http://localhost:8888/v1/mensaje |
El usuario obtiene información del token | CONSEGUIR | http://localhost:8888/v1/token/info |
Los parámetros de solicitud detallados se pueden ver en la documentación postman-api de demo-chatroom.
O ver el código fuente. Los parámetros de solicitud se pueden ver en model/reqo
y los parámetros de respuesta se pueden ver en model/reso
AJAX no es la mejor opción para la función de chat. WebSocket es mejor, pero me pidieron que usara AJAX, así que no elegí este último.
La interfaz del proyecto es relativamente simple porque solo se usa como demostración.
Mi inglés no es muy bueno y los comentarios del código están en inglés solo porque soy demasiado vago para cambiar el método de entrada.
Esta es la primera vez que uso go para desarrollar un proyecto web, y también es la primera vez que uso reaccionar para escribir el front-end. Dado que el front-end no presta mucha atención a la estructura del proyecto (xjbx), no lo haré. Pongo el código fuente. Compilo el proyecto y lo coloco en la carpeta de activos para facilitar la lectura. Es muy pobre, pero se puede iniciar junto con el backend. No es necesario iniciar la interfaz por separado, lo cual es más conveniente para ver. efecto. Si todavía tengo tiempo, consideraré escribir una versión minimalista en nativo para referencia de todos.
La primera vez que utilicé un ORM para operar una base de datos, me resultó muy difícil de usar. Preferí escribir SQL a mano. Hubo muchos efectos deseados y no pude encontrar una solución después de revisar los documentos durante mucho tiempo. Puedo considerar usar sqlx para la reconstrucción más adelante.
Recientemente, me he interesado más en Go y recibí la tarea de escribir una sala de chat simple. Descubrí que actualmente hay pocas prácticas de proyectos en iris, solo algunos ejemplos de nivel HelloWorld, así que decidí usar Go para hacerlo. Y luego ábralo para referencia mutua. Por supuesto, cómo diseñar la estructura del proyecto se basa completamente en mi experiencia de desarrollo limitada. Por favor, brinde sus valiosas opiniones sobre cualquier aspecto no razonable.
Este proyecto tiene los siguientes requisitos.
La función de inicio de sesión se implementa utilizando JWT
. Las ventajas y desventajas de JWT
y Session
no se discutirán en detalle.
Basado en AJAX es imprescindible para todos los proyectos de separación de front-end y back-end, por lo que esta función no se discutirá demasiado. ¿Cuál es la dificultad?
La lógica de operación del usuario es enviar datos en la sala de chat y luego enviarlos. La interfaz de chat debe mostrar los datos enviados por ella misma y actualizar los datos enviados por otros en tiempo real.
El front-end y el back-end se comunican a través de AJAX. Los datos de envío del front-end y los datos de envío del back-end se pueden expresar como.
¿Cuál es el problema aquí? El problema es que el front-end solo puede iniciar solicitudes de forma activa y el back-end solo puede aceptar solicitudes. Esto significa que los mensajes más recientes nunca se pueden enviar activamente desde el backend al frontend en tiempo real. Los mensajes más recientes solo se pueden almacenar primero en el backend y luego esperar a que el frontend inicie una solicitud antes de que el backend pueda devolver datos.
Dado que el backend no tiene la capacidad de enviar mensajes activamente al frontend, la solución para que los usuarios obtengan los datos más recientes es que el frontend establezca un temporizador每隔一段比较短的时间就请求一次后台接口(轮询)
, de modo que los datos se pueden actualizar continuamente.
La interfaz ha decidido utilizar AJAX para sondear periódicamente la interfaz en segundo plano para obtener los datos más recientes. En aras de los datos en tiempo real, el intervalo de sondeo será小于1s
Esto traerá otro problema. Bajo solicitudes tan frecuentes, el backend no debe transmitir todos los datos cada vez. Uno es la eficiencia de transmisión de la red y el costo del tráfico causado por el tamaño de los datos. El juicio del front-end sobre los nuevos datos significa que el back-end debe devolver datos que el front-end no ha recibido cada vez. El problema es: ¿cómo sabe el back-end qué información ha recibido el front-end?
Esto requiere el uso de自增主键
del mensaje. El front-end solo necesita llevar最后的消息的主键
recibido por el front-end cada vez que realiza una solicitud. Repitiendo y aumentando automáticamente, podemos encontrar fácilmente la proporción. Los datos con una clave primaria grande son los datos que la interfaz aún no ha recibido.
idioma
marco
almacenamiento de datos
tecnología
Debido al uso del marco ORM de la base de datos Xorm, las siguientes tablas se generan automáticamente y vienen con el campo
xxxxxx_at
Con base en los requisitos anteriores, se diseñaron dos tablas, users
y messages
.
Campos clave
Estructura de la tabla de la base de datos
Campo | Tipo | Nulo | Llave | Por defecto | Extra |
---|---|---|---|---|---|
IDENTIFICACIÓN | bigint(20) | NO | PRI | NULO | incremento_automático |
nombre de usuario | varchar(255) | SÍ | NULO | ||
contraseña | varchar(255) | SÍ | NULO | ||
género | bigint(20) | SÍ | NULO | ||
edad | bigint(20) | SÍ | NULO | ||
interés | varchar(255) | SÍ | NULO | ||
creado_en | fecha y hora | SÍ | NULO | ||
actualizado_en | fecha y hora | SÍ | NULO | ||
eliminado_en | fecha y hora | SÍ | NULO |
Campos clave
Estructura de la tabla de la base de datos
Campo | Tipo | Nulo | Llave | Por defecto | Extra |
---|---|---|---|---|---|
IDENTIFICACIÓN | bigint(20) | NO | PRI | NULO | incremento_automático |
id_remitente | bigint(20) | SÍ | NULO | ||
ID_receptor | bigint(20) | SÍ | NULO | ||
contenido | varchar(255) | SÍ | NULO | ||
enviar_hora | bigint(20) | SÍ | NULO | ||
creado_en | fecha y hora | SÍ | NULO | ||
actualizado_en | fecha y hora | SÍ | NULO | ||
eliminado_en | fecha y hora | SÍ | NULO |
La siguiente estructura se basa en la experiencia personal. Si hay algo inapropiado, envíenos sus valiosos comentarios.
pojo
Es fácil de entender, es la entidad correspondiente a la base de datos, pero no requiere correspondencia uno a uno con los campos de la base de datos.
reqo (objeto de solicitud), reso (objeto de respuesta)
Al realizar solicitudes a través de diferentes interfaces, los parámetros que se pueden transportar y los datos de respuesta también son diferentes, por lo que se diseñan una entidad de solicitud y una entidad de respuesta correspondientes para cada interfaz.
Lo siguiente es mi entendimiento personal.
Controlador
La responsabilidad principal es aceptar los parámetros de solicitud de la solicitud, convertirlos en reqo, realizar una verificación simple de los parámetros de la solicitud (mi definición personal es una verificación que no tiene nada que ver con la base de datos, como no nula, distinta de cero), llamar la función de la capa de Servicio para obtener el resultado de pojo, y La conversión del resultado de pojo se encapsula y se devuelve en reso.
Servicio
La responsabilidad principal es encapsular aún más la interfaz de la capa Dao y proporcionar una interfaz común para que la llame el Controlador. Los datos devueltos pueden ser pojo. La verificación de datos debe realizarse en el Servicio, como (agregar nuevos usuarios y verificar si). se repite el nombre de usuario).
dao
Básicamente, un método aquí corresponde directamente a una declaración SQL sin ninguna verificación. Los datos recibidos se consideran confiables (han sido verificados por los parámetros de las capas Controlador y Servicio), y los datos devueltos pueden ser POJO.