Java后台开发——Servlet篇

参考资料

《JSP从零开始》—— 刘鑫
Servlet官方文档
孤傲苍狼 博客园

前言

本人菜鸟,入IT只为当鼓励师。本编文章对 Servlet 作简要介绍,其中包括讲解:Servlet是什么、Servlet的功能、Servlet的生命周期、HttpServlet对象。

一、Servlet是什么

  • 一门用于开发动态web资源的技术,由sun公司提供。
  • java类编写的服务端应用程序
  • Servlet程序是由web服务器(tomcat等)调用的

说简单点,就是Sun公司开发出了一套API(java.servletjava.sevlet.http等),你可以用这些api开发Java程序,用来处理客户端请求,并控制输出的响应(向客户端浏览器输出的内容)。

servlet api

总结起来,你只需要:
① 编写一个实现了servlet接口的java类;
② 把开发好的Java类部署到web服务器中。

所以,有时我们也称实现了servlet接口的java程序为Servlet。

二、Servlet的功能

  • 对客户端发送的数据进行读取和拦截
    客户端发送一个请求会携带数据(url中的参数,页面表单提交,ajax请求),当一个Servlet接收到请求,java Servlet中的类可以通过提供的方法获得这些参数(request.getParameterName(name)等)。因此Servlet可以起拦截作用,在请求前先判断该客户端能否做出这些请求 ,若能再从服务器得到请求的资源。
    图例
  • 读取客户端的请求的隐含数据
    客户端请求的数据可分为:隐含数据,显式数据。
    隐含数据:不存在于URL中,而存在于请求的来源,缓存数据(cookie)、客户端类型(在header中)。
    显式数据:用户可见的,表单数据(来自于form)或URL参数。
    Servlet都可处理。

  • 运行结果或者生成结果
    一个Web应用程序对客户端发出的请求做出响应时,一般有很多中间过程才能得到结果,Servlet就担起了这个中间角色功能。(后面深入学习会知道,javaweb开发中的控制层是由Servlet实现的,就是常说的MVC中的C)


    图例
  • 发送响应的数据
    Servlet对客户端做出响应并经过处理得出结果后,会对客户端发送响应的数据,让客户端获取请求的结果数据。

三、Servlet的生命周期

Servlet的生命周期包含3个阶段:

1. 初始化阶段

当web服务器收到客户端对某一url地址的访问请求时,若该url配置了对应的Servlet程序,则开始该阶段。


检查请求url是否有对应的Servlet程序
  • web服务器检查是否已经装载并创建了该Servlet的实例对象。如果是,则跳过初始化阶段,否则进入下一步。
  • 装载(由Servlet容器装载一个Servlet类,把它装在到Java内存中)并创建该Servlet的一个实例对象,与 web.xml 中的配置对应起来。
  • 调用Servlet实例对象的 init() 方法。在整个Servlet生命周期中,init() 方法只被调用一次。
    步骤图示

    首次访问的两个注意点

2. 运行阶段

该阶段实际响应客户端的请求。

  • Servlet创建 HttpServletRequestHttpServletResponse 对象,前者与HTTP协议有关,后者与协议无关。
  • 调用 service(HttpServletRequest request, HttpServletResponse response) 方法,该方法通过request对象获得请求对象的信息并加以处理,再由response对象给客户端做出响应。
每当有请求时,服务端的一系列动作
调用 service() 方法,可访问请求和响应对象
运用request对象读取请求信息,处理后运用response对象写入响应信息
service() 方法返回
服务器读取响应信息
服务器发出http响应,将数据返回到客户端浏览器中

3. 消亡阶段

  • web应用程序被停止或重新启动之前,Servlet容器将调用 destroy() 方法,对Servlet对象进行销毁,释放其所占资源。在整个Servlet生命周期中,destory() 方法只被调用一次。

四、创建Servlet的步骤

  1. 引入相应的包,如:java.servletjava.servlet.http 包,两个包的区别是前者与协议无关,后者与HTTP协议相关。
  2. 创建一个扩展类,如本例中的 HelloServlet,并继承 HttpServlet 类。(一般的,HttpServlet 类封装了很多基于HTTP协议下的Servlet功能,基本够用,若自己想开发一个协议可继承 GenericServlet 类)
  3. override doGet()doPost() 方法,doGet() 响应get请求,doPost() 响应Post请求。或者可以override service()方法,对所有请求统一处理。欲详细了解 service()doGet()doPost()等方法,请看:五、关于 Servlet、HttpServlet、GenericServlet
代码示例:
package com.javaweb.servlet;

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

import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/* 用注入声明的方式表示这是一个 Servlet 类,不用在web.xml中配置 Servlet */
@WebServlet (
    urlPatterns = { "/HelloServlet" },
    name = " helloServlet "
)

// 继承HttpServlet类
public class HelloServlet extends HttpServlet {

    // 序列化,可以自动生成或者自行定义
    private static final long serialVersionUID = 1L;

    // 一、初始化阶段的 init() 方法
    public void init() throws ServletException {
    System.out.println("初始化 init 方法");
    }

    // 过程二执行的方法有一定的顺序与条件,详细请看: 五、关于 Servlet、HttpServlet、GenericServlet
    // 二、调用 public service 方法
    public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        System.out.println("调用 public service 方法");

        // 设定页面的MINE类型和字符集
        response.setContentType("text/html;charset=utf-8");
    
        // 输出响应
        PrintWriter out = response.getWriter();
        out.println("收到 service 请求");
    }

    // 二、调用 protected service 方法
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException {
        System.out.println("调用 protected service 方法");
    }

    // 二、调用 doGet() 方法
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doPost(request, response);
    }

    // 二、调用 doPost() 方法
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("调用 doPost() 方法"); 
    
        // 设定页面的MINE类型和字符集
        response.setContentType("text/html;charset=utf-8");
    
        // 输出响应
        PrintWriter out = response.getWriter();
        out.println("收到 HelloServlet doPost() 请求");
    }

    // 三、消亡阶段的 destory() 方法
    public void destory() {
        System.out.println("调用 destory() 方法");
    }
 } 

五、关于 Servlet、HttpServlet、GenericServlet

Servlet 来自于 javax.servlet.Servlet
HttpServlet 来自于 javax.servlet.http.HttpServlet
GenericServlet 来自于 javax.servlet.GenericServlet

1. Servlet

servlet 是一个接口,如果实现这个接口,那么就必须实现接口里面定义的所有方法。一般开发不会去自己实现该接口,它只提供了一种规范,供 开发者 自己来编写相关的实现


api中对 Servlet 接口的说明
  • 可以看出,Servlet接口提供了5个必须实现的方法


    Servlet 接口中的方法

2. GenericServlet

  • GenericServlet 定义了一个通用的,无关协议的Servlet。如果要在Web应用中使用Http进行Servlet通信,请扩展 HttpServlet(即继承 HttpServlet
  • 在《JSP从零开始》的第100—101页有GenericServlet类的部分源代码,读者有兴趣可研究一下


    api中对 GenericServlet 抽象类的说明
  • 下面是 GenericServlet中的方法
    GenericServlet 类中的方法

3. HttpServlet

HttpServlet 是一个抽象类,它继承了 GenericServlet 抽象类,而 GenericServlet 类实现了 Servlet 接口,所以HttpServlet 类也就默认实现了 Servlet 接口。默认实现规范而实用,开发web端的servlet程序,一般我们只需继承 HttpServlet 类就可以了

api中对 HttpServlet 抽象类的说明

  • 创建 HttpServlet 的步骤:
    ①继承 HttpServlet 抽象类;
    ②覆盖 HttpServlet 的部分方法,如覆盖 doGet()doPost() 方法;
    ③获取HTTP请求信息。通过 HttpServletRequest 对象来检索HTML表单所提交的数据或URL上的查询字符串;
    ④生成HTTP响应结果。通过 HttpServletResponse 对象生成响应结果,它有个 getWriter() 方法,该方法返回一个 PrintWriter 对象。

  • 它总共有10个方法,其中实现了:


    HttpServlet 中的方法

① 2个重载的 service() 方法

  • 在servlet中默认情况下,无论是get还是post 提交过来 都会经过service()方法来处理,然后转向到doGet()doPost()方法,所以默认情况(没有重写service方法)下,service()是用来转向的。
  • 如果你在自己的servlet类中覆盖了service()方法,那么service()就不是用来转向了,而是用来处理业务,这时不论客户端是用post还是get来请求此servlet,都会执行service()方法也只能执行servlet()方法,不会去执行doPost()doGet()方法。
    各个方法的执行顺序和条件

② doGet(),doPost(),doOptions(),doTrace(),doDelete(),doHead(), doPut() 这7个方法

  • 最常用的还是doGet()doPost(),但一般来说我们是用不到doGet()方法的。doGet()方法提交表单时会在url后边显示提交内容,并不安全。而且doGet()方法只能提交256个字符(1024字节),而doPost()没有限制,因为get方式数据的传输载体是URL(提交方式能form,也可以是任意的URL链接),而POST是HTTP头键值对(只能以form方式提交)。通常我们使用的都是doPost()方法,你只要在servlet中让这两个方法互相调用就行了。

③ getLastModified(HttpServletRequest req) 方法

  • 传入参数为一个HttpServletRequest对象
  • 返回一个数值,该值为从 1970年1月1日HttpServletRequest对象最近一次修改的那个时刻 走过的毫秒数。

最后,分享我用PowerDesigner创建的面向对象模型的关系图来说明三者的关联:


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

推荐阅读更多精彩内容