普通服务端
使用
- 开发服务端监听
- 客户端连接服务端
- 客户端与服务端进行数据交互
- 客户端和服务端的连接断开
文件和处理程序
- 文本编辑器:编辑a.txt文件
- 富文本编辑器:编辑b.word文件
- 音视频录制器:生成c.mp4文件
- 音视频播放器:播放c.mp4文件
- 音视频剪辑器:编辑c.mp4文件
- 数据库程序:编辑数据库文件
编辑a.txt文件
- 创建记事本文件a.txt
- 建立文本编辑器客户端
- 使用文本编辑器,编辑a.txt内容
编辑数据库文件
- 创建数据库文件
- 建立数据库服务端,管理数据库文件
- 开启客户端连接数据库服务端
- 客户端通过sql语句编辑数据库文件
客户端类型
- 命令行窗口:命令行窗口上的vim
- 可视化工具:精美的notepad编辑器页面
- Node程序运行时:运行过程中的Node代码
web服务端
使用
- 后端服务器开启监听
- 前端生成、发送HTTP请求(默认进行三次握手,建立连接)
- 后端接收、解析、处理请求,并返回HTTP响应
- 前端收到HTTP响应(默认进行四次挥手,断开连接)
请求分类
- 不分类:一个方法处理当前域名的所有请求
- pathname分类:不同pathname对应不同方法
- pathname&method分类
分类方式 | 转发 | 重定向 | 拦截器 | |
Servlet | pathname | request .getRequestDispatcher("/xxx") | response .sendRedirect("/xxx") | Filter |
HttpServlet | pathname method | |||
http | 不分类 | 手动实现 | res.writeHead(301, { 'Location': "/xxx" }) | 手动实现 |
express | pathname method | 内部转发: req.url="/xx" next() 外部转发: res.send( await axios({……}).data ) | res.redirect('/xxx') | 中间件实现 |
请求对象&响应对象
请求对象API | 响应对象API | |
http模块 | req.url:请求的pathname req.method:请求方式 req.httpVersion:http协议版本 req.headers:请求头 req.on('data'||'end', ()=>{}) | res.statusCode:响应状态码 res.statusMessage:响应状态信息 res.setHeader(name,value) res.getHeader(name):获取响应头属性值 res.removeHeader(name):移除响应头属性 res.writeHead( statusCode, statusMessage, headers ) res.write(data,encoding,callback) res.end(data, encoding, callback) |
express | 完全兼容http模块 req.query:请求query参数 req.params:请求params参数 app.use((req,res,next)=>{ let data='' req.on('data',(chunk)=>{ data+=chunk }) req.on('end',()=>{ req.body=JSON.parse(data) next() }) }) | 完全兼容http模块 res.set():设置响应头 res.status():设置响应状态码 res.send():设置响应体 |
koa | req和res的属性和方法都放在ctx对象上 响应行设置方法只有:ctx.set()、ctx.status()、ctx.message 响应体:ctx.body | |
httpservlet | req.getRequestURI():请求的pathname req.getMethod():请求方式 req.getProtocol():http协议版本 req.getHeaderNames():请求头属性 req.getHeader(str):请求头属性值 req.getReader()&reader.readLine():请求体 req.getParamterNames():query属性 req.getParamter(str):query属性值 | res.getStatus():获取状态码 res.setStatus(num):设置状态码 res.getHeaderNames():响应头属性 res.getHeader(str):响应头属性值 res.setHeader(name,value):设置响应头 res.getWriter.println():设置响应体 |
静态代理 | 静态代理本质:给每一个静态文件生成一个get路由 |
MVC和三层架构
图示
三层架构功能
功能 | |
Controller层 | 接收前端请求,调用service处理业务,返回后端响应 |
Service层 | 书写业务逻辑 |
Mapper层 | 数据库增删改查 |
三层架构优化
优化 | |
Controller层 | 用方法参数接收请求体、请求参数 用return返回响应体 |
Mapper层 | 封装常用的增删改查方法 支持手写sql语句 数据表能生成实体类 实体类能生成数据表 |
实现
路由注解 | 方法参数注解 | 方法响应注解 | |
SpringMVC | @Controller @ResquestMapping(str) @GetMapping(str) @PostMapping(str) | HttpServletRequest:无注解 HttpServletResponse:无注解 @RequestHeader(key):请求头 @RequestBody:请求体 @RequestParam(key):query @PathVariable:params | @ResponseBody ==>返回纯文本 |
NestJS | @Controller(str) @Get(str) @Post(str) | @Res():请求对象 @Req():响应对象 @Ip():主机IP @Headers(key?):请求头 @Body(key?):请求体 @Param(key?):params参数 @Query(key?):query参数 | @HttpCode(num) @Header(key,val) |
Servlet
生命周期
- 服务器开启:创建applicationContext作用域
- 第1次请求URL1:创建servlet实例1,调用servlet实例1的init函数、service函数
- 第2次及以上请求URL1:调用servlet实例1的service函数
- 服务器关闭:调用servlet实例1的destroy函数
四个作用域
- 一个webapp=>一个application作用域
- 一次会话=>一个session作用域
- 一次请求=>一个request作用域
- 一个servlet实例=>一个config作用域
子类
- GenericServlet继承Servlet:GenericServlet的子类只需重写service(req,res)方法
- HttpServlet继承GenericServlet:HttpServlet的子类根据请求方式重写方法
HttpServlet注解式写法
@WebServlet(urlPatterns = "/myservlet", initParams = {
@WebInitParam(name = "paramName1", value = "paramValue1"),
@WebInitParam(name = "paramName2", value = "paramValue2")
})
public class MyServlet extends HttpServlet {
@Override
protected void doGet(
HttpServletRequest request,
HttpServletResponse response
)throws IOException {...}
@Override
protected void doPost(
HttpServletRequest request,
HttpServletResponse response
) throws IOException {...}
}
@WebServlet:servlet类
@WebFilter:过滤器
@WebListener:监听器,可以配置全局的initparam
@WebInitParam:servlet类独享自己的initParam
三个理念
IOA(useless)
- 交出实例化类和属性赋值的权利
- 实例化的类,能从容器中取到
- 用注解,切换接口的实现类
- 用注解,快速加入各种服务类
AOP(useful)
- 公共代码段插入对应的类中
- Java采用动态生成类来实现
- typescript使用装饰器来实现
约定大于配置(useful)
- SpringBoot采用这种套路,大大遍历了框架的整合
- umi也采用了这种套路