软件架构与网络通信
软件架构:
- B/S:浏览器端-服务器端(JavaEE体系) 客户端不用再去开发,开发更加快速
- C/S:客户端-服务器端
资源分类:
- 静态资源:所有用户访问后得到的结果是一样的,称为静态资源
- 如html css js
- 动态资源:每个用户访问相同资源后,得到的结构可能不一样,称为动态资源。动态资源被访问后,需要先转换为静态资源,再返回给浏览器
- 如 servlet php jsp
网络通信三要素:
- IP:电子设备在网络中的唯一标识
- 端口:应用程序在计算机中的唯一标识
- 传输协议:规定了通信的规则
- 基础协议:tcp udp


http概述
http:超文本传输协议
传输协议:定义了客户端和服务器端通信的时候发送数据的格式
特点: - 基于TCP/IP的高级协议 - 默认端口号是80 - 基于请求响应模型,一次请求对应一次响应 - 无状态的,每次请求之间相互独立
http的请求消息和请求行
请求消息数据格式:
请求行
明确请求的基本信息(操作类型、目标资源、协议版本)
请求方式 请求url 请求协议/版本
请求方法:
常见方法(Servlet 中常用)
方法 含义 特点 是否有请求体 GET
请求获取资源 请求参数在请求行,数据通过 URL 传递,明文可见,长度有限制(浏览器通常限制 8KB) 无 POST
提交数据(如表单) 数据放在请求体中,适合传输大量数据,安全性较高 有 PUT
更新资源(全量更新) 需指定资源完整路径,幂等性(多次操作结果一致) 有 DELETE
删除资源 指定 URL 对应的资源,幂等性 无 HEAD
获取资源头部信息 仅返回响应头,不返回响应体,用于快速检查资源是否存在 无 请求url:协议://主机:端口/路径?查询参数#锚点
协议:固定为
http
或https
(如http://
)主机:服务器域名(如
www.example.com
)或 IP 地址(如192.168.1.1
)端口:可选,默认
80
(HTTP)或443
(HTTPS),如8080
路径:资源在服务器上的路径(如
/user/login
)查询参数:可选,格式为
key=value&key2=value2
,通过?
与路径分隔锚点:客户端浏览器使用,用于定位页面内元素,服务器不处理
Servlet服务器接收的 URL 部分:不包含锚点,仅到查询参数为止
请求头
携带请求的附加信息(客户端环境、请求参数、安全信息等)
请求头名称:请求头值
通用头字段:
字段名 含义 示例 Servlet 获取方法 Host
目标服务器的主机和端口(必传) localhost:8080
request.getHeader("Host")
User-Agent
客户端信息(浏览器 / 操作系统) Mozilla/5.0 (Windows NT 10.0) Chrome/110.0.0.0
request.getHeader("User-Agent")
Referer
来源页面 URL(防盗链,统计) http://example.com/login.html
request.getHeader("Referer")
Accept
客户端接受的响应内容类型 text/html,application/json
request.getHeader("Accept")
可以在服务器端获取
User-Agent
该头的信息,解决浏览器端兼容性问题与请求体相关的头字段:
字段名 含义 示例 Servlet 关联 Content-Type
请求体的数据格式和编码 application/x-www-form-urlencoded; charset=UTF-8
(表单数据)multipart/form-data; boundary=xxx
(文件上传)通过 request.getContentType()
获取Content-Length
请求体的字节长度 1024
通过 request.getContentLength()
获取请求空行
作为请求头和请求体的分隔符,必须存在且仅包含一个换行符(
\r\n
)请求体
封装POST请求消息的请求体的,GET请求没有请求体
空行之后(可选,非必须),存放请求的具体数据(如表单提交的参数、上传文件内容等)
- 数据格式
- application/x-www-form-urlencoded:表单默认格式,键值对编码为
key=value&key2=value2
,不支持文件上传 - multipart/form-data:文件上传专用格式,通过
boundary
分隔不同字段,支持二进制数据 - application/json:JSON
格式数据,需在
Content-Type
头中声明
- Servlet 中获取请求体数据
- 普通表单数据:通过
request.getParameter("参数名")
直接获取(自动解码) - JSON
数据:需通过
request.getReader()
或request.getInputStream()
手动解析 - 文件上传:需使用
MultipartHttpServletRequest
(需配置MultipartResolver
)
响应消息数据格式
Request请求原理


request对象和response对象的原理:
由服务器创建,我们仅使用
request对象获取请求消息,response对象来设置响应消息
request对象继承体系的结构
Servlet中的HttpServletRequest
对象是处理HTTP请求的核心接口
基本继承层次:
1 | javax.servlet.ServletRequest (接口) |
ServletRequest接口
这是最基础的请求接口,定义了通用的请求方法,不限于HTTP协议:
- 核心方法:
getParameter(String name)
- 获取请求参数getAttribute(String name)
- 获取请求属性setAttribute(String name, Object o)
- 设置请求属性getInputStream()
- 获取输入流getReader()
- 获取字符读取器getContentType()
- 获取内容类型getLocalAddr()
- 获取服务器IP地址
HttpServletRequest接口
继承自ServletResponse
接口,专门用来封装HTTP响应消息。
由于HTTP请求消息分为状态行,响应消息头,响应消息体三部分,因此,在HttpServletResponse
接口中定义了向客户端发送响应状态码,响应消息头,响应消息体的方法。:
- HTTP相关方法:
getHeader(String name)
- 获取请求头getMethod()
- 获取HTTP方法(GET/POST等)getCookies()
- 返回一个cookie对象数组getSession()
- 返回与这个请求相关的会话对象getRequestURI()
- 获取请求URIgetQueryString()
- 返回请求URL中的查询字符串getContextPath()
- 返回请求上下文的请求URI部分getServletPath()
- 获取Servlet路径
实现类 (以Tomcat为例)
Tomcat中的具体实现类结构:
1 | Request (org.apache.catalina.connector.Request) |
- Request:Tomcat内部的实际实现类,包含大量内部方法
- RequestFacade:提供给Servlet开发者的门面类,遵循门面模式,隐藏了内部复杂实现
javax.servlet.http包内容
HttpServlet是由GenericServlet抽象类扩展而来的,HttpServlet抽象类的声明如下所示:
1 | public abstract class HttpServlet extends GenericServlet implements Serializable |
HttpServlet之所以运用广泛的另一个原因是现在大部分的应用程序都要与HTTP结合起来使用。这意味着我们可以利用HTTP的特性完成更多更强大的任务。Javax.servlet.http中的许多类型都覆盖了Javax.servlet中的类型。


HttpServlet抽象类
HttpServlet 抽象类是继承于 GenericServlet 抽象类而来的。
使用 HttpServlet 抽象类时,还需要借助分别代表 Servlet 请求和 Servlet 响应的 HttpServletRequest 和 HttpServletResponse 对象。
HttpServletRequest 接口扩展于 javax.servlet.ServletRequest 接口,HttpServletResponse 接口扩展于javax.servlet.servletResponse 接口。
1 | public interface HttpServletRequest extends ServletRequest |
1 | public interface HttpServletResponse extends ServletResponse |
其中,HttpServlet 抽象类覆盖了 GenericServlet 抽象类中的Service( )方法,并且添加了一个自己独有的Service(HttpServletRequest request,HttpServletResponse方法。
这是 GenericServlet 抽象类中定义的service方法:
1 | public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; |
HttpServlet 实现的这个 service 方法
1 | public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { |
HttpServlet 中的 service 方法把接收到的 ServletRequsest 类型的对象转换成了 HttpServletRequest 类型的对象,把ServletResponse 类型的对象转换成了 HttpServletResponse 类型的对象。
之所以能够这样强制的转换,是因为在调用Servlet的Service方法时,Servlet容器总会传入一个 HttpServletRequest 对象和 HttpServletResponse 对象,预备使用HTTP。因此,转换类型当然不会出错了。
转换之后,service方法把两个转换后的对象传入了另一个service方法
1 | // 参数是HttpServletRequest对象和HttpServletResponse对象,刚好接收了上一个service方法传过来的两个对象 |
通过request获取内容
通过request获得请求行
请求行包含HTTP方法、URI和协议版本,例如:GET /test?name=value HTTP/1.1
1 | // 获取请求方法(GET/POST/PUT/DELETE等) |
获取请求头信息
请求头包含了客户端环境和请求的附加信息
1 | // 获取指定请求头的值 |
获取请求体
请求体主要出现在POST、PUT等请求中,包含客户端发送的数据
获取表单数据
1 | // 获取单个表单参数值 |
获取原始请求体
1 | // 获取输入流读取原始数据 |
获取其他请求信息
1 | // 获取客户端IP地址 |
示例
处理JSON请求
1 | protected void doPost(HttpServletRequest request, HttpServletResponse response) |
Request乱码问题的解决方法
Servlet默认编码是ISO-8559-1,需要手动修改编码方式为UTF-8编码
1 | request.setCharacterEncoding("UTF-8"); // 解决post提交方式的乱码 |
通过Response设置响应
HttpServletResponse对象是Servlet中用于构建HTTP响应的核心接口,它提供了丰富的方法来设置响应状态、响应头和响应体
设置响应状态
设置状态码
1 | // 设置成功状态码(200) |
设置状态码和错误消息
1 | // 设置状态码和自定义错误消息 |
设置响应头
基本响应头设置
1 | // 设置单个响应头 |
常用响应头快捷方法
1 | // 设置内容类型和字符编码(等同于setHeader("Content-Type", ...)) |
设置响应体
获取输出流
1 | // 获取字节输出流(用于二进制数据) |
注意,其中response对象的getOutSream()和getWriter()方法都可以发送响应消息体,但是他们之间相互排斥,不可以同时使用,否则会发生异常。
重定向相关
302重定向
1 | // 简单重定向(相对路径) |
请求转发(服务器内部)
1 | // 获取转发器 |
示例
RESTful API响应
1 | protected void doGet(HttpServletRequest request, HttpServletResponse response) |
文件下载
1 | protected void doGet(HttpServletRequest request, HttpServletResponse response) |
乱码问题
response缓冲区的默认编码也是iso8859-1
1 | response.setCharacterEncoding("utf-8"); // 更改response的编码方式为UTF-8 |
更改response的编码方式为UTF-8,只是其中一步,因为发送端服务端虽然改变了编码方式为UTF-8,但是接收端浏览器端仍然使用GB2312编码方式解码,还是无法还原正常的中文,因此还需要告知浏览器端使用UTF-8编码去解码。
1 | // 通知浏览器使用utf8 |
response.setContentType
(“text/html;charset=UTF-8”)这个方法包含了上面的两个方法的调用,因此在实际的开发中,只需要调用一个response.setContentType
(“text/html;charset=UTF-8”)方法即可。
Servlet的工作流程


关于Web基础部分
引用文章
菜鸟教程Servlet部分