2.0.5 • Published 4 days ago

a2n v2.0.5

Weekly downloads
-
License
ISC
Repository
-
Last release
4 days ago

NPM    Github

该项目是基于 Node+Express 开发的服务端框架,设计理念全部基于 Java Spring 框架,实现了 Spring 的IOC、AOP等主要功能,对 Node 感兴趣的小伙伴可以前往 Github 或者 NPM 下载体验。

✨ 特性

  • 🌍 基于 NodeJs+Express 进行开发。
  • 🌈 采用了 Java 语言 Spring 框架的设计理念,实现了 Spring 中 AOP,IOC 等主要的功能。
  • ⚙️ 在体验 Spring 设计模式的同时,又可以使用 npm 强大的插件功能。
  • 🛡 使用 TypeScript 开发,提供完整的类型定义文件。
  • 📦 如果你曾经是一个Java程序员并且有一定的Js基础,那么可以以极低的学习成本使用a2n进行开发。

✨ 版本新特性

  • 🌍 弃用了项目脚手架(a2n-cli),采用更简洁的命令行工具。
  • 🌈 默认的配置文件,不需要编写任何配置,也可以运行项目。
  • ⚙️ 将自定义配置文件内容通过合并到项目配置中。
  • 📦 自定义的环境变量配置。

📦 搭建

  • 初始化 npm 环境
npm init
  • 安装依赖
npm install a2n
  • package.json 添加启动命令
"scripts": {
  "dev": "a2n dev",
  "build": "a2n build"
}
  • 运行服务
npm run dev
  • 打包
npm run build

🔨 项目结构

  • 配置文件 a2n.config.js

a2n.config.js 为项目配置文件,配置项如下,a2n有一份默认的配置文件,如果需要修改覆盖它,只需要在项目根目录创建名为 a2n.config.js 的文件

module.exports = {
  // 全局接口前缀
  baseUrl: '/api',
  // 组件扫描路径,该路径下的js,ts文件将会被容器扫描,默认src
  componentScan: 'src',
  // 服务启动端口号
  port: 8088,
  // ApiExport 装饰器配置
  apiExport: {
    // 默认生成接口前缀
    baseUrl: "/api"
  },
  // 一些自定义的配置项
  datasource: {
    url: '123lll'
  },
  // webpack配置,值可以是以下两种情况
  // 1.一个object,会通过webpack-merge与默认webpack配置进行合并
  // 2.也可以是一个函数,入参: [程序提供的默认webpack配置, webpack-merge的merge函数],返回值:最终的webpack配置
  webpack: {
    ...
  } || (baseWebpackConfig, merge) => ({...})
}
  • ts语言配置

在项目启动时,程序会在根目录默认生成一份ts配置文件,通过修改根目录下的 tsconfig.json 配置ts语言能力。

🔨 配置环境变量

在 2.0.4 版本中,a2n 集成了 dotenv 插件,可以自定义环境变量,在项目启动时,程序会自动加载根目录下的 .env 文件,该文件内容会注入到 process.env 中,如果需要自定义环境变量,可以通过命令行指定 -e 或者 --env 参数指定自定义的环境变量文件。

  • package.json
"scripts": {
  // 不指定 -e 或 --env,默认读取根目录下 .env 文件
  "dev": "a2n dev",
  // 指定任意的参数名称,例如 --env production,读取根目录下 .env.production 文件
  "build": "a2n dev --env production"
},
  • .env
APP_TITLE = a2n服务端框架
  • 在程序中获取环境变量值
console.log(process.env.APP_TITLE)

优先级:通过 -e 或 --env 指定的配置文件如果存在同名参数,则会覆盖默认的 .env 文件

🌈 如何使用

在根目录下创建 src 文件夹(a2n.config.js 中配置的 componentScan 属性,此处以 src 为例),在 src 文件夹下创建 .ts 或 .js 文件,并 export default 导出默认 Class,该 Class 将会被容器扫描注册

编写接口

import { Control, Get, Query, Post, Body, Put, Req, Res, Request, Response } from 'a2n';

/**
 * 使用@Control标记一个Class
 * Class下的@Get,@Post,@Delete,@Put,@RequestMapping方法都会被注册为接口,方法return的值作为接口返回值
 */
@Control("/user")
export default class UserControl{

  @Get("/get")
  get(@Query query: any, @Query("name") name: string){
    // 使用@Query注入url携带的参数,@Query("name")表示注入url参数中名称为name的参数
    return query.name
  }

  @Post("/post")
  get1(@Body body: any, @Body("name") name: string){
    // 使用@Body注入请求报文携带的参数,@Body("name")表示注入请求报文中名称为name的参数
    return body
  }

  @Put("/put")
  get1(@Req request: Request, @Res response: Response){
    // 使用@Req注入请求对象,@Res注入响应对象
    // 请求和响应对象使用参考express的Request、Response使用方法 https://nodejs.cn/express/4x/api/req/
  }

}

依赖注入

import { Autowired, Bean, Config, PostConstruct, BeanScope, Scope, getBean, getBeans } from "a2n";
import RoleService from "./RoleService";
import OtherBean from "./OtherBean";

// @Service将该类交给bean容器管理,与@Bean具有相同的功能,只是命名不同
@Service
// @Scope定义了bean的创建方式,BeanScope.PROTOTYPE:多例,每次获取创建新的bean
// BeanScope.SINGLETON(默认),在单例池生成bean,每次从单例池获取
@Scope(BeanScope.PROTOTYPE)
export default class UserServicer {

  // 获取一个RoleService类型的bean注入到role属性
  @Autowired(RoleService)
  role: any = null

  // 从a2n.config.js配置文件中查询datasource.url注入到url属性中
  @Config('datasource.url')
  url: string = null

  @PostConstruct
  init() {
    // bean创建并完成依赖注入后,将会执行@PostConstruct的内容
    console.log(this.role)
    console.log(this.url)
  }

  async getUser() {
    // 可以通过getBean手动获取bean
    const other = await getBean<OtherBean>(OtherBean)
    // getBeans会获取所有属于或者继承自OtherBean的bean
    const others = await getBeans<OtherBean>(OtherBean)
  }

}

拦截器

import { Bean, Interceptor, Request, Response, BeanClass } from "a2n";

/**
 * 继承Interceptor类并注入到容器中,该类会被注册为拦截器
 * return false拦截请求
 */
@Bean
export default class AuthInterceptor extends Interceptor {

  /**
   * 拦截器校验方法
   * @param req 请求对象
   * @param res 响应对象
   * @param Cons 请求进入的Control类
   * @param methodName 请求进入Control的方法名
   * @returns false:拦截,true:不拦截
   */
  doFilter(req: Request, res: Response, Cons: BeanClass, methodName: string): boolean {
    if(req.baseUrl === "/user") {
      return true
    }else {
      return false
    }
  }

}
2.0.5

4 days ago

2.0.4

9 days ago

2.0.3

11 days ago

2.0.2

11 days ago

2.0.1

22 days ago

2.0.0

22 days ago

1.0.7

2 months ago

1.0.6

5 months ago

1.0.2

6 months ago

1.0.1

6 months ago

1.0.5

6 months ago

1.0.4

6 months ago

1.0.3

6 months ago

0.0.15

11 months ago

0.0.12

1 year ago

0.0.13

1 year ago

0.0.14

1 year ago

0.0.11

1 year ago

0.0.10

1 year ago

0.0.9

1 year ago

0.0.8

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.5

1 year ago

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.1

1 year ago