Servlet 的回顾
随着我们学习 SSM 中的 Spring MVC,由 Spring Boot 整合其他框架搭建 Web 应用,我们大部分同学对于 Java Web 应用核心的 Servlet 理解也慢慢生疏。适当的对以前核心基础的深入能帮助我们更好理解以后的知识。
简介
servlet 是基于 Java 的 Web 组件,由容器进行管理,来生成动态内容。像其他基于 Java 的组件技术一样,servlet 也是基于平台无关的 Java 类格式,被编译为平台无关的字节码,可以被基于 Java 技术的 Web 服务器动态加载并运行。容器(Container),有时候也叫做 servlet 引擎,是 Web 服务器为支持 servlet 功能扩展的部分。客户端通过 servlet 容器实现的 request/response paradigm(请求/应答模式) 与 Servlet 进行交互。
在上诉介绍中,我们简单回顾一下 Servlet 的基本介绍。
Servlet 容器
Servlet 容器是 Web 服务器或应用服务器的一部分,主要作用是:
- 能根据具体请求参数调用对应的 servlet 对象进行请求处理(具体请求和响应对象也是 servlet 产生)
- 动态产生响应发送给客户端,发送数据到客户端是通过响应对象(response)完成的。
- servlet 完成请求后,Servlet 容器必须保证响应正确输出,并将控制权还给宿主 Web 容器。
Servlet 的体系结构
Servlet 请求处理原理
这里需要注意的是:
- HttpServletRequest 与 HttpServletResponse 是由 Servlet 容器产生并传递给具体的 servlet。
- 请求接入时由 Web 服务器先根据请求,解析请求行以及请求头部字段,进行解析状态转移,这样经过处理的请求就会到具体的处理容器中(Servlet 容器)。
- Servlet 容器再对请求进行进一步解析,根据解析结果找到对应的 servlet 处理请求,并产生 HttpServletRequest 与 HttpServletResponse,传入 servlet。
- servlet 处理请求完成后,将响应信息写入 Response 中交由 Web 服务器响应给客户端。
以上就是我个人对于请求过程的一个小结。
Servlet 生命周期
一开始学习 Java Web 时,很好奇没有 main 方法为什么 servlet 就可以处理请求了,主要是没有好好理解,Servlet 容器与 servlet 的关系,以及 servlet 生命周期。
Servlet 与 Servlet 容器
回顾:servlet 被 Servlet 容器(后续都叫容器)所管理,当我们一个 Web 应用写好后,部署到 Web 服务器上,当启动服务器,Web 应用就会被启动,servlet 只在第一次被访问时由容器进行加载等一系列前置操作,让后请求就会被具体的 servlet 处理。一次请求结束后,下一次请求相同的 servlet 时,不会二次加载了,而是直接调用 service()、doGet()、doPost()
处理请求,包括销毁 servlet 也是交给容器完成,我们手动调用 destroy()
无法手动销毁。
每一次请求都会开辟一个线程来单独处理,而不是再创建 servlet,例如:
生命周期:
Servlet 被 Servlet 容器按照严格的生命周期进行管理,规定了 Servlet 加载、初始化、实例化、处理请求以及结束服务,所有的 Servlet 都必须直接或间接实现 GenericServlet 或 HttpServlet。
这里主要将 init(),servlet 被加载过程
加载 servlet:Servlet 容器,通过解析 URL,找出对应的 servlet,让后自动调用构造方法 servlet 实例化(单例模式),被加载的 servlet 对象会被容器管理。
init()初始化:在实例化之后容器调用,对 servlet 进行一些配置,每个 servlet 在整个生命周期只会被调用一次。接下来的多次访问并不会再调用,只是重复调用 service 方法。
我们查看源码发现,在 GenericServlet 类中有两个 init(),有参数的调用了无参的,主要是如果我们对 servlet 在初始化的时候需要进行一些手动配置,可以重写此方法,一般情况下不需要重写。
Servlet 中文乱码
无外乎几种常见情况:
- 请求参数乱码:
- POST:
request.setCharacterEncoding('uth-8');
- GET:
String val = new String(value.getBytes("ISO-8859"),"UTF-8");
- 或直接在 Tomcat 的 server.xml 中直接规定服务器使用的编码格式为 UTF-8 即可。
- POST:
- 响应乱码:
设置响应头编码格式为 UTF-8, response.setHead("Context-Type","text/html;charset=utf-8");
- 数据库乱码:
在数据连接参数 URL 中设置:&characterEncoding=UTF-8
- 显示页面乱码:一般是 JSP/HTML 页面编码设置问题
Servlet 的部署(idea 环境)
简述一下 Servlet 的部署。
1. 配置环境
创建 java 项目:servlet-demo
将普通 java 项目改为 webapp 项目:
对 web.xml 的版本进行选择,之后就会项目目录下就会出现 web 的目录结构,让后就可以项目添加至 Tomcat 服务器中了。
如果不用 maven 进行管理,直接导入 jar 包,反之则在 pom.xml 中添加对应版本的 servlet 相关依赖:
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>jsp-api</artifactId>
<version>2.2</version>
</dependency>
</dependencies>
具体版本需要自己根据 jdk 来选择。
直接运行 tomcat 看看部署环境是否成功。
2. 创建 Servlet 类
在 main/java
下创建 MyServlet
类,并继承 HttpServlet
自己重写 service、doGet、doPost
方法,实现业务逻辑。
3. 设置 Servlet 类的映射
编写 web.xml 中,为 servlet 类配置映射。
也可以直接在 servlet 类上直接用注解方式,但是注意是 Servlet 3 版本以上才有的。
@WebServlet("/MyServlet");
两者只能存在一种,不然会报错。
小结
其实也没有多深入学习 Servlet,最多也就是回顾一下 Servlet,温故知新,回顾一下基本原理,如果要更深入了解,应该是要到工作以后了,反射、代理、Tomcat 刨析、映射、IO等各种原理,层层交织,有序组织,最后实现。希望自己在学习途中能好好稳固基础,探究原理。