Shiliew 植树人

Servlet学习记录(一)

2017-02-24

  学习Servlet能帮助我们更好地理解MVC框架到底帮助我们做了什么,就像Hibernate和Mybatis这样的持久层框架封装了JDBC一样,Struts和SpringMVC封装了Servlet。所谓框架,就是将一些通用的功能组装在一起,留出接口以调用,省去我们每次都需要实现一遍通用功能的麻烦。那么现在,要搞懂SpringMVC的工作原理,就先要知道Servlet的工作过程。

Servlet是什么

  Servlet代表Server Applet,意思是服务器端小程序。而同时你也可以抽象地理解为一些遵从Java Servlet API的Java类。狭义上,Servlet是一个接口,广义上,任何实现了Servlet接口的类都可以被称为Servlet。

  HttpServlet继承GenericServlet抽象类,而GenericServlet实现Servlet接口。Servlet接口定义了五个方法,分别是:

  • init(ServletConfig) : void
  • getServlet() : ServletConfig
  • service(ServletRequest, ServletResponse) : void
  • getServletInfo() : String
  • destroy() : void

  Servlet可以响应任何请求,但最主要的应用还是响应HTTP请求。先看第一个简单的示例。


import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HelloServlet extends HttpServlet {

	private static final long serialVersionUID = -4739360880971235479L;

	public HelloServlet() {
		super();
	}
	
	public void destroy() {
		super.destroy(); // Just puts "destroy" string in log
		// Put your code here
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	}

	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

	}

	public void init() throws ServletException {
		// Put your code here
	}

}

  这是以前写过的一个示例,我将doGet和doPost中的代码都删除了,一般都是重写这两个方法完成自己的需要。在一个Servlet中,最重要的三个方法分别是init、service和destroy。上面代码没有写出service是因为一般我们不需要重写HttpServlet中的service方法。值得一提的是,在HttpServlet中,有两个service方法:一个是public修饰的service(ServletRequest, ServletResponse),其作用是接收客户端请求,将ServletRequest和ServletResponse转换为HttpServletRequest和将HttpServletResponse,并转发给另外一个service;另一个是protected修饰的service(HttpServletRequest, HttpServletResponse),这里则是调用相应的方法去处理请求。

  因为Servlet只能在Servlet容器中运行,如Tomcat,在完成了自己定义的Servlet类之后,需要将此Servlet注册到Servlet容器中。通常的做法是在项目的web.xml文件中定义,示例如下:

<servlet>
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>com.servlets.HelloServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/HelloServlet</url-pattern>
    </servlet-mapping>

  标签是用来声明一个Servlet的,标签中为定义的该Servlet的变量名,中为该Servlet的所在。标签用来表示特定的url会被拦截并交给某个声明的Servlet处理,表示与声明的Servlet变量名对应,表示需要拦截的url。具体的过程大致是:一个请求会被所有的进行匹配,当请求的url中有和中相同的时,就被其拦截。然后会根据中的变量名去寻找相应的servlet,找到后处理请求。

  当然还可以通过@webServlet注解去在Servlet类上注册Servlet,示例如下:

@WebServlet(name = "HelloServlet", urlPatterns = {"/HelloServlet"})
public class HelloServlet extends HttpServlet {...}

Servlet生命周期

  Servlet从初始化到销毁包含三个核心的方法:init、service和destroy。

  Servlet初始化阶段,Servlet容器会根据web.xml中的定义来初始化Servlet,标签中的数字表示启动顺序,负数表示不在项目启动时初始化,其余的按递增的顺序进行初始化。当一次请求发生时,Servlet容器会去内存中查找对应的Servlet对象,如果不存在,则创建。通过调用init()方法来初始化Servlet实例,该方法在Servlet实例的生命周期里面只会调用一次。

  Servlet初始化之后,Servlet容器就可以调用实例中的service()方法处理相应的请求了。

  在最后,Servlet容器在重新启动或者关闭时会调用destroy()方法来销毁Servlet实例,释放相应的资源。

  具体的过程以后学习并记录,先记录一个请求发送到Servlet容器并处理返回的流程示意图。 requestToServlet

  1. Web客户向Servlet容器发出Http请求;
  2. Servlet容器解析Web客户的Http请求;
  3. Servlet容器创建一个HttpRequest对象,在这个对象中封装Http请求信息;
  4. Servlet容器创建一个HttpResponse对象;
  5. Servlet容器调用HttpServlet的service方法,把HttpRequest和HttpResponse对象作为service方法的参数传给HttpServlet对象;
  6. HttpServlet调用HttpRequest的有关方法,获取HTTP请求信息;
  7. HttpServlet调用HttpResponse的有关方法,生成响应数据;
  8. Servlet容器把HttpServlet的响应结果传给Web客户。

参考

传送门一 传送门二


Comments

comments powered by HyperComments