小言_互联网的博客

JavaWeb核心技术系列教程(04)——Servlet入门详解及原理剖析

200人阅读  评论(0)

C语言自学完备手册(33篇)

Android多分辨率适配框架

JavaWeb核心技术系列教程

HTML5前端开发实战系列教程

MySQL数据库实操教程(35篇图文版)

推翻自己和过往——自定义View系列教程(10篇)

走出思维困境,踏上精进之路——Android开发进阶精华录

讲给Android程序员看的前端系列教程(40集免费视频教程+源码)


版权声明

  • 本文原创作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

Servlet简介

Servlet由Sun公司研发,它是一种运行在Web服务器中的小型Java程序。Servlet通过HTTP协议接收Web客户端的请求并对其作出响应。其实,关于Servlet的作用,我们只看它的名字也能知晓一些端倪:Serv是Server(Service)的缩写;let后缀表示"小"的含义.比如:booklet表示小册子,townlet表示小镇,lakelet表示小湖…server表示服务器;所以把Server(Service)与let后缀融合在一起的Servlet表示服务端的小程序。嗯哼,这么说是不是就更形象和便于理解呢?

Servlet概述

Servlet是一个Java类,它不能独立运行;Servlet的运行由Servlet引擎来控制和调度。Servlet引擎是一种容器程序,它负责管理和维护所有Servlet对象的生命周期;因此,它也被称之为Servlet容器或Web容器。Servlet的加载、执行、以及如何接收客户端发送的数据、以及如何将数据传输到客户端等底层事务都是由Servlet引擎来实现的。也就是说:Servlet引擎负责将客户端的请求信息转交给Servlet并将Servlet生成的响应信息返回给客户端。Servlet自身提供了一些约定的方法供Servlet容器去调用,它只负责在自身的方法中接受并处理Servlet容器传递进来的数据,以及生成响应数据并返回至Servlet容器,最终由servlet容器将响应数据返回至客户端。

在JavaWeb中提供三种方式实现servlet技术:javax.servlet.Servlet接口、javax.servlet.GenericServlet类、javax.servlet.http.HttpServlet类;在此,我们先来学习javax.servlet.Servlet接口。

javax.servlet.Servlet接口

javax.servlet.Servlet接口是Servlet技术的根基,所有的Servlet类都必须实现这一接口。在该接口中定义了如下方法:

public void init(ServletConfig config) throws ServletException;
 
public void destroy();
 
public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;

public String getServletInfo();

public ServletConfig getServletConfig();

各方法详解如下:

init(ServletConfig config)

该方法负责Servlet初始化工作。Servlet容器在创建好Servlet对象后,就会调用此方法。该方法输入参数为ServletConfig类型,Servlet容器通过该参数向Servlet传递初始化配置信息。

service(ServletRequest req,ServletResponse res)

该方法负责响应用户的请求,当Servlet容器接收到客户端访问Servlet对象的请求时就会调用此方法。Servlet容器会构造一个表示客户端请求信息的 ServletRequest对象和一个用于响应客户端的ServletResponse对象作为参数传递给service( )方法。在service( )方法中,可通过ServletRequest对象得到客户端的相关信息和请求信息,在对请求进行处理后,调用ServletResponse对象的方法设置响应信息及相关数据。

destroy( )

该方法负责释放Servlet对象占用的资源。当Servlet对象被销毁时容器会调用此方法。

getServletInfo( )
该方法以字符串形式返回包含Servlet创建者、版本和版权等信息。

getServletConfig( )

该方法返回Servlet容器调用init(ServletConfig config)方法时传递给Servlet的ServletConfig对象

Servlet入门示例

第一步:创建JavaWeb工程



点击Finish后创建JavaWeb工程,工程结构如下图所示:

第二步:编写JavaWeb工程默认主页

选中WebContent文件夹,右键新建index.html文件

第三步:编写Java类实现Servlet接口

package cn.com;

import java.io.IOException;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
public class TestServlet implements Servlet {

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init( )");
	}

	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		System.out.println("service( )");
	}
	
	@Override
	public void destroy() {
		System.out.println("destroy( )");
	}

	@Override
	public String getServletInfo() {
		System.out.println("getServletInfo( )");
		return null;
	}
	
	@Override
	public ServletConfig getServletConfig() {
		System.out.println("ServletConfig( )");
		return null;
	}

}

第四步:在web.xml中注册和配置Servlet

为了让Servlet容器能够管理和调度Servlet,我们必须在web.xml文件中注册并配置Servlet。

代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" 
         id="WebApp_ID" 
         version="3.1">
  <display-name>ServletHelloWorld00</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
  <servlet>
     <servlet-name>TestServlet</servlet-name>
     <servlet-class>cn.com.TestServlet</servlet-class>
  </servlet>
  <servlet-mapping>
     <servlet-name>TestServlet</servlet-name>
     <url-pattern>/TestServlet</url-pattern>
  </servlet-mapping>
</web-app>

在该配置中:servlet标签用于注册servlet,它的子标签servlet-name和servlet-class分别用于指定servlet的名称和完整类名。

在该配置中:servlet-mapping标签用于映射Servlet对外访问的虚拟路径,它的子标签servlet-name必须和servlet标签的子标签servlet-name保持一致;它的子标签url-pattern用于指定访问该Servlet的虚拟路径,该路径以正斜线/开头代表当前Web应用程序的根目录。

图示如下:

第五步:运行JavaWeb项目


接下来,我们在地址栏输入http://localhost:8080/ServletHelloWorld00/TestServlet 并回车访问之前注册的Servlet即TestServlet。

图示如下:

在此,我们访问了Servlet;而且,控制台也打印出来了相关测试信息。

Servlet入门进阶

在刚才的入门示例中,我们访问了Servlet之后当前页面一片空白。其实,我们完全可以在service( )方法中向客户端返回信息,比如:文本,网页等等。

代码如下:

package cn.com;

import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
 * 本文作者:谷哥的小弟
 * 博客地址:http://blog.csdn.net/lfdfhl
 */
public class TestServlet implements Servlet {

	@Override
	public void init(ServletConfig config) throws ServletException {
		System.out.println("init( )");
	}

	@Override
	public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
		System.out.println("service( )");
		responseHtml(res);
		//responseText(res);
	}
	
	@Override
	public void destroy() {
		System.out.println("destroy( )");
	}

	@Override
	public String getServletInfo() {
		System.out.println("getServletInfo( )");
		return null;
	}
	
	@Override
	public ServletConfig getServletConfig() {
		System.out.println("ServletConfig( )");
		return null;
	}
	
	//向客户端返回文本
	public void responseText(ServletResponse response) {
		try {
			PrintWriter writer = response.getWriter();
			writer.write("This is response from server");
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	
	//向客户端返回网页
	public void responseHtml(ServletResponse response) {
		try {
			PrintWriter writer = response.getWriter();
			writer.write("<!DOCTYPE html>");
			writer.write("<html>");
			writer.write("<head>");
			writer.write("<meta charset=\"UTF-8\">");
			writer.write("<title>Servlet</title>");
			writer.write("</head>");
			writer.write("<body>");
			writer.write("<H1>Hello Servlet</H1>");
			writer.write("</body>");
			writer.write("</html>");
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}

}

请重新运行JavaWeb项目并访问http://localhost:8080/ServletHelloWorld00/TestServlet

图示如下:

浏览器访问Servlet的过程

在对Servlet有了基础的了解之后,我们再结合刚才的示例分析浏览器访问Servlet的过程。

第一步

浏览器根据用户的请求生成HTTP请求消息并将消息发送至Servlet容器

第二步

Servlet容器收到请求后检査内存中是否存在负责处理当前请求的Servlet程序的实例对象。如果不存在则加载和创建该Servlet对象

第三步

Servlet容器创建针对该次访问的请求对象request和响应对象response,它们是Servlet容器与Servlet程序进行通信的纽带。请求对象request中包含了HTTP的请求信息。响应response对象用于封装将要回送给浏览器的http响应信息,只不过此时响应对象中的初始内容为空;但是,以后可以调用它的各种方法来生成HTTP响应消息的各个部分。

第四步

Servlet容器调用Servlet的service(ServletRequest req, ServletResponse res)方法并将请求对象request和响应对象response传递给该方法。

第五步

Servlet对象的service(ServletRequest req, ServletResponse res)方法从请求对象request中读取请求信息并将依据该请求生成的响应消息放入响应对象response。至此,Servlet对象完成了对于请求的响应。

第六步

Servlet容器从响应对象response中获取响应消息并返回至浏览器。

总 结

Servlet容器与Servlet程序之间并不是直接地、正面地、手递手地通信。它们两者之前是通过请求对象request和响应对象response进行信息交互。Servlet容器创建请求对象request和响应对象response,Servlet程序使用请求对象request和响应对象response。

Servlet生命周期

在之前的讲解中,我们提到:javax.servlet.Servlet接口是Servlet技术的根基,是Servlet技术的核心,该接口中定义了如下五个方法:

public void init(ServletConfig config) throws ServletException;
 
public void destroy();
 
public void service(ServletRequest req, ServletResponse res)throws ServletException, IOException;

public String getServletInfo();

public ServletConfig getServletConfig();

在这五个方法中有三个属于生命周期方法:init(ServletConfig config)、service(ServletRequest req, ServletResponse res)、destroy( )。

按照时机和功能的不同,我们大致可将Servlet的生命周期分为三个阶段,分别是初始化阶段、运行阶段和销毁阶段。

初始化阶段

当客户端向Servlet容器发出HTTP请求要求访问Servlet时,Servlet容器首先会解析请求,检查内存中是否已经有了该Serlvet对象,如果存在则直接使用该Serlvet对象,如果不存在就创建Servlet实例对象,然后通过调用init(ServletConfig config)方法完成相关初始化工作。请注意:在Servlet的整个生命周期内init(ServletConfig config)方法只会被调用一次。

运行阶段

在该阶段Servlet容器会为该请求创建代表HTTP请求的ServletRequest对象和代表HTTP响应的ServletResponse对象,然后将它们作为参数传递给Servlet的service(ServletRequest req, ServletResponse res)方法。service(ServletRequest req, ServletResponse res)从ServletRequest对象中获取请求信息并处理该请求,通过ServletResponse对象生成响应结果。在 Servlet的整个生命周期内,针对Servlet的每一次访问请求,Servlet容器都会调用一次 Servlet的service(ServletRequest req, ServletResponse res)方法并创建新的ServletRequest对象和ServletResponse对象。也就是说,service(ServletRequest req, ServletResponse res)方法在Servlet的整个生命周期中会被调用多次。

销毁阶段

当服务器关闭或应用程序被移除出容器时Serlvet会被销毁。 在销毁Servlet之前,Servlet容器会调用Servlet的destroy( )方法从而释放相关资源。请注意:在Servlet的整个生命周期中destroy( )方法也只会被调用一次。

总 结

  • Servlet程序不能单独、自主运行。
  • Servlet容器负责Servlet的创建、运行、销毁。
  • Servlet程序的生命周期方法由Servlet容器调用。

Web应用与Tomcat

至此,我们已经写了几个简单的JavaWeb工程并且将其部署至Tomcat运行。当JavaWeb工程被发布至Tomcat后,它存在于Tomcat安装目录\webapps目录下,例如:C:\Program Files\Apache Software Foundation\Tomcat 9.0\webapps

图示如下:

再打开刚才写的Servlet入门程序,图示如下:

这些文件和目录有什么含义呢?目录里都存放了什么东西东西呢?别急,接下来,我们来了解Web应用的目录结构。

Web应用由多个Web资源或者其它文件组成,其中包括html文件、css文件、js文件、动态web页面、java程序、jar包、配置文件等等。开发人员在开发Web应用时应按照一定的目录结构来存放这些文件。否则,当把web应用交给web服务器管理时不仅可能造成web应用无法访问,还会导致web服务器报错。

Web应用目录如下:

  • 1、Web应用根目录。通常情况下把Web应用的资源,例如css、js、html、jsp等置于web应用的根目录。当然也可以把这些资源分门别类地放到与其对应的文件夹中。例如,可以在web应用根目录下建立一个html文件夹专门用于存放html文件;假设其中有个页面index.html,这时访问URL为:http://localhost:8080/应用名/html/index.html。请注意:外界可以直接访问在web应用根目录下的内容。

  • 2、WEB-INF文件夹。请注意:这个目录名称必须是大写,而且该目录下的内容是无法通过浏览器直接访问的。在该文件夹下主要有以下内容:
    (1)、web.xml:Web应用程序的配置文件
    (2)、classes:存放编译后的.class文件
    (3)、lib:存放Web应用所需的jar包

  • 3、META-INF文件夹。该文件夹用于存放meta information相关文件。一般情况下,请勿修改该文件夹中的内容。


转载:https://blog.csdn.net/lfdfhl/article/details/101350016
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场