一. servlet
1.1 什么是servlet?
servlet是一个java的服务端应用程序。类似一个java组件或者小插件,用来处理客户端和服务端之间的请求和响应。需要依赖servlet容器,由容器来实例化和调用service方法
servlet让客户端和服务器端不仅仅是进行简单的静态资源传输, 它可以实现动态的资源和一些复杂的业务逻辑。
我们使用的spring mvc和后面的springboot,都是基于dispatcherServlet来调用的
1.2 servlet和tomcat处理一个http请求的过程(tomcat7)
- 浏览器客户端先和Tomcat的Connector组件建立连接
- 客户端向Tomcat发起http请求,Connector组件分析请求信息,封装成request和response对象(不是HttpServletRequest)
- Connector中的Mapper会根据请求域名和地址匹配到servlet容器,设置到reqeust属性中
- Connector中的适配器Adapt将Request和response转换成HttpServletRequest和HttpServletResponse对象,并且根据上面找到的servlet容器,交给容器处理
- servlet容器调用servlet的doGet()或doPost()方法,如果是第一次则先初始化,servlet执行业务逻辑,并把结果写到response中
- 容器将请求数据封装成HttpServletRequest和HttpServletResponse对象,调用doGet()或doPost(),servlet执行业务逻辑,并把结果写到response中
- 返回response给Connector,Connector返回给浏览器
二. mvc流程
-
m - model 模型
数据和行为
-
v - view 视图
模型的展示,也就是页面
-
c - controller 控制器
接受请求,将数据结果返回给视图,展示视图
SpringMvc主要是围绕着DispatcherServlet进行:
- 用户发起的请求经过web服务器到dispatcherServlet
- dispatcherServlet调用HandlerMapping,根据请求的url找到找到对应的处理器调用链,包括处理器Handler和拦截器,返回给dispatcherServlet
- dispatcherServlet再根据Handler选择合适的适配器HandlerAdapt(处理器适配器)来处理,其实就是调用Controller的方法,返回modelAndView
- dispatcherServlet再用视图解析器ViewResolve去解析ModelAndView,返回视图View
- DispatcherServlet拿到视图,将模型数据渲染填充到View中
- 返回View给浏览器
三. tomcat
3.1 什么是tomcat
tomcat是阿帕奇的一个Web 应用服务器.也是一个servlet容器.
- web服务器,简单说就是可以让其他的客户端在网上能访问到服务器静态资源的一个设备,比如浏览图片,静态网页,下载文件等。比如阿帕奇的nginx
- 而web应用服务器,是针对某个应用或者业务逻辑而实现的,通过组件可以完成一些业务逻辑比如操作数据库,处理请求返回动态的资源
四. NIO
4.1 NIO和普通IO
NIO又叫做非阻塞io,它与传统的io的区别是:
IO | NIO |
---|---|
面向流 | 面向缓冲buffer |
阻塞IO | 非阻塞IO |
传统IO,当一个线程处理一个读写IO操作的时候,该线程会一直被阻塞,知道流的传输完毕。此间线程不能做其他事,浪费资源。
而在NIO的非阻塞模式下,线程发送数据与接收数据都是通过“通道”进行的,线程只需要去询问通道是否有数据需要处理,有则处理,无则立即返回不会进行等待。
所以NIO的单线程可以处理多个通道的IO操作。
4.2 NIO的概念
a. Buffer
Buffer通常是一个数组,表示一个缓冲区。NIO的读写操作都是操作缓存。比如写,是先将数据写入Buffer,然后再写到通道Channel的
b. Channel
通道,和流不同,通道是双向的,流是单向的。流只能是读或者写,通道可以读也可以写。
C. Selector
选择器。通道会注册到选择器上,并指定监听的事件类型,比如ACCET,READ,WRITE。
只要开启一个线程不断轮询注册在选择器上的通道,选择器会调用select()方法,这个方法是阻塞的,如果监听到注册的通道的感兴趣的事件,会调用相应的方法处理
4.3 tomcat中的NIO
可以参考前面博文:
Tomcat 接收连接的accept流程
简单的说,就是tomcat内部分为两大块:
Connector和Container容器
Connector中又分为:
- Http11NioProtocol
- NioEndpoint
- Acceptor
- Poller
- Worker
- Http11ConnectionHandler
- NioEndpoint
- Mapper
- CoyoteAdapter
Acceptor
Acceptor线程组,作为生产者的角色
- 通过阻塞的accept()方法,建立与客户端的连接,并获取到SocketChannel对象
- 将SocketChannel对象封装成NioChannel对象
- 再将NioChannel对象封装到PollerEvent对象中,放到Poller的队列中
Poller
Poller线程组,作为消费者的角色,是个典型的生产者-消费者模式,Acceptor与Poller线程之间通过queue通信
- 从Poller队列中取出PollerEvent消费
- 将PollerEvent注册到Selector中
- Poller线程的run方法是一个死循环,其中Selector进行select()操作,如果注册的Channel中有可读的操作,丢到Worker线程池中开启一个线程处理
Worker
到这一步就是开始解析请求数据了
- 解析请求数据创建一个临时的Request对象(不是HttpServletRequest,org.apache.coyote.Request),交给CoyoteAdapter处理
- CoyoteAdapter会将Request对象,转成org.apache.catalina.connector.Request对象。
- 再调用Mapper,根据请求的Url,分析出对应的Host,Context,以及对应的Servlet的封装wrapper,并将这些参数都封装到Request中
- 接着就将Request交给Container容器处理,也就是Servlet容器
- 容器根据Request属性中的映射关系,找到对应的Servlet处理
- Servlet调用doGet(),doPost()方法,返回Response对象
五. http
5.1 什么是http
http是一种规定好的客户端和服务端传输信息的一种协议.
它要求传输的数据分为三个部分: 信息行,信息头,信息体.
比如请求:
- 请求行
- 请求头
- 请求体
5.3 错误码
在返回的数据中,响应行中携带状态码和状态描述.常见的状态码:
2xx是请求正常,3xx是重定向,4xx是请求错误,5xx是服务器内部错误
状态码 | 含义 |
---|---|
200 | 请求成功 |
301 | 永久重定向 |
302 | 临时重定向 |
400 | 请求的参数语法错误 |
404 | 资源找不到 |
405 | 请求的方法与后台定义的不一致 |
500 | 服务器内部的错误 |