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
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值