Nest实现自定义装饰器

Nest内置了大量的装饰器,且绝大部分的功能都是通过装饰器来实现的。

但是如果当现有的装饰器不满足我们的需求时,我们也可以自己开发一个装饰器,接下来我们实现一个自定义的装饰器。

首先创建一个nest项目:

js 复制代码
nest new custom-decorator -p pnpm

然后在新创建的项目中新建一个decorator文件:

js 复制代码
nest g decorator aaa --flat

图中这个装饰器就是自定义的装饰器。

之前我们使用的装饰器是@SetMetadata 然后加了个Guard,将metadata取出来做一些判断。首先新建一个Guard:

js 复制代码
nest g guard aaa --flat --no-spec

然后使用reflector来取上一步设置的metadata:

之后将这个Guard加到对应的路由上,刷新页面,就可以看到我们在guard中取到设置的metadata了:

不同的metadata有不同的业务场景,有些是用于权限,有些用于其他场景。

但现在都使用@SetMetadata来设置太原始了。

这时候可以使用自定义的decorator来封装一层: 装饰器可以简化成这样:

并且将Guard中获取metadatakey改成自定义装饰器中配置的key 然后和页面路由改为/hello,刷新页面: 这样就可以看到我们设置的metadata了。

除此之外,我们发现这样使用会在一个handler上使用多个装饰器,每次使用都要写好几个类似的。我们可以将装饰器合并起来,直接在自定义装饰器中使用applyDecorators将其他的装饰器合并起来: 我们使用applyDecorators将各个装饰器串联起来,在它内部来调用传入的装饰器。

然后我们在controller中新加一个路由,并使用这个自定义的装饰器: 根据aab装饰器中的定义,第一个参数是路由名称,第二个参数是所设置的metadata的值,打开/hello1页面,然后刷新,查看控制台打印的信息: 我们可以看到设置的值user1成功打印了出来。

此时,这三个的的效果是一样的: 这就是我们说的自定义装饰器。

此外还有自定义参数装饰器: 我们使用createParamDecorator来创建一个自定义参数的装饰器,其中createParamDecorator接收的参数中,第一个是传入的值,第二个是上下文,可以用来取出responserequest对象等。

我们先来用一下,在浏览器中输入/hello3路由,刷新页面,查看页面的信息: 我们发现页面展示的信息就是装饰器返回的内容(当然这块还会根据这个返回的参数来自定义一些内容)。

上面说过createParamDecorator的第二个参数ExecutionContext是上下文,可以取出来requestresponse等对象,所以在这个参数装饰器内部,我们可以实现内置的@Param@Query@Ip@Headers等装饰器的功能。

我们来试试通过ExecutionContext来获取请求的headers,然后通过传入的参数拿到具体的请求信息:

首先我们先定义这个自定义装饰器: 然后在controller中新增一个/hello4的路由,并在其中使用@Headers装饰器,获取Accept信息: 此时我们使用了内置的装饰器@Headers和自定义装饰器,都是来获取请求体的accept信息,在页面中输入/hello4路由,刷新页面,查看控制台打印的信息: 可以看到打印出来的信息都一样。

我们再使用ExecutionContext,自定义装饰器来实现一个@Query的功能:

首先再新建一个新的自定义装饰器: 在这里面我们通过ExecutionContext获取到了请求的request信息,返回了对应的request.query[key],之后我们在controller中新建一个路由: 然后打开浏览器输入路由/hello5?aaa=yangmy&bbb=chzuze,刷新页面,查看控制台打印内容: @Query的使用一模一样。

而且这些装饰器和内置装饰器一样,也都可以使用Pipe来做参数的转换和验证:


上面我们讲的是对方法和参数的自定义装饰器,那对class的装饰器我们改如何实现?

其实也很简单,首先我们定义一个仅用于路由功能的自定义装饰器: 然后我们替换掉controller中的@Controller: 然后我们可以看到控制台中的日志,路由已被添加了一层/aaa

再次访问页面时需要在之前的路由前面加上/aaa

同样,我们还可以使用applyDecorators组合多个装饰器给controller使用: 在这个装饰器中我们不仅给这个controller设置了前置路由,同样设置了keyeeemetadata

之后我们使用这个装饰器,并向guard中添加一条信息打印:

然后浏览器访问http://localhost:3000/aaa,查看控制台日志打印: 成功访问到了在自定义装饰器中设置的值为yangmy的metadata.

总结:

方法装饰器就是传入参数,然后调用下其他的装饰器就好,比如对@SetMetadata的封装。

如果想将多个装饰器组合成一个,就使用applyDecorators这个api。

class装饰器和方法装饰器的用法是一样的。

可以使用createParamDecorator创建参数装饰器,通过它可以拿到ExecutionContext,这样我们就可以拿到request,response,从而可以实现更多的内置装饰器功能,headers,query,ip等等

相关推荐
大前端爱好者40 分钟前
React 19 新特性详解
前端
Amagi.1 小时前
Spring中Bean的作用域
java·后端·spring
随云6321 小时前
WebGL编程指南之着色器语言GLSL ES(入门GLSL ES这篇就够了)
前端·webgl
2402_857589361 小时前
Spring Boot新闻推荐系统设计与实现
java·spring boot·后端
J老熊1 小时前
Spring Cloud Netflix Eureka 注册中心讲解和案例示范
java·后端·spring·spring cloud·面试·eureka·系统架构
Benaso1 小时前
Rust 快速入门(一)
开发语言·后端·rust
sco52821 小时前
SpringBoot 集成 Ehcache 实现本地缓存
java·spring boot·后端
原机小子2 小时前
在线教育的未来:SpringBoot技术实现
java·spring boot·后端
寻找09之夏2 小时前
【Vue3实战】:用导航守卫拦截未保存的编辑,提升用户体验
前端·vue.js
吾日三省吾码2 小时前
详解JVM类加载机制
后端