[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept":2134,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept":2159},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":2130,"stem":2131,"id":2132,"extension":2133},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept","拦截器 (Interceptors)","拦截器可包装响应、记录日志、映射 DTO。见 guards。","技能小册",[12,13],"nestjs","intercept","2021-04-26",false,{"type":17,"value":18,"toc":2117},"minimark",[19,23,33,41,46,116,120,135,170,184,529,532,583,587,594,927,930,934,949,954,1025,1029,1080,1084,1116,1120,1127,1280,1287,1313,1316,1322,1340,1348,1440,1447,1534,1537,1541,1546,1871,1875,1878,1897,1900,1904,1959,1962,2053,2056,2060,2063,2113],[20,21,8],"h1",{"id":22},"拦截器-interceptors",[24,25,26,27,32],"p",{},"拦截器可包装响应、记录日志、映射 DTO。见 ",[28,29,31],"a",{"href":30},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fguards","guards","。",[24,34,35,36,40],{},"拦截器是 NestJS 中一种强大的 AOP（面向切面编程）组件，可以在",[37,38,39],"strong",{},"路由处理器的执行前后","插入自定义逻辑。它们基于 RxJS 的 Observable 对象，使得你可以灵活地操纵请求-响应流。",[42,43,45],"h3",{"id":44},"一拦截器的作用","一、拦截器的作用",[47,48,49,62],"table",{},[50,51,52],"thead",{},[53,54,55,59],"tr",{},[56,57,58],"th",{},"功能",[56,60,61],{},"描述",[63,64,65,76,86,96,106],"tbody",{},[53,66,67,73],{},[68,69,70],"td",{},[37,71,72],{},"方法执行前后逻辑",[68,74,75],{},"在控制器方法执行前\u002F后执行额外代码（如日志、计时、事务开启\u002F提交）",[53,77,78,83],{},[68,79,80],{},[37,81,82],{},"转换返回结果",[68,84,85],{},"统一包装响应格式、自动序列化、过滤敏感字段",[53,87,88,93],{},[68,89,90],{},[37,91,92],{},"扩展功能",[68,94,95],{},"实现缓存、响应的性能监测、请求\u002F响应脱敏",[53,97,98,103],{},[68,99,100],{},[37,101,102],{},"处理超时或流式响应",[68,104,105],{},"设置超时时间，或者对流式响应进行中间处理",[53,107,108,113],{},[68,109,110],{},[37,111,112],{},"异常映射",[68,114,115],{},"捕获异常并转换为友好格式（通常配合异常过滤器）",[42,117,119],{"id":118},"二拦截器接口与切面模式","二、拦截器接口与切面模式",[24,121,122,123,127,128,131,132,32],{},"拦截器实现 ",[124,125,126],"code",{},"NestInterceptor"," 接口，其中 ",[124,129,130],{},"intercept(context: ExecutionContext, next: CallHandler)"," 方法返回 ",[124,133,134],{},"Observable\u003Cany>",[136,137,138,149],"ul",{},[139,140,141,144,145,148],"li",{},[124,142,143],{},"context","：执行上下文，类似于守卫中的 ",[124,146,147],{},"ExecutionContext","，可以获取请求对象等。",[139,150,151,154,155,158,159,162,163,166,167,32],{},[124,152,153],{},"next","：",[124,156,157],{},"CallHandler"," 对象，它的 ",[124,160,161],{},"handle()"," 方法返回一个 ",[37,164,165],{},"RxJS Observable","，代表",[37,168,169],{},"原始控制器处理器的响应流",[24,171,172,173,176,177,176,180,183],{},"通过 RxJS 操作符（如 ",[124,174,175],{},"map","、",[124,178,179],{},"tap",[124,181,182],{},"catchError","）可以修改响应或处理副作用。",[185,186,191],"pre",{"className":187,"code":188,"language":189,"meta":190,"style":190},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import { Injectable, NestInterceptor, ExecutionContext, CallHandler } from \"@nestjs\u002Fcommon\";\nimport { Observable } from \"rxjs\";\nimport { map } from \"rxjs\u002Foperators\";\n\n@Injectable()\nexport class TransformInterceptor implements NestInterceptor {\n  intercept(context: ExecutionContext, next: CallHandler): Observable\u003Cany> {\n    \u002F\u002F 请求前逻辑（例如计时开始）\n    console.log(\"Before controller...\");\n\n    return next.handle().pipe(\n      \u002F\u002F 请求后逻辑（修改响应）\n      map((data) => ({ data, code: 0, message: \"success\" })),\n    );\n  }\n}\n","ts","",[124,192,193,246,269,292,299,312,334,381,388,414,419,443,449,509,517,523],{"__ignoreMap":190},[194,195,198,202,206,210,213,216,218,221,223,226,229,232,236,240,243],"span",{"class":196,"line":197},"line",1,[194,199,201],{"class":200},"sVHd0","import",[194,203,205],{"class":204},"sP7_E"," {",[194,207,209],{"class":208},"su5hD"," Injectable",[194,211,212],{"class":204},",",[194,214,215],{"class":208}," NestInterceptor",[194,217,212],{"class":204},[194,219,220],{"class":208}," ExecutionContext",[194,222,212],{"class":204},[194,224,225],{"class":208}," CallHandler",[194,227,228],{"class":204}," }",[194,230,231],{"class":200}," from",[194,233,235],{"class":234},"sjJ54"," \"",[194,237,239],{"class":238},"s_sjI","@nestjs\u002Fcommon",[194,241,242],{"class":234},"\"",[194,244,245],{"class":204},";\n",[194,247,249,251,253,256,258,260,262,265,267],{"class":196,"line":248},2,[194,250,201],{"class":200},[194,252,205],{"class":204},[194,254,255],{"class":208}," Observable",[194,257,228],{"class":204},[194,259,231],{"class":200},[194,261,235],{"class":234},[194,263,264],{"class":238},"rxjs",[194,266,242],{"class":234},[194,268,245],{"class":204},[194,270,272,274,276,279,281,283,285,288,290],{"class":196,"line":271},3,[194,273,201],{"class":200},[194,275,205],{"class":204},[194,277,278],{"class":208}," map",[194,280,228],{"class":204},[194,282,231],{"class":200},[194,284,235],{"class":234},[194,286,287],{"class":238},"rxjs\u002Foperators",[194,289,242],{"class":234},[194,291,245],{"class":204},[194,293,295],{"class":196,"line":294},4,[194,296,298],{"emptyLinePlaceholder":297},true,"\n",[194,300,302,305,309],{"class":196,"line":301},5,[194,303,304],{"class":204},"@",[194,306,308],{"class":307},"sGLFI","Injectable",[194,310,311],{"class":208},"()\n",[194,313,315,318,322,326,329,331],{"class":196,"line":314},6,[194,316,317],{"class":200},"export",[194,319,321],{"class":320},"sbsja"," class",[194,323,325],{"class":324},"sbgvK"," TransformInterceptor",[194,327,328],{"class":320}," implements",[194,330,215],{"class":324},[194,332,333],{"class":204}," {\n",[194,335,337,341,344,347,351,353,355,358,360,362,365,367,369,372,376,379],{"class":196,"line":336},7,[194,338,340],{"class":339},"sVXei","  intercept",[194,342,343],{"class":204},"(",[194,345,143],{"class":346},"s99_P",[194,348,350],{"class":349},"smGrS",":",[194,352,220],{"class":324},[194,354,212],{"class":204},[194,356,357],{"class":346}," next",[194,359,350],{"class":349},[194,361,225],{"class":324},[194,363,364],{"class":204},")",[194,366,350],{"class":349},[194,368,255],{"class":324},[194,370,371],{"class":204},"\u003C",[194,373,375],{"class":374},"sZMiF","any",[194,377,378],{"class":204},">",[194,380,333],{"class":204},[194,382,384],{"class":196,"line":383},8,[194,385,387],{"class":386},"sutJx","    \u002F\u002F 请求前逻辑（例如计时开始）\n",[194,389,391,394,397,400,403,405,408,410,412],{"class":196,"line":390},9,[194,392,393],{"class":208},"    console",[194,395,396],{"class":204},".",[194,398,399],{"class":307},"log",[194,401,343],{"class":402},"skxfh",[194,404,242],{"class":234},[194,406,407],{"class":238},"Before controller...",[194,409,242],{"class":234},[194,411,364],{"class":402},[194,413,245],{"class":204},[194,415,417],{"class":196,"line":416},10,[194,418,298],{"emptyLinePlaceholder":297},[194,420,422,425,427,429,432,435,437,440],{"class":196,"line":421},11,[194,423,424],{"class":200},"    return",[194,426,357],{"class":208},[194,428,396],{"class":204},[194,430,431],{"class":307},"handle",[194,433,434],{"class":402},"()",[194,436,396],{"class":204},[194,438,439],{"class":307},"pipe",[194,441,442],{"class":402},"(\n",[194,444,446],{"class":196,"line":445},12,[194,447,448],{"class":386},"      \u002F\u002F 请求后逻辑（修改响应）\n",[194,450,452,455,457,459,462,464,467,470,473,476,478,481,483,487,489,492,494,496,499,501,503,506],{"class":196,"line":451},13,[194,453,454],{"class":307},"      map",[194,456,343],{"class":402},[194,458,343],{"class":204},[194,460,461],{"class":346},"data",[194,463,364],{"class":204},[194,465,466],{"class":320}," =>",[194,468,469],{"class":402}," (",[194,471,472],{"class":204},"{",[194,474,475],{"class":208}," data",[194,477,212],{"class":204},[194,479,480],{"class":402}," code",[194,482,350],{"class":204},[194,484,486],{"class":485},"srdBf"," 0",[194,488,212],{"class":204},[194,490,491],{"class":402}," message",[194,493,350],{"class":204},[194,495,235],{"class":234},[194,497,498],{"class":238},"success",[194,500,242],{"class":234},[194,502,228],{"class":204},[194,504,505],{"class":402},"))",[194,507,508],{"class":204},",\n",[194,510,512,515],{"class":196,"line":511},14,[194,513,514],{"class":402},"    )",[194,516,245],{"class":204},[194,518,520],{"class":196,"line":519},15,[194,521,522],{"class":204},"  }\n",[194,524,526],{"class":196,"line":525},16,[194,527,528],{"class":204},"}\n",[24,530,531],{},"常用的 RxJS 操作符：",[47,533,534,544],{},[50,535,536],{},[53,537,538,541],{},[56,539,540],{},"操作符",[56,542,543],{},"作用",[63,545,546,555,564,573],{},[53,547,548,552],{},[68,549,550],{},[124,551,175],{},[68,553,554],{},"修改响应数据（如包装格式）",[53,556,557,561],{},[68,558,559],{},[124,560,179],{},[68,562,563],{},"执行副作用（如日志记录），不改变响应",[53,565,566,570],{},[68,567,568],{},[124,569,182],{},[68,571,572],{},"捕获错误，转换为自定义错误响应",[53,574,575,580],{},[68,576,577],{},[124,578,579],{},"timeout",[68,581,582],{},"设置超时，抛出超时错误",[42,584,586],{"id":585},"三响应映射示例统一包装格式","三、响应映射示例：统一包装格式",[24,588,589,590,593],{},"很多 API 会返回固定格式 ",[124,591,592],{},"{ code, data, message }","，可以使用全局响应拦截器统一实现。",[185,595,597],{"className":187,"code":596,"language":189,"meta":190,"style":190},"\u002F\u002F common\u002Finterceptors\u002Fresponse.interceptor.ts\nimport { Injectable, NestInterceptor, ExecutionContext, CallHandler } from \"@nestjs\u002Fcommon\";\nimport { Observable } from \"rxjs\";\nimport { map } from \"rxjs\u002Foperators\";\n\nexport interface Response\u003CT> {\n  code: number;\n  data: T;\n  message: string;\n}\n\n@Injectable()\nexport class ResponseInterceptor\u003CT> implements NestInterceptor\u003CT, Response\u003CT>> {\n  intercept(context: ExecutionContext, next: CallHandler): Observable\u003CResponse\u003CT>> {\n    return next.handle().pipe(\n      map((data) => ({\n        code: 0,\n        data,\n        message: \"success\",\n      })),\n    );\n  }\n}\n",[124,598,599,604,636,656,676,680,699,712,724,736,740,744,752,788,827,845,864,876,884,900,910,917,922],{"__ignoreMap":190},[194,600,601],{"class":196,"line":197},[194,602,603],{"class":386},"\u002F\u002F common\u002Finterceptors\u002Fresponse.interceptor.ts\n",[194,605,606,608,610,612,614,616,618,620,622,624,626,628,630,632,634],{"class":196,"line":248},[194,607,201],{"class":200},[194,609,205],{"class":204},[194,611,209],{"class":208},[194,613,212],{"class":204},[194,615,215],{"class":208},[194,617,212],{"class":204},[194,619,220],{"class":208},[194,621,212],{"class":204},[194,623,225],{"class":208},[194,625,228],{"class":204},[194,627,231],{"class":200},[194,629,235],{"class":234},[194,631,239],{"class":238},[194,633,242],{"class":234},[194,635,245],{"class":204},[194,637,638,640,642,644,646,648,650,652,654],{"class":196,"line":271},[194,639,201],{"class":200},[194,641,205],{"class":204},[194,643,255],{"class":208},[194,645,228],{"class":204},[194,647,231],{"class":200},[194,649,235],{"class":234},[194,651,264],{"class":238},[194,653,242],{"class":234},[194,655,245],{"class":204},[194,657,658,660,662,664,666,668,670,672,674],{"class":196,"line":294},[194,659,201],{"class":200},[194,661,205],{"class":204},[194,663,278],{"class":208},[194,665,228],{"class":204},[194,667,231],{"class":200},[194,669,235],{"class":234},[194,671,287],{"class":238},[194,673,242],{"class":234},[194,675,245],{"class":204},[194,677,678],{"class":196,"line":301},[194,679,298],{"emptyLinePlaceholder":297},[194,681,682,684,687,690,692,695,697],{"class":196,"line":314},[194,683,317],{"class":200},[194,685,686],{"class":320}," interface",[194,688,689],{"class":324}," Response",[194,691,371],{"class":204},[194,693,694],{"class":324},"T",[194,696,378],{"class":204},[194,698,333],{"class":204},[194,700,701,705,707,710],{"class":196,"line":336},[194,702,704],{"class":703},"sucvu","  code",[194,706,350],{"class":349},[194,708,709],{"class":374}," number",[194,711,245],{"class":204},[194,713,714,717,719,722],{"class":196,"line":383},[194,715,716],{"class":703},"  data",[194,718,350],{"class":349},[194,720,721],{"class":324}," T",[194,723,245],{"class":204},[194,725,726,729,731,734],{"class":196,"line":390},[194,727,728],{"class":703},"  message",[194,730,350],{"class":349},[194,732,733],{"class":374}," string",[194,735,245],{"class":204},[194,737,738],{"class":196,"line":416},[194,739,528],{"class":204},[194,741,742],{"class":196,"line":421},[194,743,298],{"emptyLinePlaceholder":297},[194,745,746,748,750],{"class":196,"line":445},[194,747,304],{"class":204},[194,749,308],{"class":307},[194,751,311],{"class":208},[194,753,754,756,758,761,763,765,767,769,771,773,775,777,779,781,783,786],{"class":196,"line":451},[194,755,317],{"class":200},[194,757,321],{"class":320},[194,759,760],{"class":324}," ResponseInterceptor",[194,762,371],{"class":204},[194,764,694],{"class":324},[194,766,378],{"class":204},[194,768,328],{"class":320},[194,770,215],{"class":324},[194,772,371],{"class":204},[194,774,694],{"class":324},[194,776,212],{"class":204},[194,778,689],{"class":324},[194,780,371],{"class":204},[194,782,694],{"class":324},[194,784,785],{"class":204},">>",[194,787,333],{"class":204},[194,789,790,792,794,796,798,800,802,804,806,808,810,812,814,816,819,821,823,825],{"class":196,"line":511},[194,791,340],{"class":339},[194,793,343],{"class":204},[194,795,143],{"class":346},[194,797,350],{"class":349},[194,799,220],{"class":324},[194,801,212],{"class":204},[194,803,357],{"class":346},[194,805,350],{"class":349},[194,807,225],{"class":324},[194,809,364],{"class":204},[194,811,350],{"class":349},[194,813,255],{"class":324},[194,815,371],{"class":204},[194,817,818],{"class":324},"Response",[194,820,371],{"class":204},[194,822,694],{"class":324},[194,824,785],{"class":204},[194,826,333],{"class":204},[194,828,829,831,833,835,837,839,841,843],{"class":196,"line":519},[194,830,424],{"class":200},[194,832,357],{"class":208},[194,834,396],{"class":204},[194,836,431],{"class":307},[194,838,434],{"class":402},[194,840,396],{"class":204},[194,842,439],{"class":307},[194,844,442],{"class":402},[194,846,847,849,851,853,855,857,859,861],{"class":196,"line":525},[194,848,454],{"class":307},[194,850,343],{"class":402},[194,852,343],{"class":204},[194,854,461],{"class":346},[194,856,364],{"class":204},[194,858,466],{"class":320},[194,860,469],{"class":402},[194,862,863],{"class":204},"{\n",[194,865,867,870,872,874],{"class":196,"line":866},17,[194,868,869],{"class":402},"        code",[194,871,350],{"class":204},[194,873,486],{"class":485},[194,875,508],{"class":204},[194,877,879,882],{"class":196,"line":878},18,[194,880,881],{"class":208},"        data",[194,883,508],{"class":204},[194,885,887,890,892,894,896,898],{"class":196,"line":886},19,[194,888,889],{"class":402},"        message",[194,891,350],{"class":204},[194,893,235],{"class":234},[194,895,498],{"class":238},[194,897,242],{"class":234},[194,899,508],{"class":204},[194,901,903,906,908],{"class":196,"line":902},20,[194,904,905],{"class":204},"      }",[194,907,505],{"class":402},[194,909,508],{"class":204},[194,911,913,915],{"class":196,"line":912},21,[194,914,514],{"class":402},[194,916,245],{"class":204},[194,918,920],{"class":196,"line":919},22,[194,921,522],{"class":204},[194,923,925],{"class":196,"line":924},23,[194,926,528],{"class":204},[24,928,929],{},"然后在控制器方法中正常返回数据即可，拦截器会自动包装。",[42,931,933],{"id":932},"四使用拦截器","四、使用拦截器",[24,935,936,937,940,941,944,945,948],{},"拦截器可以通过 ",[124,938,939],{},"@UseInterceptors()"," 装饰器应用在",[37,942,943],{},"方法、控制器","或",[37,946,947],{},"全局","范围内。",[950,951,953],"h4",{"id":952},"_1-方法级","1. 方法级",[185,955,957],{"className":187,"code":956,"language":189,"meta":190,"style":190},"@Post()\n@UseInterceptors(TransformInterceptor)\ncreate(@Body() dto: CreateUserDto) {\n  return this.userService.create(dto);\n}\n",[124,958,959,968,978,994,1021],{"__ignoreMap":190},[194,960,961,963,966],{"class":196,"line":197},[194,962,304],{"class":204},[194,964,965],{"class":307},"Post",[194,967,311],{"class":208},[194,969,970,972,975],{"class":196,"line":248},[194,971,304],{"class":204},[194,973,974],{"class":307},"UseInterceptors",[194,976,977],{"class":208},"(TransformInterceptor)\n",[194,979,980,983,986,989,992],{"class":196,"line":271},[194,981,982],{"class":307},"create",[194,984,985],{"class":208},"(@",[194,987,988],{"class":307},"Body",[194,990,991],{"class":208},"() dto: CreateUserDto) ",[194,993,863],{"class":204},[194,995,996,999,1003,1005,1008,1010,1012,1014,1017,1019],{"class":196,"line":294},[194,997,998],{"class":200},"  return",[194,1000,1002],{"class":1001},"s39Yj"," this",[194,1004,396],{"class":204},[194,1006,1007],{"class":208},"userService",[194,1009,396],{"class":204},[194,1011,982],{"class":307},[194,1013,343],{"class":402},[194,1015,1016],{"class":208},"dto",[194,1018,364],{"class":402},[194,1020,245],{"class":204},[194,1022,1023],{"class":196,"line":301},[194,1024,528],{"class":204},[950,1026,1028],{"id":1027},"_2-控制器级","2. 控制器级",[185,1030,1032],{"className":187,"code":1031,"language":189,"meta":190,"style":190},"@Controller('users')\n@UseInterceptors(LoggingInterceptor)\nexport class UsersController { ... }\n",[124,1033,1034,1054,1063],{"__ignoreMap":190},[194,1035,1036,1038,1041,1043,1046,1049,1051],{"class":196,"line":197},[194,1037,304],{"class":204},[194,1039,1040],{"class":307},"Controller",[194,1042,343],{"class":208},[194,1044,1045],{"class":234},"'",[194,1047,1048],{"class":238},"users",[194,1050,1045],{"class":234},[194,1052,1053],{"class":208},")\n",[194,1055,1056,1058,1060],{"class":196,"line":248},[194,1057,304],{"class":204},[194,1059,974],{"class":307},[194,1061,1062],{"class":208},"(LoggingInterceptor)\n",[194,1064,1065,1067,1069,1072,1074,1077],{"class":196,"line":271},[194,1066,317],{"class":200},[194,1068,321],{"class":320},[194,1070,1071],{"class":324}," UsersController",[194,1073,205],{"class":204},[194,1075,1076],{"class":349}," ...",[194,1078,1079],{"class":204}," }\n",[950,1081,1083],{"id":1082},"_3-全局级无依赖注入","3. 全局级（无依赖注入）",[185,1085,1087],{"className":187,"code":1086,"language":189,"meta":190,"style":190},"\u002F\u002F main.ts\napp.useGlobalInterceptors(new ResponseInterceptor());\n",[124,1088,1089,1094],{"__ignoreMap":190},[194,1090,1091],{"class":196,"line":197},[194,1092,1093],{"class":386},"\u002F\u002F main.ts\n",[194,1095,1096,1099,1101,1104,1106,1109,1111,1114],{"class":196,"line":248},[194,1097,1098],{"class":208},"app",[194,1100,396],{"class":204},[194,1102,1103],{"class":307},"useGlobalInterceptors",[194,1105,343],{"class":208},[194,1107,1108],{"class":349},"new",[194,1110,760],{"class":307},[194,1112,1113],{"class":208},"())",[194,1115,245],{"class":204},[950,1117,1119],{"id":1118},"_4-全局级支持依赖注入","4. 全局级（支持依赖注入）",[24,1121,1122,1123,1126],{},"使用 ",[124,1124,1125],{},"APP_INTERCEPTOR"," 令牌在模块中注册，这样拦截器就可以注入其他服务。",[185,1128,1130],{"className":187,"code":1129,"language":189,"meta":190,"style":190},"import { Module } from \"@nestjs\u002Fcommon\";\nimport { APP_INTERCEPTOR } from \"@nestjs\u002Fcore\";\nimport { ResponseInterceptor } from \".\u002Fcommon\u002Finterceptors\u002Fresponse.interceptor\";\n\n@Module({\n  providers: [\n    {\n      provide: APP_INTERCEPTOR,\n      useClass: ResponseInterceptor,\n    },\n  ],\n})\nexport class AppModule {}\n",[124,1131,1132,1153,1175,1196,1200,1211,1221,1226,1238,1249,1254,1261,1268],{"__ignoreMap":190},[194,1133,1134,1136,1138,1141,1143,1145,1147,1149,1151],{"class":196,"line":197},[194,1135,201],{"class":200},[194,1137,205],{"class":204},[194,1139,1140],{"class":208}," Module",[194,1142,228],{"class":204},[194,1144,231],{"class":200},[194,1146,235],{"class":234},[194,1148,239],{"class":238},[194,1150,242],{"class":234},[194,1152,245],{"class":204},[194,1154,1155,1157,1159,1162,1164,1166,1168,1171,1173],{"class":196,"line":248},[194,1156,201],{"class":200},[194,1158,205],{"class":204},[194,1160,1161],{"class":208}," APP_INTERCEPTOR",[194,1163,228],{"class":204},[194,1165,231],{"class":200},[194,1167,235],{"class":234},[194,1169,1170],{"class":238},"@nestjs\u002Fcore",[194,1172,242],{"class":234},[194,1174,245],{"class":204},[194,1176,1177,1179,1181,1183,1185,1187,1189,1192,1194],{"class":196,"line":271},[194,1178,201],{"class":200},[194,1180,205],{"class":204},[194,1182,760],{"class":208},[194,1184,228],{"class":204},[194,1186,231],{"class":200},[194,1188,235],{"class":234},[194,1190,1191],{"class":238},".\u002Fcommon\u002Finterceptors\u002Fresponse.interceptor",[194,1193,242],{"class":234},[194,1195,245],{"class":204},[194,1197,1198],{"class":196,"line":294},[194,1199,298],{"emptyLinePlaceholder":297},[194,1201,1202,1204,1207,1209],{"class":196,"line":301},[194,1203,304],{"class":204},[194,1205,1206],{"class":307},"Module",[194,1208,343],{"class":208},[194,1210,863],{"class":204},[194,1212,1213,1216,1218],{"class":196,"line":314},[194,1214,1215],{"class":402},"  providers",[194,1217,350],{"class":204},[194,1219,1220],{"class":208}," [\n",[194,1222,1223],{"class":196,"line":336},[194,1224,1225],{"class":204},"    {\n",[194,1227,1228,1231,1233,1236],{"class":196,"line":383},[194,1229,1230],{"class":402},"      provide",[194,1232,350],{"class":204},[194,1234,1161],{"class":1235},"s_hVV",[194,1237,508],{"class":204},[194,1239,1240,1243,1245,1247],{"class":196,"line":390},[194,1241,1242],{"class":402},"      useClass",[194,1244,350],{"class":204},[194,1246,760],{"class":208},[194,1248,508],{"class":204},[194,1250,1251],{"class":196,"line":416},[194,1252,1253],{"class":204},"    },\n",[194,1255,1256,1259],{"class":196,"line":421},[194,1257,1258],{"class":208},"  ]",[194,1260,508],{"class":204},[194,1262,1263,1266],{"class":196,"line":445},[194,1264,1265],{"class":204},"}",[194,1267,1053],{"class":208},[194,1269,1270,1272,1274,1277],{"class":196,"line":451},[194,1271,317],{"class":200},[194,1273,321],{"class":320},[194,1275,1276],{"class":324}," AppModule",[194,1278,1279],{"class":204}," {}\n",[42,1281,1283,1284],{"id":1282},"五内置拦截器classserializerinterceptor","五、内置拦截器：",[124,1285,1286],{},"ClassSerializerInterceptor",[24,1288,1289,1291,1292,1294,1295,1298,1299,176,1302,176,1305,1308,1309,1312],{},[124,1290,239],{}," 提供了内置的 ",[124,1293,1286],{},"，它利用 ",[124,1296,1297],{},"class-transformer"," 的 ",[124,1300,1301],{},"@Exclude()",[124,1303,1304],{},"@Expose()",[124,1306,1307],{},"@SerializeOptions()"," 等装饰器来",[37,1310,1311],{},"控制对象序列化","，常用于隐藏敏感字段（如密码）。",[950,1314,1315],{"id":1315},"使用步骤",[1317,1318,1319],"ol",{},[139,1320,1321],{},"安装依赖（通常已有）：",[185,1323,1327],{"className":1324,"code":1325,"language":1326,"meta":190,"style":190},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","npm install class-transformer\n","bash",[124,1328,1329],{"__ignoreMap":190},[194,1330,1331,1334,1337],{"class":196,"line":197},[194,1332,1333],{"class":324},"npm",[194,1335,1336],{"class":238}," install",[194,1338,1339],{"class":238}," class-transformer\n",[1317,1341,1342],{"start":248},[139,1343,1344,1345,1347],{},"在 DTO 或实体中使用 ",[124,1346,1301],{}," 装饰器：",[185,1349,1351],{"className":187,"code":1350,"language":189,"meta":190,"style":190},"import { Exclude } from \"class-transformer\";\n\nexport class UserEntity {\n  id: number;\n  name: string;\n\n  @Exclude()\n  password: string;\n}\n",[124,1352,1353,1374,1378,1389,1400,1411,1415,1425,1436],{"__ignoreMap":190},[194,1354,1355,1357,1359,1362,1364,1366,1368,1370,1372],{"class":196,"line":197},[194,1356,201],{"class":200},[194,1358,205],{"class":204},[194,1360,1361],{"class":208}," Exclude",[194,1363,228],{"class":204},[194,1365,231],{"class":200},[194,1367,235],{"class":234},[194,1369,1297],{"class":238},[194,1371,242],{"class":234},[194,1373,245],{"class":204},[194,1375,1376],{"class":196,"line":248},[194,1377,298],{"emptyLinePlaceholder":297},[194,1379,1380,1382,1384,1387],{"class":196,"line":271},[194,1381,317],{"class":200},[194,1383,321],{"class":320},[194,1385,1386],{"class":324}," UserEntity",[194,1388,333],{"class":204},[194,1390,1391,1394,1396,1398],{"class":196,"line":294},[194,1392,1393],{"class":703},"  id",[194,1395,350],{"class":349},[194,1397,709],{"class":374},[194,1399,245],{"class":204},[194,1401,1402,1405,1407,1409],{"class":196,"line":301},[194,1403,1404],{"class":703},"  name",[194,1406,350],{"class":349},[194,1408,733],{"class":374},[194,1410,245],{"class":204},[194,1412,1413],{"class":196,"line":314},[194,1414,298],{"emptyLinePlaceholder":297},[194,1416,1417,1420,1423],{"class":196,"line":336},[194,1418,1419],{"class":204},"  @",[194,1421,1422],{"class":307},"Exclude",[194,1424,311],{"class":208},[194,1426,1427,1430,1432,1434],{"class":196,"line":383},[194,1428,1429],{"class":703},"  password",[194,1431,350],{"class":349},[194,1433,733],{"class":374},[194,1435,245],{"class":204},[194,1437,1438],{"class":196,"line":390},[194,1439,528],{"class":204},[1317,1441,1442],{"start":271},[139,1443,1444,1445,154],{},"在控制器方法上应用 ",[124,1446,1286],{},[185,1448,1450],{"className":187,"code":1449,"language":189,"meta":190,"style":190},"@Get(':id')\n@UseInterceptors(ClassSerializerInterceptor)\nfindOne(@Param('id') id: number): UserEntity {\n  \u002F\u002F 返回 user 实例，password 字段会被自动排除\n  return this.userService.findOne(id);\n}\n",[124,1451,1452,1470,1479,1503,1508,1530],{"__ignoreMap":190},[194,1453,1454,1456,1459,1461,1463,1466,1468],{"class":196,"line":197},[194,1455,304],{"class":204},[194,1457,1458],{"class":307},"Get",[194,1460,343],{"class":208},[194,1462,1045],{"class":234},[194,1464,1465],{"class":238},":id",[194,1467,1045],{"class":234},[194,1469,1053],{"class":208},[194,1471,1472,1474,1476],{"class":196,"line":248},[194,1473,304],{"class":204},[194,1475,974],{"class":307},[194,1477,1478],{"class":208},"(ClassSerializerInterceptor)\n",[194,1480,1481,1484,1486,1489,1491,1493,1496,1498,1501],{"class":196,"line":271},[194,1482,1483],{"class":307},"findOne",[194,1485,985],{"class":208},[194,1487,1488],{"class":307},"Param",[194,1490,343],{"class":208},[194,1492,1045],{"class":234},[194,1494,1495],{"class":238},"id",[194,1497,1045],{"class":234},[194,1499,1500],{"class":208},") id: number): UserEntity ",[194,1502,863],{"class":204},[194,1504,1505],{"class":196,"line":294},[194,1506,1507],{"class":386},"  \u002F\u002F 返回 user 实例，password 字段会被自动排除\n",[194,1509,1510,1512,1514,1516,1518,1520,1522,1524,1526,1528],{"class":196,"line":301},[194,1511,998],{"class":200},[194,1513,1002],{"class":1001},[194,1515,396],{"class":204},[194,1517,1007],{"class":208},[194,1519,396],{"class":204},[194,1521,1483],{"class":307},[194,1523,343],{"class":402},[194,1525,1495],{"class":208},[194,1527,364],{"class":402},[194,1529,245],{"class":204},[194,1531,1532],{"class":196,"line":314},[194,1533,528],{"class":204},[24,1535,1536],{},"也可以全局注册，让所有返回的实体都自动应用序列化规则。",[42,1538,1540],{"id":1539},"六高级用例超时处理","六、高级用例：超时处理",[24,1542,1122,1543,1545],{},[124,1544,579],{}," 操作符设置请求最大处理时间：",[185,1547,1549],{"className":187,"code":1548,"language":189,"meta":190,"style":190},"import {\n  Injectable,\n  NestInterceptor,\n  ExecutionContext,\n  CallHandler,\n  RequestTimeoutException,\n} from \"@nestjs\u002Fcommon\";\nimport { Observable, throwError } from \"rxjs\";\nimport { timeout, catchError } from \"rxjs\u002Foperators\";\n\n@Injectable()\nexport class TimeoutInterceptor implements NestInterceptor {\n  intercept(context: ExecutionContext, next: CallHandler): Observable\u003Cany> {\n    return next.handle().pipe(\n      timeout(5000), \u002F\u002F 5 秒超时\n      catchError((err) => {\n        if (err.name === \"TimeoutError\") {\n          return throwError(() => new RequestTimeoutException());\n        }\n        return throwError(() => err);\n      }),\n    );\n  }\n}\n",[124,1550,1551,1557,1564,1571,1578,1585,1592,1606,1631,1657,1661,1669,1684,1718,1736,1753,1771,1800,1823,1828,1848,1856,1862,1866],{"__ignoreMap":190},[194,1552,1553,1555],{"class":196,"line":197},[194,1554,201],{"class":200},[194,1556,333],{"class":204},[194,1558,1559,1562],{"class":196,"line":248},[194,1560,1561],{"class":208},"  Injectable",[194,1563,508],{"class":204},[194,1565,1566,1569],{"class":196,"line":271},[194,1567,1568],{"class":208},"  NestInterceptor",[194,1570,508],{"class":204},[194,1572,1573,1576],{"class":196,"line":294},[194,1574,1575],{"class":208},"  ExecutionContext",[194,1577,508],{"class":204},[194,1579,1580,1583],{"class":196,"line":301},[194,1581,1582],{"class":208},"  CallHandler",[194,1584,508],{"class":204},[194,1586,1587,1590],{"class":196,"line":314},[194,1588,1589],{"class":208},"  RequestTimeoutException",[194,1591,508],{"class":204},[194,1593,1594,1596,1598,1600,1602,1604],{"class":196,"line":336},[194,1595,1265],{"class":204},[194,1597,231],{"class":200},[194,1599,235],{"class":234},[194,1601,239],{"class":238},[194,1603,242],{"class":234},[194,1605,245],{"class":204},[194,1607,1608,1610,1612,1614,1616,1619,1621,1623,1625,1627,1629],{"class":196,"line":383},[194,1609,201],{"class":200},[194,1611,205],{"class":204},[194,1613,255],{"class":208},[194,1615,212],{"class":204},[194,1617,1618],{"class":208}," throwError",[194,1620,228],{"class":204},[194,1622,231],{"class":200},[194,1624,235],{"class":234},[194,1626,264],{"class":238},[194,1628,242],{"class":234},[194,1630,245],{"class":204},[194,1632,1633,1635,1637,1640,1642,1645,1647,1649,1651,1653,1655],{"class":196,"line":390},[194,1634,201],{"class":200},[194,1636,205],{"class":204},[194,1638,1639],{"class":208}," timeout",[194,1641,212],{"class":204},[194,1643,1644],{"class":208}," catchError",[194,1646,228],{"class":204},[194,1648,231],{"class":200},[194,1650,235],{"class":234},[194,1652,287],{"class":238},[194,1654,242],{"class":234},[194,1656,245],{"class":204},[194,1658,1659],{"class":196,"line":416},[194,1660,298],{"emptyLinePlaceholder":297},[194,1662,1663,1665,1667],{"class":196,"line":421},[194,1664,304],{"class":204},[194,1666,308],{"class":307},[194,1668,311],{"class":208},[194,1670,1671,1673,1675,1678,1680,1682],{"class":196,"line":445},[194,1672,317],{"class":200},[194,1674,321],{"class":320},[194,1676,1677],{"class":324}," TimeoutInterceptor",[194,1679,328],{"class":320},[194,1681,215],{"class":324},[194,1683,333],{"class":204},[194,1685,1686,1688,1690,1692,1694,1696,1698,1700,1702,1704,1706,1708,1710,1712,1714,1716],{"class":196,"line":451},[194,1687,340],{"class":339},[194,1689,343],{"class":204},[194,1691,143],{"class":346},[194,1693,350],{"class":349},[194,1695,220],{"class":324},[194,1697,212],{"class":204},[194,1699,357],{"class":346},[194,1701,350],{"class":349},[194,1703,225],{"class":324},[194,1705,364],{"class":204},[194,1707,350],{"class":349},[194,1709,255],{"class":324},[194,1711,371],{"class":204},[194,1713,375],{"class":374},[194,1715,378],{"class":204},[194,1717,333],{"class":204},[194,1719,1720,1722,1724,1726,1728,1730,1732,1734],{"class":196,"line":511},[194,1721,424],{"class":200},[194,1723,357],{"class":208},[194,1725,396],{"class":204},[194,1727,431],{"class":307},[194,1729,434],{"class":402},[194,1731,396],{"class":204},[194,1733,439],{"class":307},[194,1735,442],{"class":402},[194,1737,1738,1741,1743,1746,1748,1750],{"class":196,"line":519},[194,1739,1740],{"class":307},"      timeout",[194,1742,343],{"class":402},[194,1744,1745],{"class":485},"5000",[194,1747,364],{"class":402},[194,1749,212],{"class":204},[194,1751,1752],{"class":386}," \u002F\u002F 5 秒超时\n",[194,1754,1755,1758,1760,1762,1765,1767,1769],{"class":196,"line":525},[194,1756,1757],{"class":307},"      catchError",[194,1759,343],{"class":402},[194,1761,343],{"class":204},[194,1763,1764],{"class":346},"err",[194,1766,364],{"class":204},[194,1768,466],{"class":320},[194,1770,333],{"class":204},[194,1772,1773,1776,1778,1780,1782,1785,1788,1790,1793,1795,1798],{"class":196,"line":866},[194,1774,1775],{"class":200},"        if",[194,1777,469],{"class":402},[194,1779,1764],{"class":208},[194,1781,396],{"class":204},[194,1783,1784],{"class":208},"name",[194,1786,1787],{"class":349}," ===",[194,1789,235],{"class":234},[194,1791,1792],{"class":238},"TimeoutError",[194,1794,242],{"class":234},[194,1796,1797],{"class":402},") ",[194,1799,863],{"class":204},[194,1801,1802,1805,1807,1809,1811,1813,1816,1819,1821],{"class":196,"line":878},[194,1803,1804],{"class":200},"          return",[194,1806,1618],{"class":307},[194,1808,343],{"class":402},[194,1810,434],{"class":204},[194,1812,466],{"class":320},[194,1814,1815],{"class":349}," new",[194,1817,1818],{"class":307}," RequestTimeoutException",[194,1820,1113],{"class":402},[194,1822,245],{"class":204},[194,1824,1825],{"class":196,"line":886},[194,1826,1827],{"class":204},"        }\n",[194,1829,1830,1833,1835,1837,1839,1841,1844,1846],{"class":196,"line":902},[194,1831,1832],{"class":200},"        return",[194,1834,1618],{"class":307},[194,1836,343],{"class":402},[194,1838,434],{"class":204},[194,1840,466],{"class":320},[194,1842,1843],{"class":208}," err",[194,1845,364],{"class":402},[194,1847,245],{"class":204},[194,1849,1850,1852,1854],{"class":196,"line":912},[194,1851,905],{"class":204},[194,1853,364],{"class":402},[194,1855,508],{"class":204},[194,1857,1858,1860],{"class":196,"line":919},[194,1859,514],{"class":402},[194,1861,245],{"class":204},[194,1863,1864],{"class":196,"line":924},[194,1865,522],{"class":204},[194,1867,1869],{"class":196,"line":1868},24,[194,1870,528],{"class":204},[42,1872,1874],{"id":1873},"七拦截器的执行顺序","七、拦截器的执行顺序",[24,1876,1877],{},"多个拦截器可以同时应用，执行顺序为：",[136,1879,1880,1886,1891],{},[139,1881,1882,1885],{},[37,1883,1884],{},"请求前","：按照注册顺序执行（最外层 → 内层）",[139,1887,1888],{},[37,1889,1890],{},"控制器方法执行",[139,1892,1893,1896],{},[37,1894,1895],{},"响应后","：按照注册顺序的逆序执行（内层 → 最外层）",[24,1898,1899],{},"对于全局拦截器，会先于控制器\u002F方法级拦截器执行（在 NestJS 中，全局拦截器始终在最外层）。",[42,1901,1903],{"id":1902},"八与管道的区别","八、与管道的区别",[47,1905,1906,1922],{},[50,1907,1908],{},[53,1909,1910,1913,1916,1919],{},[56,1911,1912],{},"组件",[56,1914,1915],{},"主要职责",[56,1917,1918],{},"执行时机",[56,1920,1921],{},"操作对象",[63,1923,1924,1945],{},[53,1925,1926,1929,1932,1935],{},[68,1927,1928],{},"管道",[68,1930,1931],{},"验证和转换输入数据",[68,1933,1934],{},"控制器方法执行前（参数层面）",[68,1936,1937,1938,176,1941,1944],{},"请求参数（",[124,1939,1940],{},"@Body()",[124,1942,1943],{},"@Query()"," 等）",[53,1946,1947,1950,1953,1956],{},[68,1948,1949],{},"拦截器",[68,1951,1952],{},"修改输出结果、处理响应流",[68,1954,1955],{},"控制器方法执行前后",[68,1957,1958],{},"响应对象（整个 Observable 流）",[42,1960,1961],{"id":1961},"总结",[47,1963,1964,1974],{},[50,1965,1966],{},[53,1967,1968,1971],{},[56,1969,1970],{},"概念",[56,1972,1973],{},"说明",[63,1975,1976,1993,2008,2016,2033,2045],{},[53,1977,1978,1981],{},[68,1979,1980],{},"拦截器接口",[68,1982,1983,1984,1986,1987,1989,1990],{},"实现 ",[124,1985,126],{},"，",[124,1988,13],{}," 方法 + ",[124,1991,1992],{},"next.handle()",[53,1994,1995,1998],{},[68,1996,1997],{},"切面模式",[68,1999,2000,2001,176,2003,176,2005,2007],{},"使用 RxJS 操作符（",[124,2002,175],{},[124,2004,179],{},[124,2006,182],{},"）处理响应流",[53,2009,2010,2013],{},[68,2011,2012],{},"响应映射",[68,2014,2015],{},"统一包装数据结构，简化控制器",[53,2017,2018,2021],{},[68,2019,2020],{},"使用方式",[68,2022,2023,2025,2026,2029,2030,2032],{},[124,2024,939],{}," 方法\u002F控制器\u002F全局（",[124,2027,2028],{},"app.useGlobalInterceptors"," 或 ",[124,2031,1125],{},"）",[53,2034,2035,2038],{},[68,2036,2037],{},"内置拦截器",[68,2039,2040,2042,2043,2032],{},[124,2041,1286],{}," 自动排除标记字段（配合 ",[124,2044,1301],{},[53,2046,2047,2050],{},[68,2048,2049],{},"高级功能",[68,2051,2052],{},"超时控制、缓存拦截、日志记录、性能统计",[24,2054,2055],{},"掌握拦截器，你可以将横切关注点（cross-cutting concerns）从业务逻辑中抽离出来，实现更干净、可复用的代码。",[2057,2058,2059],"h2",{"id":2059},"参考文献",[24,2061,2062],{},"以下链接在编写时均可正常访问：",[47,2064,2065,2074],{},[50,2066,2067],{},[53,2068,2069,2072],{},[56,2070,2071],{},"资料",[56,2073,1973],{},[63,2075,2076,2089,2101],{},[53,2077,2078,2086],{},[68,2079,2080],{},[28,2081,2085],{"href":2082,"rel":2083},"https:\u002F\u002Fdocs.nestjs.com\u002F",[2084],"nofollow","NestJS 文档",[68,2087,2088],{},"官方",[53,2090,2091,2098],{},[68,2092,2093],{},[28,2094,2097],{"href":2095,"rel":2096},"https:\u002F\u002Fdocs.nestjs.com\u002Finterceptors",[2084],"Interceptors",[68,2099,2100],{},"本章主题",[53,2102,2103,2110],{},[68,2104,2105],{},[28,2106,2109],{"href":2107,"rel":2108},"https:\u002F\u002Fdocs.nestjs.com\u002Ffaq\u002Frequest-lifecycle",[2084],"Request lifecycle",[68,2111,2112],{},"执行顺序",[2114,2115,2116],"style",{},"html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZMiF, html code.shiki .sZMiF{--shiki-light:#E2931D;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sucvu, html code.shiki .sucvu{--shiki-light:#E53935;--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":190,"searchDepth":248,"depth":248,"links":2118},[2119,2120,2121,2122,2123,2125,2126,2127,2128,2129],{"id":44,"depth":271,"text":45},{"id":118,"depth":271,"text":119},{"id":585,"depth":271,"text":586},{"id":932,"depth":271,"text":933},{"id":1282,"depth":271,"text":2124},"五、内置拦截器：ClassSerializerInterceptor",{"id":1539,"depth":271,"text":1540},{"id":1873,"depth":271,"text":1874},{"id":1902,"depth":271,"text":1903},{"id":1961,"depth":271,"text":1961},{"id":2059,"depth":248,"text":2059},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fintercept","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FNestJS\u002Fnew\u002Fintercept.md","md",{"items":2135},[2136,2140,2144,2148,2151,2155],{"path":2137,"title":2138,"description":2139,"category":10,"score":314},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fauth","认证与授权","认证（Authentication）：确认「你是谁」（如 JWT、Session）。 - 授权（Authorization）：确认「你能做什么」（如 RBAC、策略检查）。",{"path":2141,"title":2142,"description":2143,"category":10,"score":314},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache","缓存","@nestjs\u002Fcache-manager 统一缓存 API，存储实现可插拔。",{"path":2145,"title":2146,"description":2147,"category":10,"score":314},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice","提供者与服务","Service 是最常见的 Provider，封装业务逻辑。见 module。",{"path":30,"title":2149,"description":2150,"category":10,"score":314},"守卫 (Guards) 与授权","守卫决定是否放行请求，常用于认证与授权。见 auth。",{"path":2152,"title":2153,"description":2154,"category":10,"score":314},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fconfig","配置管理（Config 模块）","@nestjs\u002Fconfig 加载 .env 并提供 ConfigService。见 工程化 env。",{"path":2156,"title":2157,"description":2158,"category":10,"score":314},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdatabase","数据库集成（以 TypeORM 为例）","Nest 通过 @nestjs\u002Ftypeorm 等包集成 ORM；生产环境用 migration，慎用 synchronize。亦可选用 Prisma、MikroORM 等（见 官方 Database）。",{"series":2160,"title":1108,"items":2161,"index":421,"prev":2222,"next":2223},"booklet\u002Fend\u002Fnestjs\u002Fnew",[2162,2164,2168,2170,2172,2176,2180,2184,2186,2190,2194,2196,2197,2201,2205,2209,2212,2216,2218],{"path":2137,"title":2138,"date":2163,"pinned":15},"2025-12-23",{"path":2165,"title":2166,"date":2167,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase","NestJS 基础","2021-03-09",{"path":2141,"title":2142,"date":2169,"pinned":15},"2025-07-04",{"path":2152,"title":2153,"date":2171,"pinned":15},"2023-08-26",{"path":2173,"title":2174,"date":2175,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcontroller","控制器与路由","2020-07-18",{"path":2177,"title":2178,"date":2179,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcron","定时任务","2023-04-12",{"path":2181,"title":2182,"date":2183,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcustom-decorators","自定义装饰器","2021-09-19",{"path":2156,"title":2157,"date":2185,"pinned":15},"2023-05-26",{"path":2187,"title":2188,"date":2189,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdeploy","部署与运维","2023-01-24",{"path":2191,"title":2192,"date":2193,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Ferror","异常处理","2020-01-28",{"path":30,"title":2149,"date":2195,"pinned":15},"2023-09-09",{"path":7,"title":8,"date":14,"pinned":15},{"path":2198,"title":2199,"date":2200,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger","日志记录","2022-10-10",{"path":2202,"title":2203,"date":2204,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmiddleware","中间件 (Middleware)","2021-11-26",{"path":2206,"title":2207,"date":2208,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule","模块系统与依赖注入","2022-06-15",{"path":2210,"title":2211,"date":2175,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fpipes","管道 (Pipes) 与数据验证",{"path":2213,"title":2214,"date":2215,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fqueue","队列（Bull）","2021-07-01",{"path":2145,"title":2146,"date":2217,"pinned":15},"2024-12-02",{"path":2219,"title":2220,"date":2221,"pinned":15},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fwebsocket","WebSocket（网关）","2022-12-14",{"path":30,"title":2149,"date":2195,"pinned":15},{"path":2198,"title":2199,"date":2200,"pinned":15}]