Servlet接口
什么是Servlet?
Servlet是一种基于Java技术的Web组件,用于生成动态内容,由容器管理,是平台无关的Java类组成,并且由Java Web服务器加载执行,是Web容器的最基本组成单元
什么是Servlet容器?
Servlet容器作为Web服务器或应用服务器的一部分,通过请求和响应提供Web客户端与Servlets交互的能力,容器管理Servlet实例以及它们的生命周期(创建、初始化、提供服务、销毁等)
在java web中不管是使用J2EE原生的servlet/jsp还是使用springmvc/springboot,在web服务器看来只是对外暴露出来的Servlet,而这个Servlet是javax.servlet.Servlet接口,该接口定义了Servlet引擎与Servlet程序之间通信的协议约定。
1 | // Servlet的加载和实例化可以发生在容器启动时,也可以延迟初始化直到有请求需要处理时 |
而为了简化开发,jdk中提供了一个实现Servlet接口的简单的Servlet类,javax.servlet.GenericServlet,该类实现了Servlet的基本功能,对init(ServletConfig config)、service(ServletRequest req, ServletResponse res)和destroy()方法提供了默认实现
jdk针对HTTP协议专门提供了一个Servlet类,javax.servlet.http.HttpServlet,该类继承于GenericServlet类,在其基础上针对HTTP的特点进行扩充,一般编写程序时继承HttpServlet即可,这样只需要重写doGet()和doPost()方法即可
Servlet中涉及的主要对象
- 请求对象 ServletRequest、HttpServletRequest
- 响应对象 ServletResponse、HttpServletResponse
- Servlet配置对象 ServletConfig
- Servlet上下文对象 ServletContext
Servlet注册与运行
Servlet编写好之后需要在web.xml中进行注册和映射才能被Servlet容器加载从而被外界访问
1 | <!-- 注意servlet和servlet-mapping都是成对出现的 --> |
tomcat中的web.xml包含有一个缺省的Servlet
1 | <servlet> |
ServletConfig
对于每个Servlet可能在启动时都需要一些初始化参数,而所有的Servlet是交由Servlet引擎去实例化的,那么也就是需要将每个Servlet的初始化参数也都配置到web.xml中,Servlet引擎将Servlet容器对象和Servlet的配置信息封装到ServletConfig中,并在Servlet初始化时将ServletConfig传递给该Servlet。javax.servlet.ServletConfig接口的作用就是用来定义ServletConfig对象所需要对外提供的方法
1 | public interface ServletConfig { |
Servlet引擎装载并创建一个Servlet对象后,会调用该对象的init(ServletConfig config)方法,Servlet中的ServletConfig getServletConfig()方法会返回init传入的ServletConfig对象
1 | <servlet> |
1 | // 获取指定的属性 |
ServletContext
每个Web应用程序在启动时都会创建一个ServletContext对象,每个Web应用程序都有一个唯一的ServletContext对象,javax.servlet.ServletContext接口定义了ServletContext需要对外提供的方法,Servlet通过这些方法来和ServletContext容器进行通信
- 该对象代表当前WEB应用,可以获取到web应用的信息,一个Web应用只有一个ServletContext对象
- 可以使用ServletConfig的getServletContext()获取到ServletContext
- 可以获取web应用的初始化参数,这是全局的方法,
在web.xml中配置<context-param>
- 获取web应用某个文件的绝对路径(在服务器上的路径,不是部署前的方法) getRealPath
- 获取当前应用的名称 getContextPath
- 获取当前web应用的某一个文件对应的输入流 getResourceAsStream() path是相对于当前web应用的根目录
1 | <context-param> |
servlet生命周期
生命周期相关方法,servlet生命周期中的方法全是由servlet容器来调用的
- 构造器 web容器调用Servlet的无参构造器,默认是在第一次请求时被加载,可以通过load-on-startup标签来进行设置什么时候加载
- init方法
- service方法
- destory方法
init方法—初始化
init方法在第一次创建servlet时被调用,在后续每次请求时都不会被调用。
当用户调用servlet的时候,该servlet的一个实例就会被创建,并且为每一个用户产生一个新的线程,init()用于进行一些初始化数据的加载和处理,这些数据会被用于servlet的整个生命周期
1 | void init(ServletConfig config) throws ServletException; |
为了防止重写该方法时开发者忘记将入参config赋值给成员变量config,故而提供了GenericServlet类进行了一次封装
1 | public void init(ServletConfig config) throws ServletException { |
在进行Servlet重写时只需要重写不带参数的init方法即可
1 | public void init() throws ServletException |
该方法是由servlet容器调用的
什么时候触发初始化
有两种情况会进行Servlet的初始化
Servlet被客户端首次请求访问时触发初始化方法
如果配置了load-on-startup元素,则在Servlet容器启动该Servlet所属Web应用时就会初始化该Servlet
1
2
3
4
5
6
7<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>
org.springframework.web.servlet.DispatcherServlet
</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
重写init方法
GenericServlet实现了Servlet和ServletConfig,是一个抽象类,并对init(ServletConfig config)方法进行了一层封装,有一个ServletConfig成员变量,在init()方法中进行了初始化,使得可以直接在GenericServlet中直接使用ServletConfig方法
而我们平时写Servlet大多是继承于HttpServlet类的,在对init方法进行重写时,重写不带参的init()方法即可
1 | //GenericServlet类 |
该方法由GenericServlet的调用,如果需要使用到ServletConfig则调用getServletConfig()方法来获取
service方法
service方法是实际处理请求的方法,servlet容器调用service方法来处理请求,并将响应写回到客户端,每次服务器接收到一个新的servlet请求时,服务器会产生一个新的线程来调用服务
1 | void service(ServletRequest req, ServletResponse res) throws ServletException, IOException; |
处理请求逻辑
HttpServlet继承了GenericServlet,重写了service方法,将ServletRequest和ServletResponse转换为HttpServletRequest和HttpServletResponse,并根据不同的请求方式进行分发,doGet/doPost/doHead等
1 |
|
servlet可以在任何协议下访问 ,写的Servlet必须实现Servlet接口,在http协议下可以使用HttpServlet ,用来给Web访问的
在HttpServlet类中对于service()方法进行了处理,根据请求方式的不同,将请求分发到了不同的方法,而我们一般情况下写Servlet也是继承自HttpServlet的,所以在写请求处理逻辑时,只需要重写doGet()和doPost()方法即可
1 | // HttpServlet类 |
GET方法
GET方法时浏览器向web服务器传递信息的默认方法,会在地址栏上产生很长的字符串,且GET方法有大小限制,请求字符串中最多只能有1024个字符
POST方法
POST方法不将请求信息放到地址中
destroy方法
destory()方法只在servlet生命周期结束时被调用一次。可以在destory()方法中进行一些资源的清理,如关闭数据库连接、停止后台线程等