假设你有一个 Angular 应用程序,其中有一个组件需要从服务器获取特定模型的数据。你可以使用上述方法将一个名为queryProductModel的查询参数添加到请求中,以便服务器能够根据该参数返回相应的模型数据。
首先,你需要创建一个实现HttpInterceptor接口的拦截器。以下是一个示例的拦截器代码:
@Injectable()
export class queryProductModelInterceptor implements HttpInterceptor {
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const modifiedRequest = request.clone({
setParams: {
queryProductModel: 'true'
}
});
return next.handle(modifiedRequest);
}
}" aria-label="复制" data-bs-original-title="复制"></button>
</div>
</div><pre class="typescript hljs language-typescript"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">Injectable</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">HttpInterceptor</span>, <span class="hljs-title class_">HttpRequest</span>, <span class="hljs-title class_">HttpHandler</span>, <span class="hljs-title class_">HttpEvent</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">Observable</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'rxjs'</span>;
<span class="hljs-meta">@Injectable</span>()
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">queryProductModelInterceptor</span> <span class="hljs-keyword">implements</span> <span class="hljs-title class_">HttpInterceptor</span> {
<span class="hljs-title function_">intercept</span>(<span class="hljs-attr">request</span>: <span class="hljs-title class_">HttpRequest</span><<span class="hljs-built_in">any</span>>, <span class="hljs-attr">next</span>: <span class="hljs-title class_">HttpHandler</span>): <span class="hljs-title class_">Observable</span><<span class="hljs-title class_">HttpEvent</span><<span class="hljs-built_in">any</span>>> {
<span class="hljs-keyword">const</span> modifiedRequest = request.<span class="hljs-title function_">clone</span>({
<span class="hljs-attr">setParams</span>: {
<span class="hljs-attr">queryProductModel</span>: <span class="hljs-string">'true'</span>
}
});
<span class="hljs-keyword">return</span> next.<span class="hljs-title function_">handle</span>(modifiedRequest);
}
}</pre><p>接下来,你需要将拦截器注册到你的 Angular 应用程序中。你可以在根模块的提供商(providers)数组中注册该拦截器,如下所示:</p><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark far fa-copy rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="import { NgModule } from '@angular/core';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { queryProductModelInterceptor } from './query-product-model.interceptor';
@NgModule({
imports: [HttpClientModule],
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: queryProductModelInterceptor,
multi: true
}
]
})
export class AppModule { }" aria-label="复制" data-bs-original-title="复制"></button>
</div>
</div><pre class="typescript hljs language-typescript"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">NgModule</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">HttpClientModule</span>, <span class="hljs-variable constant_">HTTP_INTERCEPTORS</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-keyword">import</span> { queryProductModelInterceptor } <span class="hljs-keyword">from</span> <span class="hljs-string">'./query-product-model.interceptor'</span>;
<span class="hljs-meta">@NgModule</span>({
<span class="hljs-attr">imports</span>: [<span class="hljs-title class_">HttpClientModule</span>],
<span class="hljs-attr">providers</span>: [
{
<span class="hljs-attr">provide</span>: <span class="hljs-variable constant_">HTTP_INTERCEPTORS</span>,
<span class="hljs-attr">useClass</span>: queryProductModelInterceptor,
<span class="hljs-attr">multi</span>: <span class="hljs-literal">true</span>
}
]
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">AppModule</span> { }</pre><p>在上述示例中,我们将<code>queryProductModelInterceptor</code>拦截器注册为<code>HTTP_INTERCEPTORS</code>提供商,并将<code>multi</code>属性设置为<code>true</code>,以确保不覆盖其他已注册的拦截器。</p><p>现在,当你的组件通过 Angular 的 HTTP 客户端发送请求时,拦截器将在请求发出之前修改请求并添加<code>queryProductModel=true</code>的查询参数。</p><p>假设你的组件中有一个使用<code>HttpClient</code>进行数据请求的方法,示例如下:</p><div class="widget-codetool" style="display: none;">
<div class="widget-codetool--inner">
<button type="button" class="btn btn-dark far fa-copy rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-my-component',
template: `
<button (click)="getData()">Get Data</button>
`
})
export class MyComponent {
constructor(private http: HttpClient) {}
getData() {
this.http.get('https://example.com/api/data').subscribe(
(response) => {
console.log(response);
},
(error) => {
console.error(error);
}
);
}
}" aria-label="复制" data-bs-original-title="复制"></button>
</div>
</div><pre class="typescript hljs language-typescript"><span class="hljs-keyword">import</span> { <span class="hljs-title class_">Component</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/core'</span>;
<span class="hljs-keyword">import</span> { <span class="hljs-title class_">HttpClient</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">'@angular/common/http'</span>;
<span class="hljs-meta">@Component</span>({
<span class="hljs-attr">selector</span>: <span class="hljs-string">'app-my-component'</span>,
<span class="hljs-attr">template</span>: <span class="hljs-string">`
<button (click)="getData()">Get Data</button>
`</span>
})
<span class="hljs-keyword">export</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">MyComponent</span> {
<span class="hljs-title function_">constructor</span>(<span class="hljs-params"><span class="hljs-keyword">private</span> http: HttpClient</span>) {}
<span class="hljs-title function_">getData</span>(<span class="hljs-params"></span>) {
<span class="hljs-variable language_">this</span>.<span class="hljs-property">http</span>.<span class="hljs-title function_">get</span>(<span class="hljs-string">'https://example.com/api/data'</span>).<span class="hljs-title function_">subscribe</span>(
<span class="hljs-function">(<span class="hljs-params">response</span>) =></span> {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">log</span>(response);
},
<span class="hljs-function">(<span class="hljs-params">error</span>) =></span> {
<span class="hljs-variable language_">console</span>.<span class="hljs-title function_">error</span>(error);
}
);
}
}</pre><p>当你点击"Get Data"按钮时,<code>getData()</code>方法将发送一个 HTTP GET 请求到<code>https://example.com/api/data</code>。由于我们已经注册了<code>queryProductModelInterceptor</code>拦截器,该拦截器将修改请求并添加<code>queryProductModelModel=true</code>的查询参数。</p><p>在 Chrome 开发者工具中,你可以观察到实际发送的 HTTP 请求的 URL 是<code>https://example.com/api/data?queryProductModel=true</code>。这意味着拦截器成功地将查询参数添加到了请求中,并且该参数将被发送到服务器以获取相应的模型数据。</p><p>请注意,示例中的 URL(<code>https://example.com/api/data</code>)只是一个占位符,你需要将其替换为实际的服务器端点 URL,以确保请求能够到达正确的服务器。</p><p>在 Angular 的 <code>HttpInterceptor</code> 接口中,<code>intercept</code> 和 <code>handleRequest</code> 方法各自具有不同的作用。</p><ol><li><p><code>intercept</code> 方法:</p><ul><li><code>intercept</code> 方法是 <code>HttpInterceptor</code> 接口的核心方法之一。</li><li>该方法用于拦截传出的 HTTP 请求和传入的 HTTP 响应,并对它们进行处理或修改。</li><li>在 <code>intercept</code> 方法中,你可以访问到原始的请求对象和请求处理器对象,可以修改请求的头部、URL、参数等,并且可以添加、删除或修改请求的拦截器。</li><li>你可以在 <code>intercept</code> 方法中执行一些额外的逻辑,如添加身份验证信息、处理错误、记录日志等。</li><li>最后,你需要调用 <code>next.handle(request)</code> 将修改后的请求传递给下一个拦截器或最终的请求处理器。</li></ul></li><li><p><code>handleRequest</code> 方法:</p><ul><li><code>handleRequest</code> 方法是请求处理器(request handler)的一部分,用于处理最终的 HTTP 请求。</li><li>在 <code>intercept</code> 方法中的最后一步,你需要调用 <code>next.handle(request)</code>,这将触发 <code>handleRequest</code> 方法的执行。</li><li><code>handleRequest</code> 方法将接收到经过拦截器链处理后的最终请求对象,并处理该请求,发送它到服务器并等待响应。</li><li>你可以在 <code>handleRequest</code> 方法中执行一些与请求和响应相关的操作,例如发送请求、处理响应、处理错误等。</li><li><code>handleRequest</code> 方法返回一个 <code>Observable</code> 对象,用于订阅响应并对其进行处理。</li></ul></li></ol><p>综上所述,<code>intercept</code> 方法用于拦截和修改传出的 HTTP 请求,并在最后调用 <code>next.handle(request)</code> 将修改后的请求传递给下一个拦截器或最终的请求处理器。而 <code>handleRequest</code> 方法则负责实际处理最终的 HTTP 请求,并返回一个可观察对象以进行响应的处理。</p><p>通过这两个方法的组合使用,你可以在 Angular 中的 HTTP 拦截器中实现对请求和响应的拦截、修改和处理,以及执行额外的逻辑操作。</p>