go+iris+jwt+mysql+xorm+viper, uma sala de chat simples para o projeto iris, incluindo login, registro, chat privado e chat em grupo.
Primeiro, dê uma olhada na introdução do front-end abaixo deste documento para saber como operá-lo (devido à energia limitada, a IU não é particularmente fácil de usar).
Acesse o endereço de demonstração Se o status do pequeno ícone acima for normal, você poderá acessá-lo. Ele pode entrar em estado inativo e será necessário aguardar alguns segundos.
O projeto atualmente escreve apenas adaptações relacionadas ao mysql, mas usando xorm não é difícil suportar outros bancos de dados. Isso pode ser feito, mas não é necessário, se você tiver preguiça de executá-lo sozinho, é só dar uma olhada. no URL de demonstração Se você estiver interessado Ninguém tem mysql agora.
Originalmente, eu queria oferecer suporte ao sqlite, para que não houvesse necessidade de configurar os parâmetros do banco de dados, mas considerando que compilar o sqlite no Windows requer a configuração do ambiente gcc, o que é mais problemático, mas não há efeito de inicialização rápida e simplesmente não está completo , portanto, outros bancos de dados não são suportados por enquanto (algum dia adicione mais quando tiver tempo).
Portanto o projeto só precisa configurar os seguintes parâmetros
git clone https://github.com/JabinGP/demo-chatroom.git
cd demo-chatroom
// 复制config.toml.example 为 config.toml 并填写数据库信息,或者可选修改端口号
go run main.go
O padrão é a porta 8888. Após a inicialização, acesse http://localhost:8888
Usei o react, mas não usei a estrutura da UI. Muitos pequenos detalhes não são bem executados. A interface é feita de acordo com o tamanho do celular. Se você abrir o computador, poderá abrir o f12. Vamos nos contentar com isso.
A caixa de bate-papo configura a janela para rolar automaticamente para baixo, mas a API é fornecida pelo React e é considerada incompatível com muitos navegadores. Esse problema pode ser resolvido usando o navegador Chrome.
Após o registro, retorne manualmente e selecione login. O nome vermelho na caixa de mensagem é para discurso público e o nome cinza é para bate-papo privado. Você pode especificar o nome do destinatário na caixa vermelha. discurso público Após especificar, apenas os usuários correspondentes podem ver as informações.
Seu nome de usuário é exibido na caixa azul. Clique para sair diretamente.
O formato da API é baseado em um design tranquilo e a função de login é concluída usando jwt. Muitas interfaces exigem status de login e o JWT precisa ser carregado ao solicitar. conveniente para teste. O tempo de validade de emissão do JWT é definido como apenas 20 minutos. Ele precisa ser expirado.
O formato de solicitação da API é o mesmo da interface geral. Get usa Params e Post, Put, Delete, etc. usa Json no Body para passar parâmetros.
O formato de retorno é bastante controverso. Venho estudando isso há algum tempo. Algumas pessoas defendem o uso do código de status http 200 completo e a adição de um código ao conteúdo de retorno para identificar o erro, como este:
// 注册错误时
// http status 200
{
"code" : 40001 ,
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"code" : 200 ,
"msg" : "成功" ,
"data" : {
"username" : " JabinGP " ,
"id" : 3
}
}
Outros defendem o uso de códigos de status http completos para indicar erros:
// 注册错误时
// http status 400
{
"msg" : "注册用户名非法"
}
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
Na verdade, ambas as abordagens acima têm seus prós e contras:
Com base na situação acima, combinarei os dois:
Quando bem-sucedido, retorne o código de status http 200
// 注册成功时
// http status 200
{
"username" : " JabinGP " ,
"id" : 3
}
Quando ocorrer uma falha, selecione vários códigos de status comumente usados para expressar o erro, 400 (erro de solicitação), 500 (erro interno do servidor), 404 (não encontrado), 401 (falha de autenticação), classifique aproximadamente o erro e retorne Personalize um código, mensagem e detalhes nos dados para representar a causa detalhada do erro:
// 注册失败
// http status 400
{
"code" : 6 ,
"msg" : "数据检验失败" ,
"detail" : "用户名已存在"
}
// 登录失效
// http status 401
{
"code" : 8 ,
"msg" : "未认证登录" ,
"detail" : " Token is expired "
}
Após essa combinação, o retorno de chamada bem-sucedido é bem-sucedido e não há necessidade de escrever res.data.data repetidamente. O retorno de chamada de erro apenas trata erros, que podem ser avaliados pelo código de status http e podem ser codificados posteriormente, mensagens e. detalhado para lidar com erros.
A lista de APIs é a seguinte. Substitua localhost por mike.jabingp.cn ou você pode solicitar diretamente ao back-end de demonstração:
Função | Método de solicitação | endereço |
---|---|---|
Obter token de login | PUBLICAR | http://localhost:8888/v1/login |
Encontre usuários | PEGAR | http://localhost:8888/v1/user |
registrar | PUBLICAR | http://localhost:8888/v1/user |
Os próprios usuários modificam as informações | COLOCAR | http://localhost:8888/v1/user |
O usuário envia mensagem | PUBLICAR | http://localhost:8888/v1/message |
O usuário obtém informações | PEGAR | http://localhost:8888/v1/message |
O usuário obtém informações do token | PEGAR | http://localhost:8888/v1/token/info |
Parâmetros de solicitação detalhados podem ser visualizados na documentação do postman-api do demo-chatroom.
Ou visualize o código-fonte. Os parâmetros de solicitação podem ser visualizados em model/reqo
e os parâmetros de resposta podem ser visualizados em model/reso
AJAX não é a melhor escolha, pois a função de chat é melhor, mas me pediram para usar AJAX, então não escolhi a última.
O front-end do projeto é relativamente simples porque é usado apenas como demonstração.
Meu inglês não é muito bom e os comentários do código estão em inglês só porque tenho preguiça de mudar o método de entrada.
Esta é a primeira vez que uso go para desenvolver um projeto web, e também é a primeira vez que uso react para escrever o front end. Como o front end não presta muita atenção à estrutura do projeto (xjbx), não vou. coloco o código fonte. Compilei o projeto e coloquei na pasta assets para facilitar a leitura. É muito ruim, mas pode ser iniciado junto com o backend. Não há necessidade de iniciar o frontend separadamente, o que é mais conveniente para ver o. efeito. Se ainda tiver tempo, considerarei escrever uma versão minimalista em nativo para referência de todos.
A primeira vez que usei um ORM para operar um banco de dados, achei muito difícil de usar. Prefiro escrever sql manualmente. Havia muitos efeitos desejados e não consegui encontrar uma solução depois de examinar os documentos por muito tempo. Posso considerar usar o sqlx para reconstrução posteriormente.
Recentemente, fiquei mais interessado em Go e recebi a tarefa de escrever uma sala de chat simples. Descobri que atualmente existem poucas práticas de projeto em iris, apenas alguns exemplos no nível HelloWorld, então decidi usar Go para fazer isso. e, em seguida, abra-o para referência mútua. É claro que como projetar a estrutura do projeto é totalmente baseado em minha experiência limitada de desenvolvimento.
Este projeto tem os seguintes requisitos
A função de login é implementada usando JWT
desta vez. As vantagens e desvantagens do JWT
e Session
não serão discutidas em detalhes.
Baseado em AJAX é obrigatório para todos os projetos de separação de front-end e back-end, portanto, esta função não será muito discutida. O foco aqui não é atualização.
A lógica de operação do usuário é enviar os dados na sala de chat, e então os dados são enviados. A interface do chat deve exibir os dados enviados por si mesma e atualizar os dados enviados por terceiros em tempo real.
O front-end e o back-end se comunicam por meio de AJAX. Os dados de envio do front-end e os dados de envio do back-end podem ser expressos como.
Qual é o problema aqui? O problema é que o front-end só pode iniciar solicitações ativamente e o back-end só pode aceitar solicitações. Isso significa que as mensagens mais recentes nunca podem ser enviadas ativamente do back-end para o front-end em tempo real. As mensagens mais recentes só podem ser armazenadas primeiro no back-end e depois esperar que o front-end inicie uma solicitação antes que o back-end possa retornar os dados.
Como o back-end não tem a capacidade de enviar mensagens ativamente para o front-end, a solução para os usuários obterem os dados mais recentes é o front-end definir um cronômetro每隔一段比较短的时间就请求一次后台接口(轮询)
, de modo que os dados podem ser atualizados continuamente.
O front-end decidiu usar AJAX para pesquisar regularmente a interface de segundo plano para obter os dados mais recentes. Para obter dados em tempo real, o intervalo de pesquisa será小于1s
, isso trará outro problema. Sob essas solicitações frequentes, o back-end não deve transmitir todos os dados todas as vezes. Um é a eficiência de transmissão da rede e o custo do tráfego causado pelo tamanho dos dados; o julgamento do front-end sobre novos dados significa que o back-end deve retornar dados que o front-end não recebeu todas as vezes. O problema é: como o back-end sabe quais informações o front-end recebeu?
Isso requer o uso自增主键
da mensagem. O front-end só precisa carregar最后的消息的主键
recebida pelo front-end toda vez que faz uma solicitação. repetindo e aumentando automaticamente, podemos descobrir facilmente a proporção. Os dados com uma chave primária grande são os dados que o front-end ainda não recebeu.
linguagem
quadro
armazenamento de dados
tecnologia
Devido ao uso da estrutura ORM do banco de dados Xorm, as tabelas a seguir são geradas automaticamente e vêm com o campo
xxxxxx_at
Com base nos requisitos acima, duas tabelas, users
e messages
foram projetadas.
Campos-chave
Estrutura da tabela do banco de dados
Campo | Tipo | Nulo | Chave | Padrão | Extra |
---|---|---|---|---|---|
EU IA | grandeint(20) | NÃO | PRI | NULO | incremento_automático |
nome de usuário | varchar(255) | SIM | NULO | ||
senha | varchar(255) | SIM | NULO | ||
gênero | grandeint(20) | SIM | NULO | ||
idade | grandeint(20) | SIM | NULO | ||
interesse | varchar(255) | SIM | NULO | ||
criado_em | datahora | SIM | NULO | ||
atualizado_em | datahora | SIM | NULO | ||
excluído_em | datahora | SIM | NULO |
Campos-chave
Estrutura da tabela do banco de dados
Campo | Tipo | Nulo | Chave | Padrão | Extra |
---|---|---|---|---|---|
EU IA | grandeint(20) | NÃO | PRI | NULO | incremento_automático |
ID_do_remetente | grandeint(20) | SIM | NULO | ||
ID_do_receptor | grandeint(20) | SIM | NULO | ||
contente | varchar(255) | SIM | NULO | ||
hora_envio | grandeint(20) | SIM | NULO | ||
criado_em | datahora | SIM | NULO | ||
atualizado_em | datahora | SIM | NULO | ||
excluído_em | datahora | SIM | NULO |
A estrutura a seguir é baseada na experiência pessoal. Se houver algo inapropriado, envie-nos seus valiosos comentários.
pojo
É fácil de entender, é a entidade correspondente ao banco de dados, mas não requer correspondência um a um com os campos do banco de dados.
reqo (objeto de solicitação), reso (objeto de resposta)
Ao fazer solicitações por meio de interfaces diferentes, os parâmetros que podem ser transportados e os dados de resposta também são diferentes, portanto, uma entidade de solicitação e uma entidade de resposta correspondentes são projetadas para cada interface.
O seguinte é meu entendimento pessoal
Controlador
A principal responsabilidade é aceitar os parâmetros da solicitação, convertê-los em reqo, realizar uma verificação simples dos parâmetros da solicitação (minha definição pessoal é uma verificação que não tem nada a ver com o banco de dados, como não nulo, diferente de zero), chamar a função da camada de serviço para obter o resultado do pojo, e A conversão do resultado do pojo é encapsulada e retornada em reso.
Serviço
A principal responsabilidade é encapsular ainda mais a interface da camada Dao e fornecer uma interface comum para o Controlador chamar. Os dados retornados podem ser pojo. A verificação dos dados precisa ser realizada no Serviço, como (adicionar novos usuários, verificar se). o nome de usuário é repetido).
Tao
Basicamente, um método aqui corresponde diretamente a uma instrução SQL sem qualquer verificação. Os dados recebidos são considerados confiáveis (foram verificados pelos parâmetros das camadas Controlador e Serviço), e os dados retornados podem ser POJO.