フロントエンドで Java SpringBoot プロジェクトを作成します | JD Cloud Technology Team

序文

遊ぼう、騒ぎましょう、からかわないでください!Node サービスを C 側のサービスとして使用することはお勧めできません。結局のところ、これはメカニズムです。この機能は、Java >>>[スクリプト] という言語設計の最初からその使命を決定します。ここでは説明しません。JavaScript の歴史を見ればわかります。これにより、「いいね!」ができないことも決まります。言語を終了すると、少量のユーザーの訪問には耐えられますが、多数の同時訪問に耐えられるようになると、素晴らしいものになるでしょう~C端单线程多任务Javascript多线程多任务

では、なぜ依然として Node サービスを作成する必要があるのでしょうか? その主な理由は、利便性と迅速性であり、小規模プロジェクトの場合、構築が早く完了し、開発コストが小さいことです。次に、主に書くことによって次のような利点が得られます。Nest

  • デコレータ構文を学び、そのシンプルさと美しさを感じてください。
  • 新しい開発フレームワークを自ら学び、さまざまなフレームワークの長所と短所を感じ、今後の開発と選択の基礎を築きます。
  • サーバー側のトラブルシューティングの複雑さを感じて、フロントエンド設計のインスピレーションを見つけてください。

この記事では主に NestJs + Sequelize + MySQL を使用して基本操作を完了します。Node サーバーの基本構造を示します。Java SpringBoot プロジェクトの基本構造も見ることができます。これらは非常によく似ています。信じられないでしょう、サーバー開発について聞いてください。クラスメート。

良い習慣をつけましょう。記事を読むときは読む前に3回クリックしてください~[いいね、フォロー、リツイート]、コメントを読んだ後にコメントすることができます~改善を続けて穴を埋めてください~

最初のステップはプロジェクトを開始することです

サーバーを選択する際は、以前Egg.jsを使用したことがありますので、今回は選択しません。次に、Egg も Koa の開発基盤を継承しており、Express も Koa をベースにした革新的なものであり、両者は似ているはずなので、Koa と Express を選択しません。

したがって、構文が Java と同じであることを確認するために Nest.js を試してみたいと思います。さらに、以前に Java + SpringBoot プロジェクトを開発したことがあります。もちろん、古い SSH 2.0 も最初から構築しました。 Spring2.0 + Struts2 + Hibernate3.2 なら簡単に始められるはずだと思うので、振り返って書いてみます。

参考ドキュメント:

私の考えを述べさせていただきますと、まず、まだ始めたばかりで、よくわからない落とし穴もたくさんあると思いますが、まずは簡単に説明して、後でさらに深めていきます。サーバーサイドも開発したいので、やりたいならもっとやって、みんなで楽しくやってみましょう。フロントエンドフレームワークとして、中間処理層として使用する予定です。従来の基盤となるデータベースを使用します。これは比較的安定しており、信頼性が高く、比較的馴染みのあるものです。ここでは新しいものは使用しません。結局のところ、データベースはすべての基礎です。NestGraphqlMySQL

具体的な実装手順について話しましょう。

1. [必須]データベースはありません。インターフェイス要求は完了しており、実行できます。
2. [必須]基本データベースを作成しデータベースにアクセスして機能を完了します。MySQL@nestjs/sequelize增删改查CRUD
3. [オプション] 正確なデータクエリを実現するために API クエリを処理する予定です。これは非常に普及していますが、ほとんど使用されていません。まずは体験してから、直接ビジネスで使用できるようにする予定ですGraphql
4. [オプション] API ドキュメントを自動的に生成し、フロントエンド サービスとバックエンド サービスの共同デバッグとテストを迅速に実行するためのアクセス権。Swagger
Swagger は、RESTful Web サービスを設計、構築、文書化、および利用するためのオープンソース ツールです。
5. 【オプション】インターフェースリクエスト、データベース最適化処理
◦ リクエストの オフロード、データベース書き込みロック、および同時プロセス処理
リクエストとレスポンスを均一に処理し、認証処理、リクエストのインターセプトなどの操作を実行するミドルウェアを 追加しました。middleware
◦ データベース 分割バックアップとデータベース災害管理。プライマリ、バックアップ、災害に分割されます。
データベースの読み取りと書き込みを分離し、データを二重に書き込み、データベースのキャッシュ機構を確立し、処理を使用するredis

さらに最適化ポイントを追加することも歓迎です。一緒に話し合います~興味があれば、コードの追加を手伝ってください~

大まかな方向性を決めた後、整理を始めました。後から追加するだけで、基本機能の完成を優先する必要があります。Nest.js 公式 Web サイト: https://docs.nestjs.com/早速、詳細を見ていきましょう。

# 进入文件夹目录
cd full-stack-demo/packages
# 安装脚手架
npm i -g @nestjs/cli
# 创建基础项目
nest new node-server-demo 
# 进入项目 
cd new node-server-demo 
# 运行项目测试
npm run start:dev

混乱しないように、不要なものをいくつか削除し、単純なものから始めて、次に複雑なものにしましょう。次に、このフレームワークの感触を得るために簡単な例を作成し、後で完全なコードを公開します。さっそく始めましょう! 調整後のディレクトリ構成:

- パブリックメソッドクラス common
- 構成クラスファイル config
- コントローラー。フロントエンドによって開始されたさまざまなリクエストを処理するために使用されます。 controller
- データベースとの対話ロジックを処理するために使用されるサービス クラス service
- DTO (データ転送オブジェクト) を使用して、入力データを検証し、転送されるフィールドまたは形式を制限できます。 dto
- オブジェクト関連の属性情報を記述するために使用されるエンティティ クラス entities
- Spring の Bean と同様に、すべてのサービス クラスとコントローラー クラスを登録するために使用されるモジュール module
◦ これら は完全に同等ではなく、2 つの実装メカニズムは異なります。これは、誰もが理解できるようにするためのものです。
- ネストスタートアップポータル main.ts
- typescript 関連の宣言タイプ types





デモを書いているだけなので、急げばコメントを書かなくても済みます 一目で理解できる気がします Java SpringBootの書き方と非常に一致しています コードの一部は表示:

  • コントローラーコントローラー
// packages/node-server-demo/src/controller/user/index.ts
import { Controller, Get, Query } from '@nestjs/common';
import UserServices from '@/service/user';
import { GetUserDto, GetUserInfoDto } from '@/dto/user';

@Controller('user')
export class UserController {
  constructor(private readonly userService: UserServices) {}

  // Get 请求 user/name?name=bricechou
  @Get('name')
  async findByName(@Query() getUserDto: GetUserDto) {
    return this.userService.read.findByName(getUserDto.name);
  }
 
  // Get 请求 user/info?id=123
  @Get('info')
  async findById(@Query() getUserInfoDto: GetUserInfoDto) {
    const user = await this.userService.read.findById(getUserInfoDto.id);
    return { gender: user.gender, job: user.job };
  }
}

// packages/node-server-demo/src/controller/log/add.ts
import { Controller, Post, Body } from '@nestjs/common';
import { AddLogDto } from '@/dto/log';
import LogServices from '@/service/log';

@Controller('log')
export class CreateLogController {
  constructor(private readonly logServices: LogServices) {}

  // post('/log/add')
  @Post('add')
  create(@Body() createLogDto: AddLogDto) {
    return this.logServices.create.create(createLogDto);
  }
}


  • データ転送データ転送オブジェクト
// packages/node-server-demo/src/dto/user.ts
export class CreateUserDto {
  name: string;
  age: number;
  gender: string;
  job: string;
}

// 可以分开写,也可以合并
export class GetUserDto {
  id?: number;
  name: string;
}

// 可以分开写,也可以合并
export class GetUserInfoDto {
  id: number;
}


  • サービスデータベース対話処理クラス
// packages/node-server-demo/src/service/user/read.ts
import { Injectable } from '@nestjs/common';
import { User } from '@/entities/User';

@Injectable()
export class ReadUserService {
  constructor() {}

  async findByName(name: string): Promise<User> {
    // 可以处理判空,从数据库读取/写入数据,可能会被多个 controller 进行调用
    console.info('ReadUserService findByName > ', name);
    return Promise.resolve({ id: 1, name, job: '程序员', gender: 1, age: 18 });
  }

  async findById(id: number): Promise<User> {
    console.info('ReadUserService findById > ', id);
    return Promise.resolve({
      id: 1,
      name: 'BriceChou',
      job: '程序员',
      gender: 1,
      age: 18,
    });
  }
}


  • モジュールモジュール登録、サービスクラス/コントロールクラス
// packages/node-server-demo/src/module/user.ts
import { Module } from '@nestjs/common';
import UserService, { ReadUserService } from '@/service/user';
import { UserController } from '@/controller/user';

@Module({
  providers: [UserService, ReadUserService],
  controllers: [UserController],
})
export class UserModule {}


// packages/node-server-demo/src/module/index.ts 根模块注入
import { Module } from '@nestjs/common';
import { UserModule } from './user';
import { LogModule } from './log';

@Module({
  imports: [
    UserModule,
    LogModule,
  ],
})
export class AppModule {}


  • main.js は登録されているすべてのクラスを開始します
// packages/node-server-demo/src/main.ts
import { AppModule } from '@/module';
import { NestFactory } from '@nestjs/core';
import { NestExpressApplication } from '@nestjs/platform-express';

async function bootstrap() {
  const app = await NestFactory.create<NestExpressApplication>(AppModule);
  // 监听端口 3000 
  await app.listen(3000);
}

bootstrap();

このようにして、スタンドアロン サーバーが起動され、[ https://hoppscotch.io/ ] を使用してリクエストを作成し、リターンの効果を確認できます。Postwoman





コンソールもログを受信しました。これらのログ リクエストは後でファイルとして保存できるため、リクエスト ログも利用できるようになり、完璧です。次に、単一のマシンで泥んこをする必要がないように、データベースへの接続を開始します~.log

ステップ 2: MySQL を構成する

MySQL のインストールは実際には非常に簡単です。私のコンピュータは Mac なので、以下のスクリーンショットはすべて Mac に基づいています。まず、対応するデータベースをダウンロードします。

ダウンロード アドレス: https://dev.mysql.com/downloads/mysql/他のシステムについては、オンラインでチュートリアルを見つけることができますが、これはおそらく非常に一般的なものなので、チュートリアルは繰り返しません。

  • 注:インストールされたデータベースのパスワードを設定する必要があります。また、データベースに接続するにはパスワードが必要です。そうしないと、データベース接続が失敗します。
  • MySQL の場合はデータベースをインストールするだけなので、手順に慣れていればコマンドラインから直接操作することができます。
  • 慣れていない場合は、グラフィカル管理ツールをダウンロードしてください。
Mysql 公式コンソールhttps://dev.mysql.com/downloads/workbench/
◦ Windows では https://www.heidisql.com/download.php?download=installer を使用することもできます

PS: ワークベンチをインストールするときに、要件が上記であることがわかりました。私のコンピューターは ですMacOS 13MacOS 12

ダウンロードは無駄なので、https://downloads.mysql.com/archives/workbench/のアーカイブからのみ下位バージョンを見つけることができますデータベース サービスにもバージョン要件があり、コンピュータのバージョンに応じてサポートされているバージョンを選択できます。ここで私が選択したのは、デフォルトで最新バージョンです。それをダウンロードして直接インストールし、最後まで入力した root パスワードを覚えておいてください。8.0.31https://downloads.mysql.com/archives/community/8.0.34Next

現在のデータベースが実行されているかどうかを確認し、Workbench を起動してステータスを確認します。



1.データベースの作成

データベースには文字セットの選択があります。さまざまな文字セットと検証ルールは保存されたデータに影響を与えるため、自分でクエリを実行し、独自のデータ保存原則に従って選択できます。私はデフォルトで最も幅広いものを選択しています。確認後、右下の「適用」ボタンを選択します。

2. テーブルと属性を作成する



回答の選択肢:

テーブル内の各行を一意に識別する、テーブル内の 1 つ以上の列の組み合わせです。 PRIMARY KEY
•説明は省略します 、直訳です。 Not NULLUnique
生成列はテーブル内の特別なタイプの列であり、その値は挿入ステートメントから取得されず、他の列の値に基づいて式または関数によって生成されます。 GENERATED
CREATE TABLE people (
    first_name VARCHAR(100),
    last_name VARCHAR(100),
    full_name VARCHAR(200) AS (CONCAT(first_name, ' ', last_name))
);

  • UNSIGNEDこの数値型は正の数 (ゼロを含む) のみを格納でき、負の数は格納できません。
  • ZEROFILL数値型フィールドの先頭をゼロで埋めると、フィールドが宣言された長さに達するまでフィールドが自動的に変更されます (例: 00007)。UNSIGNED
  • BINARYバイナリ文字列の格納に使用されます。フィールドが BINARY(5) として宣言されている場合、このフィールドに格納されている文字列は長さ 5 のバイナリ文字列として処理されます。
長さ 3 の文字列を保存しようとすると、右側に 2 つのヌルバイトが埋め込まれます。
長さ 6 の文字列を保存しようとすると、長さ 5 に切り詰められます。
主な目的は、暗号化ハッシュなど、バイト単位で比較する必要があるデータを保存することです。
  • さらに、迅速な検索を容易にするためのインデックスを簡単に作成することもできます。
CREATE TABLE `rrweb`.`test_sys_req_log` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `content` TEXT NOT NULL,
  `l_level` INT UNSIGNED NOT NULL,
  `l_category` VARCHAR(255) NOT NULL,
  `l_created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  `l_updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE INDEX `id_UNIQUE` (`id` ASC) VISIBLE,
  INDEX `table_index` (`l_level` ASC, `l_category` ASC, `l_time` ASC) VISIBLE);

3. データベースに接続します

現在、Apple Silicon アーキテクチャ用の公式プリコンパイル済みバイナリは存在しないためです。その結果、現在Mac x86 チップのみをサポートしているMac M1 チップでは、リンクされたデータベース操作を使用できませんああ~、長い間苦労していろいろな書類を確認した結果、こんな落とし穴があったのですが、どうでもいいので、別の方法で開けましょう。node-oracledbTypeORM

諦めてhttps://docs.nestjs.com/techniques/database#sequelize-integrationを選択するしかありませんでした。バンバンバン〜 虎のように激しい操作で、完了しました。

  • インストールSequelize
# 安装连接库
npm install --save @nestjs/sequelize sequelize sequelize-typescript mysql2
# 安装 type
npm install --save-dev @types/sequelize

  • 基本的なデータベース情報を構成する
// packages/node-server-demo/src/module/index.ts
import { Module } from '@nestjs/common';
import { UserModule } from './user';
import { LogModule } from './log';
import { Log } from '@/entities/Log';
import { SequelizeModule } from '@nestjs/sequelize';

@Module({
  imports: [
    SequelizeModule.forRoot({
      dialect: 'mysql',
      // 按数据库实际配置
      host: '127.0.0.1',
      // 按数据库实际配置
      port: 3306,
      // 按数据库实际配置
      username: 'root',
      // 按数据库实际配置
      password: 'hello',
      // 按数据库实际配置
      database: 'world',
      synchronize: true,
      models: [Log],
      autoLoadModels: true,
    }),
    LogModule,
    UserModule,
  ],
})
export class AppModule {}


  • エンティティとデータベース間の 1 対 1 マッピング
import { getNow } from '@/common/date';
import {
  Model,
  Table,
  Column,
  PrimaryKey,
  DataType,
} from 'sequelize-typescript';

@Table({ tableName: 'test_sys_req_log' })
export class Log extends Model<Log> {
  @PrimaryKey
  @Column({
    type: DataType.INTEGER,
    autoIncrement: true,
    field: 'id',
  })
  id: number;

  @Column({ field: 'content', type: DataType.TEXT })
  content: string;

  @Column({ field: 'l_level', type: DataType.INTEGER })
  level: number; // 3严重,2危险,1轻微

  @Column({ field: 'l_category' })
  category: string; // 模块分类/来源分类

  @Column({
    field: 'l_created_at',
    type: DataType.NOW,
    defaultValue: getNow(),
  })
  createdAt: number;

  @Column({
    field: 'l_updated_at',
    type: DataType.NOW,
    defaultValue: getNow(),
  })
  updatedAt: number;
}


  • モジュール登録エンティティ
// packages/node-server-demo/src/module/log.ts
import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';
import { Log } from '@/entities/Log';
import LogServices, {
  CreateLogService,
  UpdateLogService,
  DeleteLogService,
  ReadLogService,
} from '@/service/log';
import {
  CreateLogController,
  RemoveLogController,
  UpdateLogController,
} from '@/controller/log';

@Module({
  imports: [SequelizeModule.forFeature([Log])],
  providers: [
    LogServices,
    CreateLogService,
    UpdateLogService,
    DeleteLogService,
    ReadLogService,
  ],
  controllers: [CreateLogController, RemoveLogController, UpdateLogController],
})
export class LogModule {}


  • サービスはデータベースを操作してデータを処理します
import { Log } from '@/entities/Log';
import { Injectable } from '@nestjs/common';
import { AddLogDto } from '@/dto/log';
import { InjectModel } from '@nestjs/sequelize';
import { ResponseStatus } from '@/types/BaseResponse';
import { getErrRes, getSucVoidRes } from '@/common/response';

@Injectable()
export class CreateLogService {
  constructor(
    @InjectModel(Log)
    private logModel: typeof Log,
  ) {}

  async create(createLogDto: AddLogDto): Promise<ResponseStatus<null>> {
    console.info('CreateLogService create > ', createLogDto);
    const { level = 1, content = '', category = 'INFO' } = createLogDto || {};
    const str = content.trim();
    if (!str) {
      return getErrRes(500, '日志内容为空');
    }
    const item = {
      level,
      category,
      // Tips: 为防止外部数据进行数据注入,我们可以对内容进行 encode 处理。
      // content: encodeURIComponent(str),
      content: str,
    };
    await this.logModel.create(item);
    return getSucVoidRes();
  }
}

虎の如く熾烈な作戦で、振り返るとふふふ~、ついに外界から最初のデータを受け取りました! hello world!





接続とデータの作成が成功しました。この時点で、基本的な機能は完成しました〜

ステップ 3:基本機能の実装CRUD

実際、データベースの操作ロジックと呼ばれるコンテンツの残りの部分は誰もが自分で理解できます。まずは何について話しましょうCRUD

  • C作成する
  • R読んで読んで
  • Uアップデートアップデート
  • D削除削除

以下は誰でも参照できる簡単な例です。残りはドキュメントを見つけてビジネス ロジックを実装するだけです。

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { User } from './user.model';

@Injectable()
export class UserService {
  constructor(
    @InjectModel(User)
    private userModel: typeof User,
  ) {}
  // 创建新数据
  async create(user: User) {
    const newUser = await this.userModel.create(user);
    return newUser;
  }
  // 查找所有数据
  async findAll() {
    return this.userModel.findAll();
  }
  // 按要求查找单个
  async findOne(id: string) {
    return this.userModel.findOne({ where: { id } });
  }
  // 按要求更新
  async update(id: string, user: User) {
    await this.userModel.update(user, { where: { id } });
    return this.userModel.findOne({ where: { id } });
  }
  // 按要求删除
  async delete(id: string) {
    const user = await this.userModel.findOne({ where: { id } });
    await user.destroy();
  }
}

Tips:削除する場合、バックアップ データベースとメイン データベースの 2 つのデータベースを疑似的に削除できます。マスター データベースは直接削除することも、削除を示すフラグを追加することもできます。データベースをバックアップすると、データの復元操作を実行できるように、削除せずに書き込みと更新操作のみが可能になります。

また、SQLデータベースインジェクションを防ぐために、全員が一律にデータソースを検証するか、直接エンコードする必要があり、重要なデータはMD5で直接暗号化することができ、データベースが直接ダウンロードされて漏洩することを防ぎます。SQLデータベースのセキュリティ処理に関しては、オンラインチュートリアルがたくさんありますので、探してみてください~

デプロイは比較的シンプルなので、いちいち詳しく説明する必要はありませんが、データベースはグループが提供するクラウドデータベースを利用でき、Nestは通常のノードデプロイです。

著者: JD Retail 周明良

出典:JD Cloud Developer Community 転載の際は出典を明記してください

オープンソース フレームワーク NanUI の作者がスチールの販売に切り替えたため、プロジェクトは中断されました。Apple App Store の無料リストのナンバー 1 はポルノ ソフトウェア TypeScript です。人気が出てきたばかりなのに、なぜ大手はそれを放棄し始めるのでしょうか。 ? TIOBE 10月リスト:Javaが最大の下落、C#はJavaに迫る Rust 1.73.0リリース AIガールフレンドにイギリス女王暗殺を勧められた男性に懲役9年の実刑判決 Qt 6.6正式リリース ロイター:RISC-Vテクノロジーが中米テクノロジー戦争の鍵となる 新たな戦場 RISC-V: 単一の企業や国に支配されない レノボ、Android PC の発売を計画
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/4090830/blog/10116557