文章目录
- 1. Tomcat
- 1.1 常见的错误
- 1.1.1 出现 404
- 1.1.2 出现 405
- 1.1.3 出现 500
- 1.2 HttpServlet
- 1.2.1 Tomcat 的处理逻辑
- 1.2.2 相关方法
- 1.3 HttpServletRequest
- 1.3.1 常见方法
- 1.3.2 jackson 处理逻辑
- 1.4 HttpServletResponse
- 1.4.1 常见方法
1. Tomcat
tomcat 是一个 HTTP 服务器程序,对 HTTP 协议进行了封装,提供了一组 API,即 Servlet
开发者自己写的代码(类),会被加载到 Tomcat 中,Tomcat 接收到请求就会执行开发者写的代码,来完成相应的业务逻辑
Maven 是一个项目构建工具,可以进行项目的依赖的管理,代码编译和打包
tomcat 收到请求之后,就有可能执行子类中的方法,HttpServletRequest 对象是 Tomcat 解析请求后构造好的对象,HttpServletResponse 对象是个输出型参数
war 是 Tomcat 专属的压缩包,不仅有 .class 文件,还有 web.xml 等 Tomcat 要求的文件以及前端代码。
Tomcat 加载 webapp 的时候,用的是自定义的类加载器,只在 webapp 指定目录中查找,找不到就抛异常,不会去标准库中查找
1.1 常见的错误
1.1.1 出现 404
- url 路径有问题
- webapp 没有正确加载(如 web.xml 有问题)
1.1.2 出现 405
- 请求的方法与实际写的方法不一致(如前端请求 GET,但后端写的是 POST)
- 没有删掉super.doGet(req, resp),导致 HTTP 响应的格式出现了问题,浏览器无法正常解析
1.1.3 出现 500
- 服务器内部出错
1.2 HttpServlet
写 Servlet 的代码,并不需要写 main 方法,而是直接重写 HttpServlet 中的相关方法即可,Tomcat 中有 main 方法,也可以视为是一个框架。
继承 HttpServlet,重写其中的方法,就是为了将自己的代码插入到 Tomcat 中
1.2.1 Tomcat 的处理逻辑
// 通过 TCP Socket 读取请求
String requestString = readRequest();// 解析请求
HttpServletRequest req = parse(requestString);// 构造响应对象
HttpServletResponse resp = new HttpServletResponse();// 创建一个 HttpServlet 对象
HttpServlet s = new 自己写的Servlet子类();
s.doGet(req, resp);//将得到的响应 resp 返回给浏览器// ...
1.2.2 相关方法
方法名 | 调用时机 | 作用 |
---|---|---|
init | 在 HttpServlet 实例化之后被调用一次 | 完成初始化 |
destroy | 在 HttpServlet 实例不再使用的时候调用一次(HttpServlet 被销毁之前) | 释放资源(若直接在任务资源管理器中结束任务,则来不及调用 destroy,若通过 8005 管理端口给 Tomcat 发送一个 “停机” 指令,则会执行 destroy,大多数情况下会直接杀进程) |
service | 收到 HTTP 请求的时候调用 | 根据不同的方法将请求分发给 doGet、doPost 等 |
doGet | 收到 Get 请求的时候被调用 | 计算 Get 请求的响应 |
doPost | 收到 Post 请求的时候被调用 | 计算 Post 请求的响应 |
前三个方法体现了 Servlet 的生命周期
1.3 HttpServletRequest
Tomcat 通过 Socket API 读取 HTTP 请求(字符串),并且按照 HTTP 协议的格式将字符串解析成 HttpServletRequest 对象
1.3.1 常见方法
方法名 | 解释 |
---|---|
String getProtocol() | 返回请求协议的名称和版本 |
String getMethod() | 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT |
String getRequestURI() | 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分 |
String getContextPath() | 返回指示请求上下文的请求 URI 部分 |
String getQueryString() | 返回查询字符串 |
Enumeration getParameterNames() | 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称 |
String getParameter(String name) | 以字符串形式返回请求参数的值,或者如果参数不存在则返回 null |
String[] getParameterValues(String name) | 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null |
Enumeration getHeaderNames() | 返回一个枚举,包含在该请求中包含的所有的头名 |
String getHeader(String name) | 以字符串形式返回指定的请求头的值 |
String getCharacterEncoding() | 返回请求主体中使用的字符编码的名称 |
String getContentType() | 返回请求主体的 MIME 类型,如果不知道类型则返回 null |
int getContentLength() | 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1 |
InputStream getInputStream() | 用于读取请求的 body 内容. 返回一个 InputStream 对象(得到一个流对象,读取这个流对象就能得到整个请求的 body,不必一次性处理完所有数据,可以一次处理一点,也可以一次处理完全部) |
Cookie[] getCookies() | 获取到请求中的所有 Cookie |
HttpSession getSession() | 从 Cookie 中获取到 sessionId,并查询出对应的 session。若未查到,就自动创建 session,分配新的 sessionId,创建新的 HttpSession 对象,将 sessionId 和 HttpSession 存入 hash 表中,并将 sessionId 添加到响应报文的 header 中(Set-Cookie 字段) |
在代码中表示一个 “不定长” 的数据时,经常会想到使用 “流对象”
1.3.2 jackson 处理逻辑
将 json 字符串转为 Java 对象,或将 Java 对象转为 json 字符串
// 将 json 字符串转为 Java 对象
Request request = objectMapper.readValue(req.getInputStream(), Request.class);
-
json 字符串是在 http 的 body 中,需要通过 HttpServletRequest 的 getInputStream 获取到,直接将 流对象 传给 readValue, readValue 内部会读取 InputStream 中的所有数据(http 请求的 body)
-
将 json 字符串按照 json 的格式解析成 Map(键值对)
-
将 Map 转换成 java 对象(通过 Request.class 告诉 readValue 方法,将 Map 转成什么对象)
-
readValue 内部,通过反射 API 创建 Request.class 实例,并根据其中的属性名来查询 Map,将查询结果赋值给相应的属性
jackson 只会处理 public 的属性
// 将 Java 对象转为 json 字符串
String respJson = objectMapper.writeValueAsString(response)
- 通过参数 response 获取到类对象,再通过反射拿到属性名字
- 根据属性名拿到属性值
- 根据属性名和属性值构造 json 格式的字符串
1.4 HttpServletResponse
1.4.1 常见方法
方法名 | 解释 |
---|---|
void setStatus(int sc) | 为该响应设置状态码 |
void setHeader(String name, String value) | 设置一个带有给定的名称和值的 header。如果 name 已经存在,则覆盖旧的值 |
void addHeader(String name, String value) | 添加一个带有给定的名称和值的 header。如果 name 已经存在,不覆盖旧的值, 并列添加新的键值对 |
void setContentType(String type) | 设置被发送到客户端的响应的内容类型 |
void setCharacterEncoding(String charset) | 设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8 |
void sendRedirect(String location) | 使用指定的重定向位置 URL 发送临时重定向响应到客户端 |
PrintWriter getWriter() | 往 body 中写入文本格式数据 |
OutputStream getOutputStream() | 用于往 body 中写入二进制格式数据 |
void addCookie(Cookie cookie) | 向响应中添加指定的 cookie(添加到了浏览器中) |
session 不是持久化存储的
- 将会话进行持久化保存(文件、数据库、redis)
- 使用令牌的方式,将用户信息在服务器端加密,保存在浏览器