如何书写Servlet代码及其运行原理


提示:以下是本篇文章正文内容,Java系列学习将会持续更新

一、Servlet 是什么?

Servlet 是一种实现动态页面的技术。是一组 Tomcat 提供给程序猿的 API,帮助程序猿简单高效的开发一个 web app。

静态页面: 就是内容始终固定的页面。即使 用户不同/时间不同/输入的参数不同 , 页面内容也不会发生变化。
动态页面: 指的是 用户不同 / 时间不同 / 输入的参数不同,页面内容会发生变化。如个人中心页面。

大体的开发流程 —— 整个过程都需要遵守标准,否则Tomcat不认:

  1. 通过继承HttpServlet抽象类,完成我们自己类(每个都是一个独立的Web资源) HelloServlet
  2. 重写其中的方法(get、 post …) ,就是输出资源内容的过程
  3. 把动态资源和路径建立绑定关系。/hello <=> HelloServlet
    1. 通过web.xml (演示,麻烦,少用)
    2. 使用Java中的注解语法完成 @WebServlet

对于Web资源类,我们只负责写:

  1. 不需要我们自己实例化HelloServlet对象 (Tomcat内部在实例化)
  2. 我们也不会调用我们写好的get、post 方法 (Tomcat 内部会在合适的时机去调用)

回到目录…

二、书写 Servlet 程序

2-1 书写Web资源类的流程

// 类名无所谓,但是尽量按照一定的规范去命名比较好
// 1. 声明这个类是一个 Web 资源,让类继承 HttpServlet 这个抽象类
public class FirstServlet extends HttpServlet {
    @Override
    // 2. 看我们的动态资源支持哪些 HTTP 方法(支持 get 方法,重写 doGet 方法)
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 3. 读取 req 对象中的信息(都是 来自 HTTP 请求中信息)
        // 4. 根据我们当下的条件
        
        // 5. 准备响应数据,通过填写 resp 对象来做到
        // 这个例子中  201  text/plain    "你好世界" charset=utf-8
        resp.setStatus(201);    // 状态码
        resp.setContentType("text/plain; charset=utf-8");  // 输出的文本类型
        PrintWriter writer = resp.getWriter();  // 调用响应对象的输出方法
        writer.print("你好世界");
    }
    // 6. 把动态资源和一个资源路径建立绑定关系 /first
	// 6.1 先使用 web.xml 的方式
}

2-2 通过web.xml动态绑定

<!-- 指明Web资源类 -->
<servlet>
	<servlet-name>MyFirstServlet</servlet-name>
	<servlet-class>servlet.FirstServlet</servlet-class>
</servlet>
<!-- 映射到具体的类 -->
<servlet-mapping>
	<servlet-name>MyFirstServlet</servlet-name>
	<!-- ServletPath -->
	<url-pattern>/first</url-pattern>
</servlet-mapping>

2-3 通过@WebServlet注解动态绑定

// 6.2 通过用 @WebServlet 注解修饰类,来实现绑定
@WebServlet("/second")
public class SecondServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(202);
        resp.setContentType("text/css; charset=utf-8");
        PrintWriter writer = resp.getWriter();
        writer.print("你好中国");
    }
}

回到目录…

三、Servlet 运行原理

在 Servlet 的代码中我们并没有写 main 方法, 实际上我们写的代码是交给 Tomcat 服务器来运行。
当浏览器给服务器发送请求的时候, Tomcat 作为 HTTP 服务器, 就可以接收到这个请求。

HTTP 协议作为一个应用层协议, 需要底层协议栈来支持工作. 如下图所示:
在这里插入图片描述

更详细的交互过程如下:
在这里插入图片描述

3-1 Tomcat内部的过程

  1. Tomcat收到了一个HTTP请求
  2. Tomcat根据HTTP协议的规定,解析请求,得到诸如: 请求方法、资源路径、请求头们、请求体(POST请求才有)。
  3. Tomcat根据资源路径 (Path = Context Path + Servlet Path)
    1. 先根据Context Path,决定这个资源是交给哪个Webapp处理 (隐含: Tomcat支持多个webapp同时存在)
    2. 当确定是哪个webapp后,再根据Servlet Path,去找到对应的资源进行处理
      1. 如果是动态资源,根据路径得到一个类名(servlet.FirstServlet)
        如果这个类还没有实例化对象,则实例化其对象,否则直接获取其对象 (单例模式)
        根据请求方法,调用该对象doGet或者doPost或者其他方法
        doGet方法执行结束之后,resp 对象被填充信息(203, text/css, 你好世界)
        Tomcat根据这个对象,构造HTTP响应,发送给浏览器。
      2. 如果是静态资源,就根据对应的路径去查找对应的文件,并响应文件内容。
      3. 如果动态 or 静态资源都没有找到,就会404

回到目录…

3-2 输入 URL 后,浏览器内部发生了什么?

只站在应用层的角度:

  1. 浏览器 : 解析URL,(如果是域名, 通过DNS服务器,将域名换成ip的过程)。构建HTTP请求(GET 请求)
  2. Tomcat收到了请求。根据路径,确定对应的Servlet哪个对象进行处理;根据请求方法,调用对象的对应方法。
  3. 执行Servlet业务代码(我们写的), 得到填充好的响应对象
  4. Tomcat根据响应对象,构建HTTP响应,发送给浏览器
  5. 浏览器读取响应,展示响应结果。
    如果结果是 html 或 存在JS代码的话,可能还会触发产生新的HTTP请求
  6. 浏览器得到显示页面的所有的资源,构建DOM树(包含JS处理过的情况) +进行CSS渲染
    产生最终的页面
  7. 用户看到最终的页面效果

结合网络知识:
在这里插入图片描述

  1. 站在发送端主机的角度: 应用层->传输层->网络层->数据链路层->物理层(网卡), 按照各种协议封装起来的。
  2. 站在接收端主机的角度 : 物理层(网卡) -> 数据链路层->网络层->传输层->应用层,照协议解包+分用
  3. 只在TCP的角度讲述 : 要发送HTTP请求,收到HTTP响应,首先得有TCP连接(TCP三次握手、通信、四次挥手)

回到目录…

四、Servlet API

4-1 HttpServlet

我们写 Servlet 代码的时候, 首先第一步就是先创建类, 继承自 HttpServlet, 并重写其中的某些方法.

方法名称调用时机
init在 HttpServlet 实例化之后被调用一次
destory在 HttpServlet 实例不再使用的时候调用一次
service收到 HTTP 请求的时候调用
doGet收到 GET 请求的时候调用(由 service 方法调用)
doPost收到 POST 请求的时候调用(由 service 方法调用)
doPut/doDelete/doOptions/…收到其他请求的时候调用(由 service 方法调用)

4-2 HttpServletRequest

当 Tomcat 通过 Socket API 读取 HTTP 请求(字符串), 并且按照 HTTP 协议的格式把字符串解析成
HttpServletRequest 对象.

方法描述
String getProtocol()返回请求协议的名称和版本。
String getMethod()返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。
String getRequestURI()从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。
String getContextPath()返回指示请求上下文的请求 URI 部分。
String getQueryString()返回包含在路径后的请求 URL 中的查询字符串。
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 对象.

4-3 HttpServletResponse

Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到
HttpServletResponse 对象中.
然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过
Socket 写回给浏览器.

方法描述
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 中写入二进制格式数据.

回到目录…


总结:
提示:这里对文章进行总结:
以上就是今天的学习内容,本文是JavaWeb的学习,学习如何写Servlet程序,了解Servlet的运行原理,以及Servlet API中的常用方法。之后的学习内容将持续更新!!!

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只咸鱼。。

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值