Servlet 是在服务器上运行的小程序。这个词是在 Java applet的环境中创造的,Java applet 是一种当作单独文件跟网页一起发送的小程序,
它通常用于在客户端运行,结果得到为用户进行运算或者根据用户互作用定位图形等服务。
Servlet 的主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。
实现过程:
-
客户端发送请求至服务器端;
-
服务器将请求信息发送至 Servlet;
-
Servlet 生成响应内容并将其传给服务器。响应内容动态生成,通常取决于客户端的请求;
-
服务器将响应返回给客户端。
详细原理
-
客户端请求该 Servlet;
-
加载 Servlet 类到内存;
-
实例化并调用init()方法初始化该 Servlet;
-
service()(根据请求方法不同调用doGet() 或者 doPost(),此外还有doHead()、doPut()、doTrace()、doDelete()、doOptions()、destroy()。
-
加载和实例化 Servlet。这项操作一般是动态执行的。然而,Server 通常会提供一个管理的选项,用于在 Server 启动时强制装载和初始化特定的 Servlet。
Server 创建一个 Servlet的实例
第一个客户端的请求到达 Server
Server 调用 Servlet 的 init() 方法(可配置为 Server 创建 Servlet 实例时调用,在 web.xml 中 <servlet> 标签下配置 <load-on-startup> 标签,
配置的值为整型,值越小 Servlet 的启动优先级越高)
一个客户端的请求到达 Server
Server 创建一个请求对象,处理客户端请求
Server 创建一个响应对象,响应客户端请求
Server 激活 Servlet 的 service() 方法,传递请求和响应对象作为参数
service() 方法获得关于请求对象的信息,处理请求,访问其他资源,获得需要的信息
service() 方法使用响应对象的方法,将响应传回Server,最终到达客户端。service()方法可能激活其它方法以处理请求,如 doGet() 或 doPost() 或程序员自己开发的新的方法。
对于更多的客户端请求,Server 创建新的请求和响应对象,仍然激活此 Servlet 的 service() 方法,将这两个对象作为参数传递给它。如此重复以上的循环,但无需再次调用 init() 方法。一般 Servlet 只初始化一次(只有一个对象),当 Server 不再需要 Servlet 时(一般当 Server 关闭时),Server 调用 Servlet 的 destroy() 方法。
service方法
特点:service方法,一般来说这个方法是不需要重写的,
默认的实现:根据请求的方式,调用doGet,doPost以及其他的doXXX方法。也就是说service是用来转向的,所以我们一般写一个servlet,只需要重写doGet或者doPost就可以了。
如果重写了service方法,那么servlet容器就会把请求交给这个方法来处理,倘若你重写的service方法没有调用doXXX,即使你在Servlet中又重写了其他doGet doPost等也是不回
被调用的因为Servlet的service被自动调用(就像init destory一样)。下面的一段代码就是这种情况
public class BaseServlet extends HttpServlet { private String command; private User user; private BeanFactory beanFactory; @Override protected final void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { <span style="white-space:pre"></span>
<pre name="code" class="java" style="color: rgb(68, 68, 68);"> <span style="white-space:pre"></span>
System.out.println("子类的实现"); super.service(req, resp);} }
public class FlowCardServlet extends BaseServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
<span style="white-space:pre">
</span>System.out.println("重写doGet方法"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { doGet(req, resp); }
他们之间的继承结构如下图:
其实从图中可以看出来,造成这种情况的原因就会因为子类重写了父类的方法,导致父类中默认的实现没有执行,解决方案就是在子类的方法实现末尾再调用一下父类的默认实现。即需要重写service方法,并且更具不同的method调用doPost doGet等时,就要在末尾加上一句super.service(),这样就可以解决问题了。