第1章 技术的选型和环境搭建 1
$ u7 s( s% x: x7 W$ O& Y6 J1.1 技术选型 1
' \6 a2 V$ `( G! M" h8 u0 L5 E1.1.1 前端框架选型 2
5 n4 `" d3 z0 {$ |' W- @1.1.2 后端框架选型 3 ' I" r, u; A( D8 F' s
1.1.3 数据库选型 3 / g7 z% y' Q% u; k
1.2 环境搭建 5
+ d3 d$ Q v' B: }0 U1.2.1 基础开发环境安装 5
/ b7 z4 J- Z( u1.2.2 IDE 的选择 7 & L% D7 D3 r {
1.2.3 字体的选择 8 + ]- w- ^7 g6 @/ k+ {
1.2.4 定义通用的代码格式 9
; p7 u! ~' I% e4 ] i. T3 z1.3 工程项目的结构 10
) w- ]. K" A% E$ W: I: t) B1.3.1 前端项目 10
+ b0 k; ~' N. a: _& y; `1.3.2 后端项目 13 7 I. q" i3 u- w8 w
1.3.3 整体项目工程的文件结构 14 # P% a( ]! C; g3 `
第2章 使用Angular快速构造前端原型 17
9 r; I9 ~) {/ D2.1 Angular 基础概念 17
% I4 Y% Z8 [1 Y: ]% \. l* M2.1.1 安装 Angular CLI 17 $ X* F$ V: `& w* }+ j6 z
2.1.2 依赖性注入 22 $ B! E7 t+ D' w2 q# X! W i
2.1.3 组件 27
8 f% W0 I9 }& x1 N+ K1 e% R, X+ H2.1.4 指令 28
: `: F" _/ e( m2.1.5 管道 30 # n! m4 @% P8 o% K# M$ v( v5 |7 M
2.1.6 模块 31
/ ]7 p/ s) R1 {! p/ T2.1.7 模板驱动型表单 33
5 o5 n* m" E; ]& h0 ]2.1.8 响应式表单 46 % j$ z' `' o0 g& L) k2 o- d1 v
2.2 Angular Material 介绍 55
/ c; |/ `" }) E+ x6 H2.2.1 组件类别 55
) ]& [3 m" i; c* s2.2.2 布局控件:Sidenav 57
( K u% w8 v+ }0 P. ]# f) {* @2.2.3 Flex 布局和 Angular Flex-layout 60
1 p) f/ | T8 m" \. h* c2 V2.2.4 封装 Header/Footer/Sidebar 62
. U) E# M; ^! Y4 S. x9 U1 o2.3 添加主题支持 78 $ o. [% f9 k) o8 f* p& T. u, A
2.3.1 Material Design 中对于主题的约束 79 ( A. D s9 D- Y$ r6 Y; |
2.3.2 主题的明与暗 79 " h/ n4 R- N% W- A
2.3.3 Angular Material 中的主题 80
0 |0 `9 G' ]8 L0 w' n2.4 容器化 Angular 应用 83 % X( ?5 Z! M+ l) g/ z
2.4.1 什么是容器 83
9 c ]& ^, x) {- w T9 ? y2.4.2 安装 Docker 84 2 ]( C' m- m5 v8 N- T5 K t
2.4.3 镜像仓库加速 85
4 }. Q, d2 b3 F. L: {* e* Z" b, }& U) O2.4.4 创建 Angular 的 Docker 镜像 85 _0 O2 D) o' k# |/ C
2.4.5 启动容器 87
. g) A' g# g2 `6 {0 v, f2.4.6 使用 docker-compose 组织复杂的环境配置 88
* l' ~/ J I/ \: E4 z/ T9 W0 g) J2.4.7 使用 .dockerignore 文件 91 ! ^) b4 g- [; j; Y& }. y+ p" [0 V
第3章 何谓后端 92
' D6 j5 O6 ? U5 {- S1 x6 ^* p4 }- L3.1 创建一个 Spring Boot 工程 93 3 k$ f& ~3 Q& y2 p/ P5 ^
3.1.1 通过 Gradle 创建 93 8 ?9 u$ f! Q6 ~5 ?: B( t/ C9 `3 N* w
3.1.2 通过 Maven 创建 99 $ ]2 i& E N3 C9 C0 ~
3.1.3 通过 IDE 创建 103 ; z% R2 U% R6 Y- Q
3.1.4 工程项目的组织 105 [, I9 ?4 o5 Y2 \6 t |
3.2 API 的构建可以如此简单 109 & |: F$ x3 Y. _1 F
3.2.1 API 工程结构 109 $ m7 D% N6 \( W* W4 @
3.2.2 领域对象 111
& h" |; _9 q3 `4 j9 _1 ]3.2.3 构造 Controller 112
& h% ?$ F3 J0 h T: X4 Q- I e3.2.4 启动服务 113
" P; W" A8 c9 _3.2.5 测试 API 115 1 V0 e9 s6 O$ g: g
3.3 MongoDB 支撑的 API 116
+ p H" _9 s/ U+ A5 H( W7 w3 |4 B3.3.1 什么是 NoSQL 116
5 [$ w% E0 q( }' f. H3.3.2 MongoDB 的集成 119
1 R( C2 a, \% W3.3.3 HATEOAS 124
4 s; W$ S* S+ ]6 {3.3.4 “魔法”的背后 129 " |/ b$ r! _5 x J
3.3.5 让后端也能热更新 132 $ ^# s- v- h a, J/ K$ n. k* z
3.4 容器化后端 135
' q& O+ S* x: S5 |- |: F3.4.1 手动创建镜像 135
% v9 V: T* B9 t6 }- T" m1 ]5 T9 V3.4.2 使用 Gradle 自动化 Docker 任务 137 & R. L+ S5 Q7 ?4 F0 T3 U R
3.4.3 使用 docker-compose 组合服务 141
1 E& z+ X4 A0 a' [' E. _3.4.4 IDEA 中的 Gradle 支持 142
+ L1 P3 z6 ^+ o3 `3.4.5 在容器中调试 143 ) I9 d; N. S0 `* Z J. `9 ]
第4章 登录鉴权功能的构建 145 % u8 A6 J; Q7 ]) T% F2 s% k. n1 E' ?, F
4.1 模块化和组件化 145
" R( A: r \! k; ?' H$ t4.1.1 登录的领域模型构建 145 7 ?/ s: v2 G/ i5 S$ M8 y
4.1.2 前端页面设计 147 : H. {) b: Y# \" Z, m9 v6 W8 V
4.2 响应式编程初探 166
- b7 y( H3 F }9 H. y/ `4.2.1 不同的视角 166 % F2 n! y2 h+ G1 ^# H
4.2.2 实现一个计数器 169
s( f. d- U# s% |7 c4 _3 x- H4.2.3 为什么要使用 Rx 177
7 f4 A% C: H" C3 R7 z4.2.4 Observable 的性质 178 # K2 O/ b' `7 x# S8 f# L
4.2.5 RxJS 的调试 180
1 |2 A- q2 m9 s+ }4 j5 h4.3 前端服务层 184
$ o& K3 _+ \3 Y/ p9 n6 D& E* n4.3.1 构建“伪”服务 184 / k1 b: q# u5 B3 o5 x
4.3.2 构建“聪明组件” 188
: v1 ?' B* U, c/ {7 F5 n4.3.3 路由处理 192
! Y. G, N9 Y* t$ a1 W4.4 完成忘记密码前端设计 194
. W9 A3 v. O" u4.4.1 使用 RxJS 打造短信验证码控件 194
1 u7 @9 l( [( R+ r% j* O6 c/ A7 }4.4.2 忘记密码向导“笨组件” 199
& ]; e2 Y. V0 G4 ]! G4.4.3 忘记密码的“聪明组件” 203
/ n9 k% E% a2 T+ b( }
5 |3 n4 A" a7 @/ c; Q& g第5章 构建后端API 205 0 F0 M3 _" X' \! B; b5 R
5.1 HyperMedia API 与传统 API 205
4 E9 `/ x, m) s2 i, d5.1.1 领域对象 205
& N* S$ ~+ \- K3 |% n5 t5.1.2 API的可见控制 211 ( J0 J$ [6 l$ Q5 x! j- `+ z. ~
5.1.3 传统的 API 实现模式 218 , v$ ~7 G# P$ I2 s3 S* g, R
5.2 Spring Data 中的查询 221 / i# {' Q' \3 p8 l; V0 Q+ N
5.2.1 基础概念——Repository 221
1 x- m) V2 x/ j7 X8 k5.2.2 查询方式 223 : ?, I8 r, p# H u/ w1 ~; T
5.2.3 复杂类型查询 226 7 M7 s5 J) y9 S, u T" N; U2 G3 ?2 n
5.2.4 自定义查询 228
2 ?* @( S0 K) q( e' N: Y6 Q) C5.2.5 自定义 Repository 229 2 K$ T. V$ B& L) c+ f& o8 s
5.3 Controller 的构建 230 $ C" V: N& X5 [
5.3.1 改造 TaskRepo 和 UserRepo 230 ' g' g, H" S6 U! R+ p
5.3.2 实现 Controller 231 . Q. q4 Y* {0 a
5.3.3 登录 234
6 J- K9 |( v3 H1 P; O5 z& [/ i1 j5.3.4 注册 235 + z) k' N& Q, }: A7 E/ _) H2 u
5.3.5 忘记密码第一步:验证手机 236
% O" C' [9 S/ p% r6 l5.3.6 忘记密码第二步:重置密码 244 ( h9 ^- C C% T3 ?
5.3.7 API 的异常处理 246
8 y% K) N+ e, x. v. Z1 H5.4 构建安全的 API 接口 255 3 P" S- v) O3 m6 @8 c6 s
5.4.1 为什么要保护 API 256 6 J3 ]0 B6 t7 ?8 z9 a* e
5.4.2 什么是JWT 256
( _/ W/ R8 {, a4 w5.4.3 JWT的生成和解析 259
, y! F+ E" n# m) n' @6 f5 D5.4.4 权限的设计 260 " s: r) t% m& w/ g h/ [+ f
5.4.5 使用 Spring Security 规划角色安全 261
2 `: S7 t" w) v% I( r5 \' f5.4.6 在 Spring Boot 中启用 Spring Security 265
$ F8 T0 O5 @- b' f6 c) W5.4.7 改造用户对象 266 . N$ p% y, J1 q) y8 S
5.4.8 构建 JWT token 工具类 268 , O, l+ e h8 X( ?" n' v! i
5.4.9 如何检查任何请求的授权信息 272
% [! c# u' ~# ?% q5.4.10 得到用户信息 275 ( E6 }( i( V/ D k
5.4.11 配置 Spring Security 277 5 u. N9 a8 p+ q
5.4.12 使用 JWT 进行 API 访问 292 & ]8 v! n) a3 D& Q
5.5 跨域和 API 文档 305
8 j( h9 A( l) g; p5.5.1 跨域解决方案——CORS 305
/ R! ]! _! |* d! y- Q5.5.2 API 文档 309
7 Q/ y+ L* ~! }* l第6章 前端和API的配合 322 + E& v2 h4 ^( p C
6.1 响应式的 HTTP API 处理 322 ^4 y0 g+ D& ~2 k( W% |
6.1.1 Angular 中的 HTTP 服务 322
: c& ^1 m ?- y8 d3 _% L4 S6.1.2 Angular 的开发环境配置 323 5 f* M s% ~3 Y
6.1.3 在前端服务中使用 HttpClient 327
* E% \5 a6 k- H' k6.1.4 更改注册表单控件 331 / C/ v7 b$ l0 E8 I* _1 w9 @/ f
6.2 RxJs进阶 332
javazx.com
7 g) J" h+ t7 |: J* {8 H6.2.1 改造登录表单 332
, {' {0 M( k3 O/ O+ K6.2.2 RxJs的高阶操作符 333 3 P$ D, Y* e1 P' R- t3 N+ S" w0 F
6.2.3 合并操作符 339
9 s; e% Z8 s2 Q# ~& X6.3 HTTP 拦截 342
9 F' j3 w# Y2 j( a2 `6.3.1 实现一个简单的 HttpInterceptor 342 ) e) ]8 A6 s0 f/ [( I6 ?9 |8 v
6.3.2 鉴权HttpInterceptor 343 7 x6 p8 l0 E6 r$ U2 a
6.3.3 一个日志拦截器 345 * v* h1 U8 Y, W: @! `' n# v7 @1 h( M
6.4 Angular 路由 346 , @) T2 Z) Q5 Q, F
6.4.1 基准锚链接 346
& F. d) q5 t% P0 T6.4.2 Router 模块的简介 347 ! c9 m' Z8 g# O. t5 q3 `
6.4.3 获取父路由的参数 354
* N/ m' `7 B, P' i6.4.4 获得前一个路由 354 $ l: o' A8 U9 ^' S8 B( {# m
6.4.5 Activated Route 354
z" b; z N+ L6 \( N1 s$ ]6.5 安全守卫 355
/ [: i: R$ v1 @6.5.1 激活守卫 356 $ [8 N* A! K) v1 N; C# T
6.5.2 激活子路由守卫 357 ) A: O; A; k) t1 Y" e
6.5.3 加载守卫 358 ( t' [4 x& ^/ h; {' |+ B
6.5.4 退出守卫 359 - W; i* G: E7 a& V: T
6.5.5 数据预获取守卫 359 9 l$ c) a6 j1 @& m
第7章 后端不只是API 361
# U/ B0 [1 s2 C7.1 缓存 361 # P0 w9 u8 ~6 @
7.1.1 配置 Cache 362 1 K j! I' S; j0 m
7.1.2 常用的缓存注解 364
+ H: t9 ?2 @: c$ R" E! h% {; H7.1.3 测试缓存是否生效 366
- s _0 n) P) U' E7.2 Redis 作为缓存框架 368 2 V$ A$ E1 j8 l( Y& f4 @. {& {
7.2.1 Redis 的安装配置 369 % U* x+ l7 s; i
7.2.2 在 Spring Boot 中集成 Redis 370
, X$ K/ d9 t+ b6 E/ t7.2.3 Redisson 373
, o. Y) B. J2 t# X/ J4 o7.3 使用 ElasticSearch 提升搜索性能 375
$ `1 E9 g* O+ Q7.3.1 配置 375 - W( F- E1 a7 x7 ?3 |2 {' w
7.3.2 构建用户查询 API 379
* O( b+ v4 l; v( _; _; q3 t h0 b7.4 Spring Boot Actuator 和数据审计 390
! w# a& R4 s- U: A7.4.1 初窥审计事件 390 : \2 j: p+ [9 o& @3 u$ c
7.4.2 实现应用的数据审计 394
2 T' M8 j& f- _* \- Y7.4.3 JaVers 和 Spring Boot 集成 396 $ x$ y/ c' H( _6 y7 u5 K5 m
7.5 WebSocket 实时通信服务 401
, ?2 F* j& D9 |5 |0 y4 }7.5.1 HTTP 和 WebSocket 的区别和联系 402
9 \# m8 K0 h. k7.5.2 何时使用 WebSocket 403
- }" o6 A; Q9 l3 F7.5.3 STOMP 403
* H! L. {+ o) D7.5.4 WebSocket 配置 404 $ b+ d1 h X. a: ?' P! m7 ^
7.5.5 WebScoket 安全 406
9 B1 F2 \) y& e$ ^2 `* z7.5.6 建立一个实时消息 Controller 409 " X' t/ M' c. N; p* x% k' c3 L
7.5.7 测试 WebSocket 409 ) B: ^/ K: y( ~: d7 v) B1 A
7.6 Spring Boot 的自动化测试 411 / F% k& Q* }( m
第8章 前端的工程化 422 / ]+ @7 D4 m3 Y+ ^2 W' l y
8.1 使用 Redux 管理状态 423 ' b8 b' Z5 i% @5 ~3 I2 X
8.1.1 何时需要使用 Redux 423 $ U; t* G9 O, W- l, R
8.1.2 Redux 的核心概念 424
" \( k, w1 q" t1 s( T8.1.3 在 Angular 中使用 Redux 429 $ ^% C) n& w. i, ^; m4 @
8.1.4 Selector——状态选择器 434
4 ~% w( ]3 @& `( p3 a, N+ P8.2 使用 Effects管理的副作用 437
1 s& F, W: ]2 s" @/ Q. S. p; h& i( E8.3 使用 @ngrx/entity 提升生产效率 441 + [7 u. v: V6 \$ H6 A. m |
8.4 服务端渲染 446 ! l& Q* b8 D- E5 K5 U6 H
8.4.1 Angular Universal 的工作机理 447 6 z3 T. Z: M* m' I$ t
8.4.2 安装依赖 447 3 ?* ]; z: N# |8 y/ e1 G
8.4.3 添加服务器端渲染模块 448
" F- w* O `7 W$ r' O8.4.4 使用 Node.js Express 构建服务器 450
+ @) F) }) }- A5 Q9 ?; f( R8.4.5 服务器端渲染中出现重复请求的处理 453 * C9 g5 _2 B, G- B7 O
第9章 Spring Cloud打造微服务 455 : ?" o+ y6 y2 H/ W, y4 P+ @9 p& r
9.1 微服务的体系架构 455 ' D- p) C. K5 F
9.1.1 服务即组件 456 / T3 Q) Y% k0 { Y& \+ \! O
9.1.2 微服务架构下的组织机构变化 456 g' f/ L5 p7 b$ W9 C2 P
9.1.3 产品化服务 458 4 `6 m4 N/ x* @( X6 ~- l- q2 p
9.1.4 持续集成和持续发布 458 $ o; _ E! w, h( L$ h ^; y B, J
9.1.5 监控和报警 458
c0 C5 a* @- T" k! C# s$ x4 `9.1.6 Spring Cloud 项目依赖 459
" ?9 n& O! a3 N6 c9.2 配置服务和发现服务 461
$ L0 u( \, S2 \0 |! k9.2.1 配置中心是什么 461
, y* L( Q5 j& S) M% a/ t1 E9.2.2 发现服务 465 * {0 ^( v% x" L3 g- a/ `0 S
9.3 监控服务和路由服务 472
+ p! A' t: B" g9 }7 I7 [9.3.1 Spring Boot Admin 473 $ s9 \% N2 N3 Z* w! D! j5 \
9.3.2 路由服务 478
. r0 l4 `2 D$ l# j( ?( m5 W# |# A( {/ \9.4 微服务的远程调用 485
, h- E! v$ u7 q' h7 t$ g9.4.1 Feign Client 485 % Y; @: N# c! C
9.4.2 负载均衡 490
# t; z% @% q8 R* u附录A 常见云服务使用问题汇总 492