静态网页:
静态网页是指存放在服务器文件系统中实实在在的HTML文件。当用户在浏览器中输入页面的URL,然后回车,浏览器就会将对应的html文件下载、渲染并呈现在窗口中。早期的网站通常都是由静态页面制作的。
动态网页:
当浏览器请求服务器的某个页面时,服务器根据当前时间、环境参数、数据库操作等动态的生成HTML页面,然后在发送给浏览器(后面的处理就跟静态网页一样了),如登陆注册验证,订单生成和提交等。很明显,动态网页中的“动态”是指服务器端页面的动态生成,相反,“静态”则指页面是实实在在的、独立的文件。
Web Project目录结构
Servlet 是什么?
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
使用Servlet,可以收集网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
要注意的是,由于 Servlet 是服务器端小程序,所以 Servlet 必须部署在 Servlet 容器中才能使用,例如 Tomcat,Jetty 等。
Servlet 容器
要介绍 Servlet 必须要先把 Servlet 容器说清楚,Servlet 与 Servlet 容器的关系有点像枪和子弹的关系,枪为弹而生,而弹又让枪有了杀伤力。虽然它们是彼此依存的,但是又相互独立发展,这一切都是为了适应工业化生产。从技术角度来说是为了解耦,通过标准化接口来相互协作。
Servlet容器又是什么东西?就是实现了Servlet规范,然后暴露出来一些编程的接口供我们实现自己的逻辑,所以每个自定义的Servlet类都要实现Servlet接口,它能够生成动态的内容,不向Web服务器一样,只是提供静态资源。
从上图可以看出 Tomcat 的容器分为四个等级,真正管理 Servlet 的容器是 Context 容器,一个 Context 对应一个 Web 工程
Servlet API
目前用的是Servlet 3.1 API - Apache Tomcat 8.0.53,有以下四个包
- javax.servlet:包含Servlet与Servlet容器进行通信需要的类和接口,比如请求、响应、过滤和监听等;
- javax.servlet.http:包含Servlet的实现类httpServlet与Servlet容器进行通信需要的类和接口;
- javax.servlet.annotation:使用Servlet、Filter和Listener时需要的注解;
- javax.servlet.descriptor:提供对配置信息进行编程式访问的类型;
servlet的核心技术就是实现Servlet接口,
如 javax.servlet.http.HttpServlet 类已经实现了 Servlet 接口的所有方法。
编写 Servlet时直接继承 HttpServlet,并覆盖需要的方法即可,一般只覆盖 doGet()与 doPost()方法
package servlet;
import java.io.IOException;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* Servlet implementation class HelloServlet
*/
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public HelloServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
/**
* @see Servlet#destroy()
*/
public void destroy() {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
response.getWriter().append("Served at: ").append(request.getContextPath());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
doGet(request, response);
}
}
Servlet 的生命周期
1,初始化阶段 调用init()方法
2,响应客户请求阶段 调用service()方法,由service()方法根据请求方式调用doGet()或者doPost()方法
3,终止阶段 调用destroy()方法
Servlet初始化阶段:
在下列时刻Servlet容器装载Servlet,Servlet被装载后,Servlet容器创建一个Servlet实例并且调用Servlet的init()方法进行初始化。在Servlet的整个生命周期内,init()方法只被调用一次。
1,Servlet容器启动时自动装载某些Servlet,实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码:
<loadon-startup>1</loadon-startup>
2,在Servlet容器启动后,客户首次向Servlet发送请求
3,Servlet类文件被更新后,重新装载Servlet
简单介绍一下servlet接受和响应的过程:
首先客户发送一个请求,servlet调用service方法对请求进行响应。通过源码可知,service()方法对请求的方式进行匹配,然后再进入对应的方法中调用逻辑层的方法,实现对客户的响应。在Servlet接口和GenericServlet中是没有doGet,doPost等等这些方法的,HttpServlet中定义了这些方法,但是都是返回error信息,所以,我们每次定义一个Servlet的时候,都必须实现doGet或doPost等这些方法。
GenericServlet是一个通用的,不特定于任何协议的Servlet,它实现了Servlet接口。而HttpServlet继承于GenericServlet,因此HttpServlet也实现了Servlet接口。所以我们定义Servlet的时候只需要继承HttpServlet即可。
Servlet接口和GenericServlet是不特定于任何协议的,而HttpServlet是特定于HTTP协议的类,所以HttpServlet中实现了service()方法,并将请求ServletRequest,ServletResponse强转为HttpRequest和HttpResponse。
public void service(ServletRequest req, ServletResponse res)
throws ServletException, IOException {
HttpServletRequest request;
HttpServletResponse response;
try {
request = (HttpServletRequest) req;
response = (HttpServletResponse) res;
} catch (ClassCastException e) {
throw new ServletException("non-HTTP request or response");
}
service(request, response);
}
public abstract class HttpServlet extends GenericServlet {}
public abstract class GenericServlet implements Servlet, ServletConfig,
java.io.Serializable {}
public interface Servlet {}
protected void doGet(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException
{
String protocol = req.getProtocol();
String msg = lStrings.getString("http.method_get_not_supported");
if (protocol.endsWith("1.1")) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, msg);
} else {
resp.sendError(HttpServletResponse.SC_BAD_REQUEST, msg);
}
}
Servlet响应请求阶段:
对于用户到达Servlet的请求,Servlet容器会创建特定于这个请求的ServletRequest对象和ServletResponse对象,然后调用Servlet的service方法。service方法从ServletRequest对象获得客户请求信息,处理该请求,并通过ServletResponse对象向客户返回响应信息。
public Map<String, String[]> getParameterMap();
/**
* Returns the name and version of the protocol the request uses in the form
* <i>protocol/majorVersion.minorVersion</i>, for example, HTTP/1.1. For
* HTTP servlets, the value returned is the same as the value of the CGI
* variable <code>SERVER_PROTOCOL</code>.
*
* @return a <code>String</code> containing the protocol name and version
* number
*/
Servlet终止阶段:
当WEB应用被终止,或Servlet容器终止运行,或Servlet容器重新装载Servlet新实例时,Servlet容器会先调用Servlet的destroy()方法,在destroy()方法中可以释放掉Servlet所占用的资源。
在哪些情况下 tomcat 容器会装载 servlet ?
1.
2.
3.
4.
Servlet与JSP的比较:
- 有许多相似之处,都可以生成动态网页。
- JSP的优点是擅长于网页制作,生成动态页面比较直观,缺点是不容易跟踪与排错。
- Servlet是纯Java语言,擅长于处理流程和业务逻辑,缺点是生成动态网页不直观。
参考文章