是时候再认识一下Angular中的`DI`了。依赖注入原文为:Dependency injection,简称为DI,这是一种重要的应用设计模式。后期在学习Spring Boot时还会广泛的应用这一特性。Angular神奇的实现了这一模式,这使得我们在项目中能够快速的适应多种场景。比如我们在单元测试中,某个组件在构造函数中注入了`Httpclient`,则在DI的作用下我们能够在不改变组件代码的前提下,引入`HttpModule`来使用真实的后台,引入`HttpTestingModule`来手动控制Http请求。 在Angular中,除了可注入教程已经演示过的`HttpClient`、`Router`、`ActivedRoute`以外,还可以注入其它任意的**服务**。 本节中,我们将创建一个发送当前用户已注销状态的**服务**,然后将该服务应用到**拦截器**及**组件**,最终查看这个**服务**是如何正常工作的。 ## 上节答案 修正`ApiInterceptor`前先把注销的地址改成正确的81端口的地址: ```typescript +++ b/first-app/src/app/nav/nav.component.ts @@ -18,7 +18,7 @@ export class NavComponent implements OnInit { } onSubmit(): void { - const url = 'http://angular.api.codedemo.club/teacher/logout'; + const url = 'http://angular.api.codedemo.club:81/teacher/logout'; this.httpClient.get(url) ``` 然后在拦截器增加处理以`http`打头的请求 ```typescript +++ b/first-app/src/app/api.interceptor.ts @@ -19,6 +19,9 @@ export class ApiInterceptor implements HttpInterceptor { if (url.startsWith('/')) { // 如果以/打头,比如 /clazz,则直接拼接为:http://angular.api.codedemp.club/api/clazz return this.api + url; + } else if (url.startsWith('http')) { + // 如果请求以http打头,比如http://angular.api.codedemo.club/teacher/logout,则什么也不做 + return url; } else { // 如果不以/打头,比如clazz,则接拼的时候加入/ return this.api + '/' + url; ``` 此时拦截器拦截到注销的请求地址`http://angular.api.codedemo.club:81/teacher/logout`后,则什么什么也不做。这样以来`ApiInterceptor`即可以为没有请求前缀的加入前缀,也支持历史上未改造轮子直接请求后台api地址。 ## 当前问题 在继续学习之前,我们先模拟个使用情景。 - 打开浏览器,访问[http://localhost:4200/](http://localhost:4200/),使用用户名密码登录系统 - 保持半小时当前页面不动 - 半小时后再回到当前页 - 此时无论是刷新页面,还是点击注销。除不需要认证的教师管理模块外,需要认证的个人中心、班级管理、注销等功能全部失效 - 控制台报401认证失败错误 这是由于我们的后台出于安全的考虑做了一个设置:如果用户半个小时内没有与后台交互,则认为用户处于暂离状态,后台接着对处于暂离状态的用户做了注销处理。所以半小时以后,用户再次来到界面想进行一些需要认证的操作时,全部发生了401错误。 如果你没有耐心等待上半个小时,那么也可以如下操作: - 打开浏览器,访问[http://localhost:4200/](http://localhost:4200/),使用用户名密码登录系统 - 打开控制台 ---- 网络选项卡 - 如果使用的是Chrome浏览器,则勾选`Preserve log`![image-20210409140835875](https://img.kancloud.cn/12/38/12385159447334cae680fa1cbab41e61_1580x288.png) - Firefox浏览器,无需进行任何设置 - 点击注销按钮 - 使用用户名密码再次登录系统 - 来到控制台 ---- 网络,点击XHR,在搜索框中输入logout: - ![image-20210409145428784](https://img.kancloud.cn/57/07/57071e7b56c6449a813450fe6a2fed83_1796x508.png) - 然后在下面的记录上点右键 ---- Replay XHR - ![image-20210409145502682](https://img.kancloud.cn/4c/85/4c8542e5ff2533aa2fea481f86f134ed_1396x372.png) - 如果是Firefox浏览器,则选择Resend - ![image-20210409145629045](https://img.kancloud.cn/7c/a5/7ca56eb0a89e8f9ceafbf0fef61d303f_2472x360.png) 经过上述一通操作,我们模拟了后台偷偷发生的注销操作,所以神奇的事情发生了:个人中心、班级管理全部因发生401错误而无法使用,同时注销按钮也一并失灵了,而且刷新当前页面也不起作用。 本节我们将共同解决访问题:当后台主动将用户注销时,前台在请求后台时发现发生了401错误,则将显示登录界面。 | 名称 | 链接 | | -------- | ------------------------------------------------------------ | | 本节源码 | [https://github.com/mengyunzhi/angular11-guild/archive/step6.7.zip](https://github.com/mengyunzhi/angular11-guild/archive/step6.7.zip) |