JavaWeb:是用Java技术来解决相关web(Web就是在Http协议基础之上, 利用浏览器进行访问的网站)互联网领域的技术总和.

一、Servlet与Servlet容器

1、什么是Servlet

     Servlet是一个JavaEE的组件,Servlet是一个程序(类),只不过必须要遵循Servlet的规范,必须实现Servlet接口

     Servlet也是JavaEE中的一个规范,服务器其实是对Servlet的实现。

     Java Servlet(Java服务器小程序)是一个基于Java技术的Web组件,运行在服务器端,它由Servlet容器所管理,用于生成动态的内容。即 运行在服务器端以多线程的方式处理客户端请求的小程序

2、Servlet容器

      Servlet容器也叫做Servlet引擎,是Web服务器或应用程序服务器的一部分,Servlet没有main方法,不能独立运行,它必须被部署到Servlet容器中,由容器来实例化和调用 Servlet的方法,Servlet容器在Servlet的生命周期内包容和管理Servlet。管理和运行Servlet/JSP的容器也称为Web容器

      Web容器的产品:Tomcat,JBoss,WebSphere,WebLogic 等等

3、Servlet可以完成以下功能

     1)创建并返回客户请求的动态HTML页面

     2)创建可以嵌入到 HTML页面的HTML片段

     3)与其他服务器(如数据库或基于Java的应用程序)进行通信

二、搭建一个Servlet程序

1、新建一个 dynamic web project动态的 JavaWeb项目

2、新建一个 DemoServlet类

     Servlet的含义:运行在服务器端的以多线程的方式处理客户端请求的小程序

     可以让 DemoServlet类去 implements Servlet接口 extends GenericServlet类 extends HttpServlet类

import java.io.IOException;

import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

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

    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

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

    @Override
    public String getServletInfo() {
        return null;
    }

    @Override
    public void destroy() {
        System.out.println("destroy");      
    }   
}

3、在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>DemoServlet</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>

	 <!-- 
	    1.注册servlet
	        servlet-name的值是可以自定义的
	        servlet-class 包名加上类名 -->	   
	<servlet>
		<servlet-name>HelloServlet</servlet-name>
		<servlet-class>cn.jq.demo.HelloServlet</servlet-class>
	</servlet>
	<!-- 
	    2.给已注册的servlet,映射一个url地址
	        servlet-name的值和servlet标签中的servlet-name值一致
	        url-pattern:servlet的访问方式 是可以自定义的,但是必须以 / 打头   -->
	<servlet-mapping>
		<servlet-name>HelloServlet</servlet-name>
		<url-pattern>/hello</url-pattern>
	</servlet-mapping>
	
</web-app>

4、项目部署到服务器

     浏览器访问:http://127.0.0.1:8080/DemoServlet/hello,然后 stop服务器

                        

 

三、Servlet的生命周期

      Servlet的生命周期:Servlet对象的创建,初始化,运行,销毁操作的整个过程。即阐述Servlet从产生到毁灭的整个过程。

      服务器(Tomcat)管理了Servlet对象的生命周期,Servlet的创建,初始化,运行,销毁行为的整个过程都是由Tomcat来负责调用的,

1、新建一个 LifeServlet类,注册同上

public class LifeServlet implements Servlet{    
    public LifeServlet() {
        System.out.println("构造方法");
    }

    // 初始化阶段 
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init");
    }

    // 获取Servlet的配置信息对象
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    // 响应客户请求阶段
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service");        
    }

    // 获取Servlet的信息(作者,版权等)
    @Override
    public String getServletInfo() {
        return null;
    }

    // 终止阶段
    @Override
    public void destroy() {
        System.out.println("destroy");   
    } 
}

       

2、Servlet生命周期相关方法

    1)Servlet对象的构造方法

         最先被执行,构造方法被执行意味着创建实例,且只会被执行一次,意味着Servlet是单例的,在整个Servlet容器中每个具体的Servlet实现类都只有一个实例! 

    2)init方法

         在一个Servlet的生命周期中,构造方法执行之后,马上被执行,且只会执行一次,之后无论用户执行多少次请求,都不会在调用该方法。

       关于init方法的执行时机,有两种方式可选:

       servlet默认是在用户第一次访问的时候创建而且只创建一个对象 是单例模式的(保证一个类只有一个对象产生),

       也可以设置Servlet容器启动时自动装载某些Servlet,这时创建的servlet对象也是单例模式的。 实现它只需要在web.XML文件中的<Servlet></Servlet>之间添加如下代码:

<servlet>
    <servlet-name>LifeServlet</servlet-name>
    <servlet-class>cn.jq.demo.LifeServlet</servlet-class>
    <!--若为大于0的正整数(默认值为0)时表示web应用启动时,自动装载对应的Servlet,整数越小,越优先执行,只执行一次随web应用启动时。
        若为负数,则会在第一次请求时被执行对象的Servler(和默认值一样)。 -->
    <load-on-startup>1</load-on-startup>
</servlet>

    3)service方法

        当一个客户请求该Servlet时,实际的处理工作全部有service方法来完成,service方法用来处理客户端的请求,并生成格式化数据返回给客户端。

        每一次请求服务器都会开启一个新的线程并执行一次service方法,service是由web容器来调用的。

    4)destroy方法

        该方法在整个生命周期中,也是只会被调用一次,在Servlet对象被销毁是调用,在servlet中,我们可以做一些资源的释放等操作,执行destory方法之后的servlet对象,会等待jvm虚拟机的垃圾回收机制择时回收。

总结:Servlet的生命周期:构造器 -> init方法 -> service方法(循环)-> destroy方法 

注意:

     1)Servlet类的构造器必须使用 public修饰

     2)Servlet类必须是无参数构造器(不写默认是)。原因:底层创建Servlet对象是 Class.newInstance()方式,必须有公共的无参数构造器

 

四、Servlet的请求流程

对上面的访问大致分析 Servlet的请求流程:

1、浏览器访问发送请求:http://127.0.0.1:8080/DemoServlet/life

2、Tomcat 解析请求:/DemoServlet/life

     上下文路径:/DemoServlet    资源名称: /life

3、解析Tomcat根 /cong/server.xml文件,获取其中所有的<Context>元素,并找到 path属性值为 /DemoServlet的元素,在读取该<Context>元素并获取docBase属性值,该属性值就是当前访问的Web项目的根路径。

      <Context docBase="DemoServlet" path="/DemoServlet" />

4、从该Web项目的根路径下找到 /WEB-INF/web.xml 文件

5、读取 web.xml文件,获取所有的<url-pattern>元素,并判断查到值为  /life。

     找到:进入第6步     找不到:报 404错误

6、通过资源名称 /life,找到当前Servlet的全限定名:cn.jq.demo.LifeServlet

7、从Servlet的实例缓存池(Map集合)中获取 cn.jq.demo.LifeServlet对应的对象

      Map<String, Servlet> cache = ...;

     若为第一次请求:进入第8步,否则:进入第11步。

8、使用反射创建Servlet对象

     Servlet obj = Class.forName("cn.jq.demo.LifeServlet").newInstance();

9、把创建的Servlet对象存储到Servlet实例缓存池中,供下次请求使用。

     cache.put("cn.jq.demo.LifeServlet", obj );

10、Web容器创建 ServletConfig对象,并调用 init方法,来完成初始化操作

11、Web容器容器创建 ServletRequest和 ServletResponse对象,并调用service方法处理请求

12、在service方法中,通过ServletResponse对象对当前请求的客户端作为响应。

五、Servlet初始化参数

1、ServletConfig 接口:表示当前的 Servlet的配置信息对象

      在web.xml中,每个Servlet可以单独配置/获取其初始化的配置信息。可以用一个或多个<init-param>标签(在Servlet标签里面)为 Servlet配置一些初始化参数。

    1)Servletconfig接口的方法:

StringgetInitParameter(String name)

Gets the value of the initialization parameter with the given name.

Enumeration<String>getInitParameterNames()

Returns the names of the servlet's initialization parameters as an Enumeration of String objects, or an empty Enumeration if the servlet has no initialization parameters.

ServletContextgetServletContext()

Returns a reference to the ServletContext in which the caller is executing.

StringgetServletName()

Returns the name of this servlet instance.

 

2、ServletCotext接口:很重要,先简单认识一下

      如果多个Servlet有公共的初始化参数时,此时得使用全局的初始化参数

      在web.xml中,可以用一个或多个<context-param>标签(与Servlet标签并列)为整个Web应用配置初始化信息,所有的Servlet都能访问配置的初始化信息。

    1)ServletContext域对象可以在整个web应用范围内共享数据

         作用范围:整个web应用范围内共享数据          

         生命周期:当服务器启动web应用加载后创建出ServletContext域对象。当web应用被移除出容器或服务器关闭时随着web应用的销毁域销毁。

    2)ServletContext接口的方法:

          方法很多,具体查看API:https://docs.oracle.com/javaee/7/api/

3、获取初始化参数

	<context-param>
		<param-name>encoding</param-name>
		<param-value>GBK</param-value>
	</context-param>
	<context-param>
		<param-name>password</param-name>
		<param-value>123456</param-value>
	</context-param>
	
	<servlet>
		<servlet-name>LifeServlet</servlet-name>
		<servlet-class>cn.jq.demo.LifeServlet</servlet-class>
		<!-- 配置该servelt的初始化参数(键值对) -->
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
		<init-param>
			<param-name>username</param-name>
			<param-value>admin</param-value>
		</init-param>
	</servlet>

      

public class LifeServlet implements Servlet {
    private ServletContext servletContext;

    // 初始化阶段 
    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("init");
        //获取当前Servlet在web.xml中配置的名字
        System.out.println(config.getServletName());

        //获取当前Servlet指定名称的初始化参数的值
        String usernameValue = config.getInitParameter("encoding");
        System.out.println(usernameValue);

        //获取当前Servlet所有初始化参数的名字
        Enumeration enumeration = config.getInitParameterNames();
        while (enumeration.hasMoreElements()) {
            String name = (String) enumeration.nextElement();
            String value = config.getInitParameter(name);
            System.out.println(name + ":" + value);
        }

        //获取代表当前web应用的ServletContext对象
        this.servletContext = config.getServletContext();
        System.out.println(servletContext);
    }

    // 响应客户请求阶段
    @Override
    public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
        System.out.println("service");
        // 获取单个的Context里面的初始化参数
        String value1 = servletContext.getInitParameter("encoding");
        String value2 = servletContext.getInitParameter("password");
        System.out.println(value1 + ";" + value2);

        // 一次性获取Context里所有的初始化参数
        Enumeration enumeration = servletContext.getInitParameterNames();
        while (enumeration.hasMoreElements()) {
            String name = (String) enumeration.nextElement();
            String value = servletContext.getInitParameter(name);
            System.out.println(name + ";" + value);
        }

        //获取当前WEB应用的名称
        System.out.println(servletContext.getContextPath());
    }
    ... 
}

     

 

   重新整理了下

ends ~

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐