Servlet的原理、周期、创建方法、Servlet的线程安全、ServletConfig以及重要的ServletContext

1.什么是servlet

servlet是一个Java类,是用来专门处理请求和响应的,是部署在服务器上工作的小程序,之所以叫小程序,是因为它只要部署上去就自动运行工作了可以处理事情了。servlet 通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。
HTTP:
★ HTTP是HyperText Transfer Protocol(超文本传输协议)的简写,传输HTML文件。
★ 用于定义WEB浏览器与WEB服务器之间交换数据的过程及数据本身的格式。

2.操作步骤:

a.创建一个实现servlet接口的Java类(ServletDemo1)。
ServletDemo1爆红是因为实现了Servlet接口就需要重写里面的方法。实现接口所定义的方法。
在service方法里添加输出语句

@Override
  public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
      // TODO Auto-generated method stub
      System.out.println("执行Servlet里的方法");
      
  }

b.在web.xml中配置servlet的信息。
我们的目的就是让用户通过url来访问我们的刚刚实现了servlet接口的类,然后在这个类里面做一些处理。但是我们的类是写在src中,然后编译成字节码.class文件是存放在WEB-INF中的,我们部署应用的时候就把WEB-INF的东西部署到服务器上,而WEB-INF文件中的东西是不允许外部访问的,所以如果想要访问的这个类(严格意义上说是这个类生成的字节码文件),我们就需要通过一些配置来告诉服务器某个URL地址是用来访问某个类的。这就是我们为什么要配置web.xml的原因。(服务器Tomcat启动后加载项目最先扫描执行web.xml文件)

image.png

web.xml主要代码:

<servlet>
  <!-- 一般把类名首字母变小写作为servlet-name-->
    <servlet-name>ServelDemo1</servlet-name>
    <servlet-class>com.szy.web.servlet.ServelDemo1</servlet-class>
  </servlet>

这里的访问逻辑是,我们在浏览器输入localhost:8080/应用名/demo1后,它就会找到中相应的url(在中),然后根据这个url找到对应的叫servletDemo1,然后就在这个节点里再找到该对应的。至此,就自动找到这个类,去执行相应的任务了。
  <servlet>
    <servlet-name>servelDemo1</servlet-name>
    <servlet-class>com.cms.Demo1.Service.ServelDemo1</servlet-class>
  <!-- 2,填数字越小优先级越高,越先执行,让该servlet在服务器启动时就创建,不建议写零 -->
    <load-on-startup>2</load-on-startup>
  </servlet>
 <!-- 给Servlet映射一个可访问的URI :http://localhost:8080/项目名/demo1即可通过servelDemo1映射到ServelDemo1访问该类-->
  <servlet-mapping>
    <servlet-name>servelDemo1</servlet-name>
    <url-pattern>/demo1</url-pattern>
  </servlet-mapping>

com.szy.web.servlet.ServelDemo1路径的获得操作如下图:


image.png

执行结果:

浏览器显示空白页面但是控制台输出了ServletDemo1类里的执行结果。

image.png

3.Servlet的生命周期

此接口定义了初始化 servlet 的方法 init()、为请求提供服务的方法 service()和从服务器移除 servlet 的方法 destroy()。这些方法称为生命周期方法,它们是按以下顺序调用的:

a .初始化阶段 :
构造 servlet,然后使用 init 方法将其初始化。
b.响应客户请求阶段:
处理来自客户端的对 service 方法的所有调用。
c.终止阶段:
从服务中取出 servlet,然后调用 destroy 方法销毁它,最后进行垃圾回收并终止它。

除了生命周期方法之外,此接口还提供了 getServletConfig 方法和 getServletInfo 方法,servlet 可使用前一种方法获得任何启动信息,而后一种方法允许 servlet 返回有关其自身的基本信息,比如作者、版本和版权。

package com.szy.web.servlet;
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 ServelDemo1  implements Servlet {  
    public  ServelDemo1() {
        // 实例化方法
    }
    @Override
    public void init(ServletConfig arg0) throws ServletException {
        // 初始化      
    }
    @Override
    public void service(ServletRequest arg0, ServletResponse arg1) throws ServletException, IOException {
        // 服务
        System.out.println("执行Servlet里的方法");        
    }
    @Override
    public void destroy() {
        //销毁        
    }
    @Override
    public ServletConfig getServletConfig() {
        // TODO Auto-generated method stub
        return null;
    }
    @Override
    public String getServletInfo() {
        // TODO Auto-generated method stub
        return null;
    }
}

注意:
Servlet何时被创建:
  ★ 默认情况下,当WEB客户第一次请求访问某个Servlet的时候,WEB容器将创建这个Servlet的实例。
  ★ 当web.xml文件中如果<servlet>元素中指定了<load-on-startup>子元素时,Servlet容器在启动web服务器时,将按照顺序创建并初始化Servlet对象。
  ★ 在web.xml文件中,某些Servlet只有<serlvet>元素,没有<servlet-mapping>元素,这样我们无法通过url的方式访问这些Servlet,这种Servlet通常会在<servlet>元素中配置一个<load-on-startup>子元素,让容器在启动的时候自动加载这些Servlet并调用init()方法,完成一些全局性的初始化工作。

4.servlet的三种创建方式

Servlet --> GenericServlet --> HttpServlet -->我们定义的继承HttpServlet的类
曾祖父 爷爷 爸爸 孙子

方法如下:
a. 实现javax.servlet.Servlet接口(参见:编写一个servlet程序)
要实现此接口,还可以编写一个扩展 javax.servlet.GenericServlet 的一般 servlet,或者编写一个扩展 javax.servlet.http.HttpServlet 的 HTTP servlet。

image.png

b. 继承javax.servet.GenericServlet类(适配器模式)

image.png

只需重写抽象 service 方法,因为它里面只有一个抽象方法。

image.png
image.png

c. 继承javax.servlet.http.HttpServlet类(模板方法设计模式)
我们自己写Servlet的时候,处理请求的时候实现Service()就好。不重写Service()方法,而是重写doGet和doPost2个方法,在HttpServlet抽象类中,已经实现了Service方法了,在有请求进来Servlet的时候首先从请求中获取到请求提交的方式,所以我们直接重写doGet和doPost方法就好。通常来说不确定是什么请求的情况下,默认是Get请求,在doGet和doPost中实现一个就够了,如果方法的实现写在
HTTP的请求方式包括DELETE,GET,OPTIONS,POST,PUT和TRACE,在HttpServlet类中分别提供了相应的服务方法,它们是,doDelete(),doGet(),doOptions(),doPost(), doPut()和doTrace().
项目开发一般都用这种方式创建Servlet;
第一步:创建Servlet类文件
Ctrl+N;输入Servlet:

image.png

第二步:输入类名

image.png

第三步:映射路径的名字,默认为类名,可点击Edit编辑


image.png

第三步:勾选需要重写的方法:都默认勾选Doget和Dopost方法,点击Finish:
继承HttpServlet后不要重写service的方法,因为service方法里包含调用doget跟dopost的方法,重写了那两方法不执行就作废了


image.png

第五步:检查生成的类和Web.xml的Servlet配置信息

package com.cms.Demo1.Service;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ServletDemo4
 */
public class ServletDemo4 extends HttpServlet {
    private static final long serialVersionUID = 1L;
       
    /**
     * @see HttpServlet#HttpServlet()
     */
    public ServletDemo4() {
        super();
        // TODO Auto-generated constructor 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>
        <display-name>ServletDemo4</display-name>
        <servlet-name>ServletDemo4</servlet-name>
        <servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
    </servlet>
 
  <servlet-mapping>
    <servlet-name>ServletDemo4</servlet-name>
    <url-pattern>/ServletDemo4</url-pattern>
  </servlet-mapping>

注意:查看GenericServlet 的源码包导Tomcat的源码包,apache-tomcat-7.0.81-src.zip。Outline的窗口带三角的说明是继承过来重写的方法,没有的才是自己本身的。

image.png

servet映射细节

通配符* 代表任意字符串
url-pattern: *.do 以.字符串的请求都可以访问 注:不要加/
url-pattern: /* 任意字符串都可以访问
url-pattern: /action/
以/action开头的请求都可以访问
匹配规则:
优先级:从高到低
绝对匹配--> /开头匹配 --> 扩展名方式匹配

如果url-pattern的值是/,表示执行默认映射。所有资源都是servlet

5. Servlet的线程安全

★ 单实例:每次访问多线程
★ 解决线程安全问题的最佳办法,不要写全局变量,而写局部变量。
★ Servlet的线程安全问题只有在大量的并发访问时才会显现出来,并且很难发现,因此在编写Servlet程序时要特别注意。
★ servlet处于服务器进程中,它通过多线程方式运行其service方法,一个实例可以服务于多个请求,并且其实例一般不会销毁,所以你的项目中如果只有一个servlet,那么web容器就只会创建一个实例。所以其默认非线程安全,如果需要线程安全需要指明。

6.ServletConfig

作用:
★ 可以获取servlet配置信息
★ 可以获得ServletContext对象

6.1Servlet配置信息的获取:

当servlet配置了初始化参数后,web容器在创建servlet实例对象时,会自动将这些初始化参数封装到ServletConfig对象中,并在调用servlet的init方法时,将ServletConfig对象传递给servlet。进而,程序员通过ServletConfig对象就可以得到当前servlet的初始化参数信息。
web.xml。只要有ServletConfig对象就能调用getInitParameter方法。

<servlet>
        <display-name>servletDemo4</display-name>
        <servlet-name>ServletDemo4</servlet-name>
        <servlet-class>com.cms.Demo1.Service.ServletDemo4</servlet-class>
        <!-- 初始化参数 -->
        <init-param>
        <param-name>encoding</param-name>
        <param-value>GBK</param-value>
        </init-param>
    </servlet>

获取配置信息:GBK

package com.cms.Demo1.Service;

import java.io.IOException;

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

/**
* Servlet implementation class ServletDemo4
*/
public class ServletDemo4 extends HttpServlet {
  private ServletConfig config;//config对象专门操作配置文件信息

  @Override
  public void init(ServletConfig config) throws ServletException {
      // TODO Auto-generated method stub
      this.config = config;
  }

  protected void doGet(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      String encoding = config.getInitParameter("encoding");//获得配置文件中的信息
      System.out.println(encoding);
  }

  protected void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {
      doGet(request, response);
  }

}

总结:
这样做的好处是:如果将数据库信息、编码方式等配置信息放在web.xml中,如果以后数据库的用户名、密码改变了,则直接很方便地修改web.xml就行了,避免了直接修改源代码的麻烦。
获取Servlet配置信息的方式(关键得到ServletConfig对象):

方式一:


image.png

方式二:

image.png

方式三:

image.png

7. ServletContext

ServletContext: 代表的是整个应用。一个应用只有一个ServletContext对象。单实例。

ServletContext与ServletConfig的区别:

image.png

作用:

a. 作为 域对象:在一定范围内(当前应用),使多个Servlet共享数据。

★ 域对象:在一个可以被看见的范围内共享数据用到对象
★ 作用范围:整个web应用范围内共享数据
★ 生命周期:当服务器启动web应用加载后创建出ServletContext对象后,域产生。当web应用被移除出容器或服务器关闭,随着web应用的销毁域销毁。
常用方法:
void setAttribute(String name,object value);//向ServletContext对象的map中添加数据
Object getAttribute(String name);//从ServletContext对象的map中取数据
void rmoveAttribute(String name);//根据name去移除数据
把数据添加到ServletContext的map里:

package com.cms.Demo1.Service;

import java.io.IOException;

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

/**
 * Servlet implementation class ServletDemo5
 */
public class ServletDemo5 extends HttpServlet {

    /**
     * @see HttpServoGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //通过GenericServlet类 继承的的getServletContext()方法得到ServletContext对象
    ServletContext application = this.getServletContext();//输完this.getServletContext() 后Ctrl+回车,对象ServletContext通常用application(应用)表示。
//向ServletContext添加一个键值对
    application.setAttribute("name", "value");
    
    }

    /**
     * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

取出:

package com.cms.Demo1.Service;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Servlet implementation class ServletDemo6
 */
public class ServletDemo6 extends HttpServlet {


    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String name = (String) this.getServletContext().getAttribute("name");
        System.out.println(name);
        if(name==null){
            System.out.println("你无权访问");
        }
        System.out.println();
    
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}

b. 获取全局配置信息:

web.xml文件:
String类型--getInitParameter(String name) //根据配置文件中的key得到value

image.png

Java文件:

image.png
c.获取资源路径:

String getRealPath(String path);//根据资源名称得到资源的绝对路径.
可以得到当前应用任何位置的任何资源。

image.png

注意:
getRealPath的路径是参考部署后(publish)的文件路径
'/'代表当前项目部署后的根目录:D:\apache-tomcat-7.0.52\webapps\webService

实现Servlet的转发:
image.png

注意:
RequestDispatcher getRequestDispatcher(String path) ;//参数表示要跳转到哪去

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,612评论 5 471
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,345评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,625评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,022评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,974评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,227评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,688评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,358评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,490评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,402评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,446评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,126评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,721评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,802评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,013评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,504评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,080评论 2 341

推荐阅读更多精彩内容