JavaWeb 三大组件之 Servlet
Servlet概述
之所以学习Servlet,是因为他是很多框架的基础,例如SpringMVC的DispatcherServlet,理解Servlet原理对理解其他框架很有帮助
- 生命周期方法:
- void init(ServletConfig config):初始化方法,Web容器如Tomcat创建Servlet时该方法执行一次;
- void service(ServletRequest request, ServletResponse response):每次处理请求时都会被调用;
- void destroy():Servlet销毁,关闭Web容器销毁Servlet会执行一次;
- 特性:
- 单例,一个类只有一个对象;当然可能存在多个Servlet类!
- 线程不安全的,所以它的效率是高的!
Servlet类由我们来写,但其对象由Web容器来创建,并且由Web容器来调用相应的方法。
1. 什么是Servlet
Servlet是JavaWeb的三大组件之一,它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
- 接收请求数据;
- 处理请求;
- 完成响应。
例如客户端发出登录请求,或者发出注册请求,这些请求都应该由Servlet来完成处理!Servlet需要我们自己来编写,每个Servlet必须实现javax.servlet.Servlet接口。
2. 实现Servlet的方式
实现Servlet有三种方式:
- 实现javax.servlet.Servlet接口;
- 继承javax.servlet.GenericServlet类;
- 继承javax.servlet.http.HttpServlet类;
通常我们会去继承HttpServlet类来完成我们的Servlet,先开始了解javax.servlet.Servlet接口。
Servlet接口源码(删除了大部分注释便于阅读)
package javax.servlet;
import java.io.IOException;
/**
* Defines methods that all servlets must implement.
*/
public interface Servlet {
/**
* Called by the servlet container to indicate to a servlet that the
* servlet is being placed into service.
*/
public void init(ServletConfig config) throws ServletException;
/**
* Returns a {@link ServletConfig} object, which contains
* initialization and startup parameters for this servlet.
*/
public ServletConfig getServletConfig();
/**
* Called by the servlet container to allow the servlet to respond to
* a request.
* @param req the <code>ServletRequest</code> object that contains
* the client's request
*
* @param res the <code>ServletResponse</code> object that contains
* the servlet's response
*/
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException;
/**
* Returns information about the servlet, such
* as author, version, and copyright.
* @return a <code>String</code> containing servlet information
*/
public String getServletInfo();
/**
* Called by the servlet container to indicate to a servlet that the
* servlet is being taken out of service.
*/
public void destroy();
}
3. 创建helloServlet应用
建立一个动态Web工程
next–>
创建package,编写一个HelloServlet
public class HelloServlet implements Servlet {
@Override
public void destroy() {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException {
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
System.out.println("Hello Servlet!");
}
}
在web.xml文件中配置Servlet
<servlet>
<servlet-name>helloServlet</servlet-name>
<servlet-class>com.yo.servlet.demo.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>helloServlet</servlet-name>
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
发布到tomcat 发布过程参见
浏览器访问,我创建的项目servletdemo下的helloServlet
Servlet接口
1. Servlet的生命周期
所谓某某某的生命周期,就是说某某某的出生、服务,以及死亡。Servlet生命周期也是如此!与Servlet的生命周期相关的方法有:
- void init(ServletConfig config);
- void service(ServletRequest req,ServletResponse res);
- void destroy();
1.1 Servlet 的初始化
服务器会在Servlet第一次被访问时创建Servlet,或者是在服务器启动时创建Servlet。如果服务器启动时就创建Servlet,那么还需要在web.xml文件中配置。也就是说默认情况下,Servlet是在第一次被访问时由服务器创建的。
而且一个Servlet类型,服务器只创建一个实例对象(单例),例如在我们首次访问http://localhost:8080/helloservlet/helloworld时,服务器通过“/helloworld”找到了绑定的Servlet名称为com.yo.servlet.demo.HelloServlet,然后服务器查看这个类型的Servlet是否已经创建过,如果没有创建过,那么服务器才会通过反射来创建HelloServlet的实例。当我们再次访问http://localhost:8080/helloservlet/helloworld时,服务器就不会再次创建HelloServlet实例了,而是直接使用上次创建的实例。
在Servlet被创建后,服务器会马上调用Servlet的void init(ServletConfig)方法。而且这个方法只会被调用一次。
我们可以把一些对Servlet的初始化工作放到init方法中!
1.2 Servlet服务
当服务器每次接收到请求时,都会去调用Servlet的service()方法来处理请求。服务器接收到一次请求,就会调用service() 方法一次,所以service()方法是会被调用多次的。正因为如此,所以我们才需要把处理请求的代码写到service()方法中!
1.3 Servlet的销毁
Servlet是不会轻易destroy,通常都是在服务器关闭时Servlet才会destroy!在服务器被关闭时,服务器会去销毁Servlet,在销毁Servlet之前服务器会先去调用Servlet的destroy()方法,我们可以把Servlet对某些资源的释放等代码放到destroy()方法中。
1.4 测试生命周期方法
public class HelloServlet implements Servlet {
@Override
public void destroy() {
System.out.println("HelloServlet destroy...");
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void init(ServletConfig arg0) throws ServletException {
System.out.println("HelloServlet init...");
}
@Override
public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
System.out.println("Hello Servlet!");
}
}
运行结果
HelloServlet init...
Hello Servlet!
2. Servlet接口相关类型
在Servlet接口中还存在三个类型
- ServletRequest:service() 方法的参数,它表示请求对象,它封装了所有与请求相关的数据,它是由服务器创建的;
- ServletResponse:service()方法的参数,它表示响应对象,在service()方法中完成对客户端的响应需要使用这个对象;
- ServletConfig:init()方法的参数,它表示Servlet配置对象,它对应Servlet的配置信息,对应web.xml文件中的 <servlet>xxx</servlet>元素。
2.1 ServletRequest和ServletResponse
ServletRequest和ServletResponse是Servlet#service() 方法的两个参数,一个是请求对象,一个是响应对象,可以从ServletRequest对象中获取请求数据,可以使用ServletResponse对象完成响应。
ServletRequest和ServletResponse的实例由服务器创建,然后传递给service()方法。如果在service() 方法中希望使用HTTP相关的功能,那么可以把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse。但之后讨论的HttpServlet会很好的处理这个强转问题。
2.2 ServletConfig
ServletConfig对象对应web.xml文件中的<servlet>xxx</servlet>元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取!下面这个配置获取的就是helloServlet
<servlet>
<servlet-name>helloServlet