Vue+Nestjs分库分表实现数据国际化

简介

本文介绍了如何利用Vue作为前端框架,NestJS作为后端框架,实现数据国际化,并采用分库分表的方式进行数据存储。

技术栈

  • Vue.js
  • NestJS
  • 数据库(示例使用MySQL)
  • i18n(国际化)

项目结构

前端(Vue)

plaintextCopy code
my-vue-app/
|-- src/
|   |-- assets/
|   |-- components/
|   |-- i18n/
|   |-- views/
|   |-- App.vue
|   |-- main.js
|-- public/
|-- package.json
|-- ...

后端(NestJS)

plaintextCopy code
my-nest-app/
|-- src/
|   |-- modules/
|   |-- controllers/
|   |-- services/
|   |-- main.ts
|-- package.json
|-- ...

数据库设计

采用分库分表的方式,存储多语言数据。

后端实现

安装依赖

cd my-nest-app
npm install --save @nestjs/typeorm typeorm mysql2

配置TypeORM

my-nest-app/src/app.module.ts中配置数据库连接。

import { TypeOrmModule } from '@nestjs/typeorm';

@Module({
  imports: [
    TypeOrmModule.forRoot({
      name: 'demo1',
      type: 'mysql',
      host: 'localhost',
      port: 3306, // default port for postgres
      username: 'root',
      password: 'root',
      database: 'demo1',
      entities: ['dist/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
    TypeOrmModule.forRoot({
      name: 'demo2',
      type: 'mysql',
      host: 'localhost',
      port: 3306, // default port for postgres
      username: 'root',
      password: 'root',
      database: 'demo2',
      entities: ['dist/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
  ],
})
export class DatabaseModule {}

实现服务

使用nest g res user来创建user模块

nest g res user

现在我们在user.entity.ts里面定义数据库实体

import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm';

@Entity()
export class User {
  @PrimaryGeneratedColumn()
  id: number;
  @Column()
  name: string;
}

启动服务看到数据库里面表是否被创建:

image.png

image.png
数据库创建成功,现在我们要根据前端请求参数来访问对应的数据库。

我们使用postman请求路由,并设置请求头:

image.png

我们现在创建一个守卫来获取到请求头里面的语言设置:

nest g gu internationalization

在internationalization.guard.ts里面设置:

image.png

import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Observable } from 'rxjs';
@Injectable()
export class InternationalizationGuard implements CanActivate {
  canActivate(
    context: ExecutionContext,
  ): boolean | Promise<boolean> | Observable<boolean> {
    // 获取请求头
    const request = context.switchToHttp().getRequest();
    const header = request.headers;
    // 获取语言
    request.lang = header.lang;
    return true;
  }
}

现在我们到user里面的user.controller.ts里面去设置:

导入并设置:

import { InjectConnection } from '@nestjs/typeorm';
import { Connection } from 'typeorm';
 constructor(
    private readonly userService: UserService,
    @InjectConnection('demo1') private conn1: Connection,
    @InjectConnection('demo2') private conn2: Connection,
  ) {}

现在我们到请求的接口里面去设置:

 @Get(':id')
  async findOne(@Param('id') id: string, @UserInfo() userInfo: any) {
    let connection: Connection;
    if (userInfo === 'zh') {
      connection = this.conn1;
    } else if (userInfo === 'en') {
      connection = this.conn2;
    } else {
      throw new Error('Invalid db parameter');
    }
    // return this.userService.findOne(+id);
    const result = await connection.getRepository(User).find({
      where: { id: +id },
    });
    return result;
  }

这里我就不进行封装了,需要使用的自行封装一下。
我们使用postman测试一下:

image.png

image.png

请求没有问题,后端就已经完成了,我们在去main.ts里面设置一下跨域就好了。

前端实现

安装依赖

vue create my-vue-app
cd my-vue-app
npm install --save vue-i18n axios element-plus

配置国际化

my-vue-app/src/utils/i18n.js中配置国际化。

import { createI18n } from "vue-i18n";

const messages = {
  en: require("./../locales/en.json"),
  zh: require("./../locales/zh.json"),
};

const i18n = createI18n({
  locale: "en", // 默认语言
  messages,
});

export default i18n;

现在去创建locales/en.json:

{
  "message": {
    "greeting": "Hello!"
  }
}

现在去创建locales/zh.json:

{
  "message": {
  "greeting": "你好!"
  }
}

在main.js里面导入i18n.js

import { createApp } from "vue";
import ElementPlus from "element-plus";
import "element-plus/dist/index.css";
import App from "./App.vue";
import i18n from "./utils/i18n";
createApp(App).use(i18n).use(ElementPlus).mount("#app");

实现组件

在app.vue里面使用:

<template>
  <div>
    <p>{{ $t("message.greeting") }}</p>
    <el-button type="primary" @click="changeLanguage('zh')">切换中文</el-button>
    <el-button type="success" @click="changeLanguage('en')">切换英文</el-button>
  </div>
</template>

image.png

现在实现语言切换

 changeLanguage(lang) {
      localStorage.setItem("lang", lang);
      this.$i18n.locale = lang;
    },

现在按钮就可以实现语言切换了

image.png

image.png

前后端联调

在src目录下面新建api目录像这样

现在我们来配置axios请求:

image.png

现在我们来配置请求路径以及请求头:

import axios from "axios";

const api = axios.create({
  baseURL: "http://localhost:3000",
});

// 请求拦截器
api.interceptors.request.use(
  (config) => {
    const lang = localStorage.getItem("lang") || "zh";
    config.headers["lang"] = lang;
    // 在请求发送之前做一些处理
    return config;
  },
  (error) => {
    // 当请求异常时做一些处理
    return Promise.reject(error);
  }
);

export default api;

在app.vue里面导入:

import api from "./api/index.js";

并创建请求函数:

data() {
    return {
      name: "",
    };
  },
  
getUserInfo() {
      api.get("/user/1").then((res) => {
        console.log(res.data[0].name);
        this.name = res.data[0].name;
      });

并且在切换语言的时候保存到localStorage里面,

 mounted() {
    this.getUserInfo();
  },
  methods: {
    changeLanguage(lang) {
      localStorage.setItem("lang", lang);
      this.$i18n.locale = lang;
      this.getUserInfo();
    },

现在打开界面:

image.png

image.png

现在,你已经配置好了Vue + NestJS的数据国际化分库分表项目。请根据实际需求和业务逻辑进行更详细的实现和优化。

  • 8
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Node.js 的 MySQL 分表分库数据访问中间件,实现MySQL数据的分布式集群储存管理。在处理海量数据、高并发访问时,获得更加优越的性能及横向扩展能力。它包含以下主要特性: 可伸缩、高扩展的架构 自动路由分库,维护数据库连接池 支持数据表的“横向”和“纵向”分表 支持“一主多从”式读写分离 分布式并行处理,成倍提升性能 对应用层隐藏数据来源及技术细节 拥有以上特点意味着,可随时通过增加普通级别数据库服务器的方式,方便地扩展整体系统性能,而无需修改业务层架构和代码。理论上TribeDB的扩展能力上线在于主库单表插入性能和主从数据同步开销。通过合理设计“横向”和“纵向”分表数据切分粒度,可轻松应对上亿级别的数据量和访问请求。 快速上手: var tribe = require('tribedb'); //载入配置文件,sync选项为true 表示同步读取解析配置文件 tribe.configure('/path/to/tribe.conf',{sync:true}); //通过数据库表名建立查询请求 var db = tribe.createQuery('my_table'); //插入封装 db.data({title:'标题'}).insert(function(err, data){   console.log(err);   console.log(data); }); //查询封装 db.where('title','标题').order_by('time','DESC').limit(1).select(function(err, data){   console.log(err);   console.log(data); }); //不使用封装的操作,直接执行sql tribe.query('SELECT * FROM user_0 WHERE id=1 LIMIT 1',function(err, data){   console.log(err);   console.log(data); }); TribeDB 通过全局唯一的表名,自动连接对应的数据库,并通过分表配置,将操作映射到涉及的分表,同时完成读写分离。 一切都由 TribeDB 自动完成,业务层不必关心数据的位置。当数据库负载过高需要添加服务器时,只需简单修改配置文件而不必修改业务代码,甚至将整个架构推倒重来。继续阅读文档详细了解如何使用。 标签:TribeDB
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值