MVC
SpringWeb项目结构推荐
- model:模型
- po(entity):数据库表结构类
- dao(mapper or orm):数据库单表访问类
- dal(use multiple dao):数据库多表访问层
- bo(business):业务数据类
- co(common):通用数据类
- vo(view):视图数据类(后端生成网页时使用)
- dto(transfer):传输数据类(前后端交互时使用,分为请求和响应)
- view:视图
- controller:控制器
- service:业务逻辑实例类
- manager:通用逻辑实例类
- helper:业务逻辑静态类
- utils:通用逻辑静态类
请求处理模型
JavaWeb三大组件
- Servlet
- Filter
- Listener
Servlet
Filter
Listener
请求流程描述
- web容器接收到请求后解析成Request对象
- web容器将所有请求交给DispatcherServlet处理
- DispatcherServlet通过HandlerMapping获取Handler
- 通过相应的适配类HandlerAdapter调用Handler的处理方法处理请求并返回ModelAndView
- 根据返回的ModelAndView选择一个适合的ViewResolver
- ViewResolver结合Model和View渲染视图
- 将结果放到Response对象中返回给web容器
请求过滤拦截
- Filter(过滤器)和Interceptor(拦截器)对比入门
- Filter(过滤器)和Interceptor(拦截器)对比进阶
- Filter(过滤器)和Interceptor(拦截器)对比详解
- Filter(过滤器)、Interceptor(拦截器)、AOP对比入门
- Filter(过滤器)、Interceptor(拦截器)、AOP对比进阶
- Filter(过滤器)、Interceptor(拦截器)、AOP对比详解
- Filter(过滤器)、Interceptor(拦截器)、Advice、AOP执行顺序
- Filter(过滤器)之多个Filter的顺序
- Interceptor(拦截器)之多个Interceptor的顺序
- Filter(过滤器)之如何正确的使用依赖注入
- Interceptor(拦截器)之如何正确的使用依赖注入
主要区别如下
- 使用范围不同:Filter是Servlet规范,只能用于web应用,Interceptor是Spring的规范,还可以用于非web应用
- 拦截时机不同:Filter在进入Servlet之前,Interceptor在进入Servlet之后且进入Controller之前
执行顺序如下
- Filter(过滤器)
- Servlet(DispatcherServlet)
- Interceptor(拦截器)
- Advice(通知)
- Aop(切面)
- Controller(控制器)
使用场景如下
- 认证鉴权
- 日志记录
- 耗时统计
Filter(过滤器)
- init:容器启动的时候执行一次
- doFilter:每次请求和响应时都会执行
- destroy:容器停止的时候执行一次
ps:Filter可以访问request和response,不能访问controller
ps:FilterChain.doFilter之前的代码在请求的时候执行
ps:FilterChain.doFilter之后的代码在响应的时候执行
Interceptor(拦截器)
- preHandle:Controller调用之前执行
- postHandle:Controller调用之后且视图渲染之前执行
- afterCompletion:视图渲染之后执行
ps:Interceptor可以访问request和response,还可以访问controller和modelAndView
Advice(通知)
ps:切面可以通过RequestContextHolder访问request和response
AOP(切面)
ps:AOP可以通过RequestContextHolder访问request和response,还可以通过JoinPoint访问方法参数
Controller
Controller包含多个Handler,Controller里的每个方法都是一个Handler
Request
RequestEntity包含
- 请求头(@RequestHeader)
- 请求体(@RequestBody)
Route
Param
- 参数名称
- 参数个数
- 单个参数
- 多个参数
- 参数类型
- 基本类型
- 对象类型
- 容器类型
- Map
- Array/List/Set
Pass
- Method
- GET
- POST
- MIME
- x-www-form-urlencoded(Post form type)
- multipart/form-data(Post form type)
- application/json(Post json type)
- Type
- 基本类型
- 对象类型
- 容器类型
- Map
- Array/List/Set
Method
MIME
- SpringMVC之参数传递方式之MIME
- SpringMVC之参数传递方式之MIME和Post请求
- SpringMVC之参数传递方式之MIME的application/json
- SpringMVC之参数传递方式之MIME的application/x-www-form-urlencoded
- SpringMVC之参数传递方式之MIME的multipart/form-data
- SpringMVC之参数传递方式之MIME的multipart/form-data与application/x-www-form-urlencoded的区别
- SpringMVC之参数传递方式之MIME和form的enctype
Type
Fetch
- SpringMVC之参数获取来源入门
- SpringMVC之参数获取来源详解
- SpringMVC之参数使用方式入门
- SpringMVC之参数使用方式详解
- SpringMVC之参数名称
- SpringMVC之参数默认值
- SpringMVC之Attribute和Parameter的区别入门
- SpringMVC之Attribute和Parameter的区别进阶
- SpringMVC之Attribute和Parameter的区别详解
- SpringMVC之Request和RequestScope的区别
- SpringMVC之RequestScope和SessionScope入门
- SpringMVC之RequestScope和SessionScope详解
- SpringMVC之RequestScope和SessionScope原理
- SpringMVC之forward和Redirect的区别
- SpringMVC之request.setAttribute()和session.setAttribute()的区别
- SpringMVC之request.setAttribute()和model.addAttribute()的区别
Attribute和Parameter的来源
- Request
- Session
- Model
Attribute和Parameter的获取
- HttpServletRequest:可以获取Parameter和Attribute
- HttpSession:可以获取Attribute
- Model:可以获取Attribute
Attribute和Parameter的区别
- Attribute:由后端生成,可以存在Request、Session和Model中
- Parameter:由前端生成,只存在Request中,可以自行添加到Session和Model中
Attribute和Parameter的范围
- Request:Request范围
- Session:Session范围
- Model:Request范围
ps:Request范围的数据只能被该请求单独访问,Session范围的数据可以多个请求共享访问
ps:Model的Attribute是Request范围的,如果要在Session范围内使用Model的Attribute,可以使用@SessionAttributes注解将Model的Attribute转到Session的Attribute中
Attribute和Parameter的传递
- Attribute:转发后的页面可以访问Request和Session范围的,重定向后的页面可以访问Session范围的
- Parameter:转发后的页面不可以访问,GET重定向的页面可以访问(因为浏览器会携带参数重新请求)
Parameter
Attribute
Attribute相关注解的作用
- @RequestAttribute:从HttpRequest中获取Attribute
- @SessionAttribute:从HttpSession中获取Attribute
- @ModelAttribute:从Model中获取Attribute或者将方法的返回值存入Model中
- @SessionAttributes:将Model里面的Attribute存到Session域中(Model的有效范围默认是Request域的)
ps:@SessionAttributes和@SessionAttribute之间差一个
s
,但作用不同
Model
Model的作用是将数据传递给视图进行渲染,比Request和Session更符合MVC规范
ps:视图获取参数时建议使用哪个Model,也可以使用Request和Session,因为在使用Model时可以更加优雅的通过
${param}
的方式取值
Header
Cookie
Session
Response
ResponseEntity包含
- 响应头(ResponseHeader)
- 响应体(@ResponseBody)
- 响应状态(@ResponseStatus)
ps:ResponseEntity的优先级比@ResponseBody高
Result
Status
Header
Cookie
View
Exception
- 参数校验异常
- 数据访问异常(mysql、redis)
- 业务处理异常
Context
Invalid
Validation
Annotation
@Validated和@Valid的区别
- @Validated是spring的注解,@Valid是java的注解
- @Validated不支持标注字段,@Valid支持标注字段
- @Validated不支持嵌套校验,@Valid支持嵌套校验
- @Validated支持分组校验,@Valid不支持分组校验
Exception
MethodArgumentNotValidException和ConstraintViolationException的区别
- BindException:表单请求数据绑定到参数出错时抛出的异常
- MethodArgumentNotValidException:使用@Valid和@Validated注解标注的方法参数校验失败时抛出的异常
- ConstraintViolationException:使用@NotNull等注解直接标注的方法参数校验失败时抛出的异常
Assertion
Converter
Date
Enum
Json
- Jackson详解
- Jackson注解入门
- Jackson注解详解
- Jackson之字段映射
- Jackson之依赖Getter-Setter反射方法
- Jackson之配置为依赖字段反射
- Jackson之处理is开头的字段
- Jackson之@JsonProperty和@JsonAlias详解
- Jackson之@JsonFormat处理date和enum
- Jackson之@JsonValue处理enum
- Jackson之TypeReference详解
- Jackson之自定义序列化和反序列化
- Spring之ResolvableType详解
- Spring之Jackson配置
- JsonPath详解
- jq详解
CORS
CORS:CrossSite(跨域)
- 全局
- WebMvcConfigurer
- CorsFilter
- 自定义Filter添加响应头(Access-Control-Allow-Origin)
- 局部
- @CrossOrigin
- 手动在响应里面添加响应头(Access-Control-Allow-Origin)
Auth
登录跳转实现方案
- 后端实现
- 跳首页:返回302(浏览器负责实现跳转)
- 跳当前页:返回302 + 前端将当前页地址存到sessionStorage中、返回302 + 前端请求时每次将当前页地址放到
自定义header
或者参数
中传给后端(不推荐这个方案)
- 前端实现
- 跳首页:返回401(前端负责实现跳转)
- 跳当前页:返回401 + 前端将当前页地址存到sessionStorage中
Service
- Service:
业务
逻辑实例类
- Manager:
通用
逻辑实例类
- Helper:
业务
逻辑静态类
- Utils:
通用
逻辑静态类
Model
POJO
*+ po(entity):数据库表结构类
- dao(mapper or orm):数据库单表访问类
- dal(use multiple dao):数据库多表访问层
- bo(business):业务数据类
- co(common):通用数据类
- do(domain):领域数据类
- vo(view):视图数据类(后端生成网页时使用)
- dto(transfer):传输数据类(前后端交互时使用,分为请求和响应)
Transform
View
Jsp
Thymeleaf
spel:Spring Expression Language
Freemarker
Web
Protocol
Http
RPC
RPC是远端过程调用,调用协议通常包含
- 序列化协议
- Xml
- Json
- Bin
- Hessian(比较早期的框架)
- MessagePack(Json格式的优化版)
- Protobuf(Google出品的框架)
- Thrift(FaceBook出品的框架)
- Avro(Hadoop的一个子项目)
- Kyro(针对java的二进制协议)
- Fct(针对java的二进制协议)
- 传输协议
- TCP
- HTTP
ps:RPC的传输协议可以使用TCP来实现,也可以使用Http来实现
RPC框架
- Dubbo(Ali)
- Finagle(Twitter)
- Thrift(Facebook)
- grpc(Google)
- brpc(Baidu)
WebSocket
WebSocket和Http对比
- 都是应用层协议
- WebSocket支持双向通信,Http只支持单向通信
WebSocket和Socket对比
- WebSocket是应用层协议,Socket是传输层协议的封装
- Socket比较原始,WebSocket则是在应用层面对于Socket的进一步封装
Specification
Restful(Web API)
SOAP(Web Service)
Reliability
Exception
Retry
Idempotent
幂等和去重的区别
- 幂等:是一种概念,操作执行多次的结构都是一样的
- 去重:是一种方案,操作只会执行一次
ps:去重是实现幂等的一种方案(如果操作本身就是支持幂等的就不需要去重)
如何实现幂等
- 请求
- token令牌
- 数据
- 插入操作
- 去重表(mysql)
- 直接插入 + 唯一约束:适合有唯一约束的
- 使用
insert into
检测到插入失败(DuplicateKeyException)后换一个主键重试 - 使用
insert ignore into
检测到插入失败后换一个主键重试
- 使用
- 检测插入 + 加锁控制:适合没有唯一约束的
- 使用
select for update
检测到重复后换一个主键重试
- 使用
- 直接插入 + 唯一约束:适合有唯一约束的
- 去重表(redis)
- setnx
- 去重表(mysql)
- 更新操作
- 状态机 + CAS思想
- 版本号 + CAS思想
- 计数
- 时间戳
- 插入操作
ps:去重时还可以使用布隆过滤器来优化去重的效率
ps:数据库的插入和更新都会主动加锁,所以不需要额外加锁
幂等和去重都需要唯一标识
唯一标识来源
- 业务id(身份证号、手机号、设备指纹)
- 逻辑id(发号器生成)
- 顺序id
- 随机id
唯一标识实现
- 单机
- 顺序id
- mysql自增id
- 时间戳
- 随机id
- UUID
- 顺序id
- 分布式
- 顺序id
- mysql发号器
- redis发号器
- 随机id
- UUID
- SnowflakeId
- MongodbId
- 顺序id
Repeat
如何防止重复提交
- 前端
- 进入页面时向后端请求一个去重token放入隐藏域中
- 点击提交按钮后立即禁用提交按钮
- 点击提交按钮后显示加载中或者跳转到其他页面
- 后端
- 取出前端提交的去重token
- 如果token存在,则执行正常逻辑,并销毁去重token
- 如果token不存在,则执行去重逻辑,即丢弃重复的请求
防抖和节流的区别
- 防抖:debounce,延时后只执行一次,用于防止操作过快(操作的时间间隔短)
- 截流:throttle,周期内只执行一次,用于防止操作过多(操作的触发频率高)
ps:防抖中再次触发时,会重置延时计时器和取消上一次的延时操作
ps:截流是限流的一种方式
Performance
- 缓存加速
- 本地缓存
- 集中缓存
- 异步处理
- 子线程(多线程)
- 消息队列
- 并行处理
- 分解任务并进行并行处理
- 批量处理
- 聚合任务并进行批量处理
- 池化技术
异步处理时获取任务结果
- 轮询
- 回调(回调机制,耦合)
- 监听(发布和订阅,不耦合)
系统三高
- 高性能:每次请求的处理时间越短越好
- 高并发:同时支持的请求数量越多越好
- 高可用:集群或分布式系统中部分服务节点故障也不影响整体服务(备份机制)
性能模型
- CPU密集型:需要CPU进行大量的处理,例如数学计算、加密解密、编码解码、压缩解压、正则表达式搜索
- IO密集型:大部分的时间CPU都在等IO(内存、磁盘、网络),例如WEB服务、爬虫
性能指标
服务性能指标
关键概念
- RT:响应时间(Response Time),实际包含请求时间(Request Time)、处理时间(Handle Time)、响应时间(Response Time)
- ART:平均响应时间(Average Response Time),描述的是响应时间的平均值
- HPS:每秒点击量(Hit Per Second),描述的
客户端
每秒点击量 - RPS:每秒请求量(Request Per Second),描述的
客户端
每秒请求量 - QPS:每秒查询量(Query Per Second),描述的是
查询系统
的每秒查询量 - TPS:每秒事务量(Transaction Per Second),描述的是
业务系统
的每秒事务量 - Concurrency:并发量,描述的
后端
能够同时处理的请求数量(不是单位时间能处理的数量) - Latency:延迟,用户等待请求或事务从开始到完成的时间(ART)
- Throughput:吞吐量,系统单位时间内处理请求(QPS)和事务(TPS)的数量
ps:一个事务可能会包含多个请求或者请求链
ps:前台交互型
应用追求的是最低延迟
,比如Web服务
应用
ps:后台计算型
应用追求的是最大吞吐量
,比如大数据计算
应用
延迟和吞吐量之间的关系
- 延迟和吞吐量之间没有必然的关系
- 延迟变低(比如提高处理速度)可以提高吞吐量
- 但是延迟变高(比如进行批量处理)也可以提高吞吐量
核心指标
- 平均响应时间(ART)
- 并发量(Concurrency)
- QPS
QPS = Concurrency / ART(单位通常是毫秒,计算时需要换算成秒)
ps:QPS不是ART的倒数这种估算值,需要进行实测,因为处理请求时不止一个线程或进程
ps:而且ART不是一个固定的值,会受服务器资源(cpu、mem、disk、net)的状态影响
ps:因为ART不可调,所以可以不断增大Concurrency直到QPS开始下降来测出QPS的最大值
网络性能指标
- RTT:往返时间(Round-Trip Time),表示从发送端发送数据开始,到发送端收到来自接收端的确认(接收端收到数据后便立即发送确认,不包含数据传输时间)
- Latency:时延,是一个描述
网络延迟时间
的概念,包含RTT这个核心指标
业务评价指标
- PV:单个页面访问量(Page View)
- UV:独立用户访问量(Unique Visitor)
- DAU:日活(Daily Active User)
- MAU:月活(Month Active User)
- GMV:总商品价值量(Gross Merchandise Volume)
Container
- Tomcat
- Netty(WebFlux)
- Jetty
- Undertow
Tomcat
Client
- Http请求库选型
- Http请求库演进
- HttpClient详解
- OkHttp入门
- OkHttp进阶
- OkHttp详解
- Retrofit详解
- Forest详解
- RestTemplate详解
- RestTemplate集成HttpClient和OkHttp
- RestClient详解
- WebClient详解
- OkHttp和HttpClient对比
- Retrofit和OkHttp对比
- Forest和Retrofit对比
- WebClient和RestClient和RestTemplate对比
- Dubbo和OpenFeign和Feign对比
- RestTemplate和Retrofit对比
- Feign和Retrofit对比
- Spring声明式HTTP Interface
客户端的分类
- 客户端的调用方式可以分为
编程式调用
和声明式调用
- 客户端的请求方式可以分为
同步请求
和异步请求
- 客户端的请求协议可以分为
Http请求
和RPC请求
客户端的实现
- HttpClient:Apache组织出品的较早的Http请求库,支持
编程式调用
- OkHttp:Square公司出品的较新的Http请求库,支持
编程式调用
- Retrofit:Square公司出品的较新的Http请求库,基于OkHttp和RxJava,支持
声明式调用
- Forest:开源的轻量级Http请求库,基于OkHttp和RxJava,支持
声明式调用
- RestTemplate:Spring中使用,可以适配多种Http请求库,支持
编程式调用
- RestClient:Spring中使用,新一代的同步Http请求库,支持
编程式调用
- WebClient:Spring中使用,新一代的异步Http请求库,支持
编程式调用
- Feign:SpringCloud中使用,支持负载均衡的Http请求库,支持
声明式调用
- OpenFeign:SpringCloud中使用,支持负载均衡的Http请求库,支持
声明式调用
- Dubbo:SpringCloud中使用,支持负载均衡的RPC请求库,支持
声明式调用
ps:OpenFeign是Spring对Feign支持SpringMVC的封装,可以使用SpringMVC的注解
Logging
Library
log4j2
logback
Optimize
Placeholder
Judgement
Question
Problem
Adapter
Specification
Category
Event
事件日志:程序的运行日志
- 事件信息(what)
- 事件时间(when)
- 事件来源(who)
- 事件位置(where):比如线程名、记录器名称、模块名、方法名、代码行
- 事件标签(tag):比如事件属性、输入参数
Action
操作日志:用户的行为日志
- 操作信息(what)
- 操作时间(when)
- 操作者(who)
- 操作资源(resource):资源名称和资源id
- 操作变化(change):资源变化前和变化后的状态
Trace
链路日志:服务的调用日志
Testing
Framework
Unit Test
- Junit5使用了Extend机制(@ExtendWith),可以支持多个Extend
- Junit4使用了Runner机制(@RunWith),只能支持一个Runner