Servlet笔记

Tomcat 与 Servelet概述

软件结构发展史

  • 桌面应用时代
  • 联机时代(Client-Server 模式)
  • 互联网时代(Browser-Server 模式)
桌面应用时代

桌面应用俗称单机应用,软件以及所有数据都保存在电脑本地硬盘中;优点为易于使用,结构简单;缺点为数据难以共享,安全性差,更新不及时

联机时代

C/S架构,指的是客户端和服务器架构;数据保存在服务器上,不需要保存在本机电脑;优点是数据方便共享并且安全性高;缺点是必须要安装客户端,升级与维护比较困难。C/S结构的典型应用例如:QQ。

互联网时代

B/S架构,即:浏览器和服务器的架构模式。通过浏览器加载服务端上面的内容,以网页的形式显示给用户,B/S架构的优点为:开发简单,无需安装客户端,数据易于共享;缺点为:相较于C/S模式,B/S模式的执行速度与用户体验较弱。B/S的典型应用有很多,浏览器能浏览到的各个网站都是B/S模式应用。

B/S模式执行流程


关于B/S模式执行流程,可以看我的文章 浅谈HTTP

请求与响应

客户端即是访问者,服务器即是被访问的对象。
或者可以简单地理解为,一个是浏览网页的,一个是提供网页服务给浏览者浏览的。
那么客户端从输入URL 到 页面的呈现 到底发生了什么呢?
这个问题在本文不会给出详细的解答。但是我们可以知道客户端和服务器之间一定存在着某种"沟通"。
这种沟通就是请求(Request)和 响应(Response)
在我们输入了URL之后,浏览器给服务器发送了一个request,web服务器接收到request后进行处理,然后返回给浏览器一个response,浏览器通过解析response中的HTML,我们就看到网页了。关于请求与相应的具体部分,依然可以参照我的文章 浅谈HTTP

Servlet

  • Servlet是什么
    Servlet是服务器程序,主要功能是用于生成动态Web内容。它担当Web浏览器或其他HTTP客户程序发出请求,与HTTP服务器上的数据库或者应用程序之间的中间层。

Apache Tomcat

  • Tomcat是什么
    Tomcat 是 Apache软件基金会旗下一款免费的开源的Servlet容器,由Apache基金会,Sun和一些其他公司及个人共同开发完成。Tomcat是一个服务器,如果你要将自己的电脑当作一个服务器使用,就需要开启Tomcat。
  • Tomcat与Servlet的关系
    Tomcat是J2EE Web(Servlet与JSP)标准的实现,Servlet是建立动态网站的程序代码,可以说是在Tomcat上运行的程序,简单说:Tomcat是运行平台,Servlet是运行程序

安装 Apache Tomcat

下载链接
进入官网,下载自己电脑系统匹配的版本即可,要确保安装了匹配的jdk,下载完毕后,进入下载目录的bin目录下,运行startup命令,如果出现

The CATALINA_HOME environment variable is not defined correctly

这样的报错信息,说明没有设置好JAVA_HOME
如果出现

command is not defined

那么就要看你的startup命令是否是在bin目录下运行的,在没有设置好CATALINA_HOME之前,startup命令只能在bin目录下运行。
命令运行成功后,会弹出一个黑色窗口,最后显示:


在浏览器上输入http://localhost:8080/ 会显示Apache Tomcat的页面。

如果需要关闭服务器,只需要敲入CTRL + C 即可退出

IntelliJ IDEA 整合Tomcat

关于怎样使用idea整合Tomcat的教程在网上一大堆
例如:
Kudō Shin-ichi 这位同学的文章 IntelliJ IDEA整合Tomcat服务器
这里就不再赘述。

Servlet创建与生命周期

第一个Servlet程序

在idea整合好Tomcat,创建一个web项目后,开始写第一个Servlet程序:

FirstServlet 类

package servlet;

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

public class FirstServlet extends HttpServlet {

    // idea 快捷键 快速生成 ctrl + O
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        String name = req.getParameter("name");
        String html = "<h1 style='color:red'>hi, " + name + "</h1><hr/>";
        PrintWriter out = resp.getWriter();
        out.println(html);
    }
}

在web.xml里的配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <!--servlet的别名 -->
        <servlet-name>firstServlet</servlet-name>
        <servlet-class>servlet.FirstServlet</servlet-class>
    </servlet>

    <!--servlet的映射-->
    <servlet-mapping>
        <servlet-name>firstServlet</servlet-name>
        <url-pattern>/hi</url-pattern>
    </servlet-mapping>
</web-app>

运行程序,输入URL:http://localhost:8080/first_servlet/hi?name=dobbykim
页面显示如下:


该程序的执行流程如下:
当我们输入url:http://localhost:8080/first_servlet/hi?name=dobbykim的时候,浏览器向Tomcat服务器发起了"请求"。在Servlet程序内部,首先会在配置文件web.xml中去找servlet-mapping,找到了对应的跳转地址,通过servlet-name找到了对应的servlet-class。通过servlet-class,服务器找到了FirstServlet类;在FirstServlet类中,一个请求获取到的参数,也就是本示例中的name=dobbykim会被写好的页面一同由PrintWriter对象响应回浏览器,返还给客户,呈现出页面。

Java Web标准工程结构

组织结构 描述
tocat 安装目录/webapps/ Tomcat应用根目录
/web应用目录/ Java Web应用目录
/web应用目录/index.html or .jsp 默认首页
/WEB-INF WEB应用的安全目录,用于存放配置文件
/WEB-INF/web.xml web.xml是"部署描述符文件",是该web项目核心配置文件
/WEB-INF/classes 存放编译后的classes文件
/WEB-INF/lib 用于存放web应用依赖的jar文件
/META-INF/MANIFEST.MF 包含Web应用的版本等信息

Servlet开发与基本配置

Servlet开发步骤
  • 创建Servlet类,继承HttpServlet
  • 重写service方法,编写程序代码
  • 配置web.xml,绑定URL

示例:使用Servlet计算n以内自然数的累加和,并输出,参数n通过url地址进行传递,示例程序如下:
ComputerServlet类

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

public class ComputerServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String nString = req.getParameter("n");
        int n = Integer.parseInt(nString);
        int sum = ((n + 1) * n) / 2;
        String html = "<p>" + sum + "</p>";
        PrintWriter out = resp.getWriter();
        out.println(html);
    }
}

web.xml中的配置如下:

    <servlet>
        <servlet-name>ComputerServlet</servlet-name>
        <servlet-class>ComputerServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ComputerServlet</servlet-name>
        <url-pattern>/ComputerServlet</url-pattern>
    </servlet-mapping>

通过在URL中传参即可动态改变网页中显示的内容:


请求参数的发送与接收

请求参数
  • 请求参数是指浏览器通过请求向Tomcat提交的数据
  • 请求参数通常是用户输入的数据,待Servlet进行处理
  • 请求参数的格式 :参数名1=值1&参数名2=值2&...参数名n=值n
Servlet接收请求参数
  • request.getParameter() 接收单个参数
  • request.getParameterValues() 接收多个同名参数

示例如下:
在web目录下,student.html:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学员信息登记表</title>
</head>
<body>
    <h1>学员信息登记表</h1>
    <form action="/FirstServlet/sample" method="get" >
        姓名:<input name="name"/>
        <br/>
        电话:<input name="mobile"/>
        <br/>
        性别:
        <select name="sex" style="width:100px;padding:5px;">
            <option value="male" >男</option>
            <option value="female">女</option>
        </select>
        <br/>
        特长:
        <input type="checkbox" name="spec" value="English"/>英语
        <input type="checkbox" name="spec" value="Program"/>编程
        <input type="checkbox" name="spec" value="Speech"/>演讲
        <input type="checkbox" name="spec" value="Swimming"/>游泳
        <br/>
        <input type="submit" value="提交">
        <br/>
    </form>
</body>
</html>

web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
         version="4.0">

    <servlet>
        <servlet-name>sample</servlet-name>
        <servlet-class>SampleServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>sample</servlet-name>
        <url-pattern>/sample</url-pattern>
    </servlet-mapping>
</web-app>

SampleServlet 类:

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

public class SampleServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String mobile = req.getParameter("mobile");
        String sex = req.getParameter("sex");
        String[] specs = req.getParameterValues("spec");

        PrintWriter out = resp.getWriter();
        out.println("<h1>name:" + name + "</h1>");
        out.println("<h1>mobile:" + mobile + "</h1>");
        out.println("<h1>sex:" + sex + "</h1>");
        for (int i = 0; i < specs.length; i++) {
            out.println("<h2>spec:" + specs[i] + "</h2>");
        }
    }
}

表单填写如下:



submit后,跳转页面如下:


Get与Post请求

  • get方式是将数据通过在URL附加数据显性向服务器发送数据
    例如:http://localhost:8080/FirstServlet/sample?name=zhangsan
  • post方式会将数据存放在请求体中隐性向服务器发送数据
    url中不会显示参数:http://localhost:8080/FirstServlet/sample
    请求体的内容:name=zhangsan
Get与Post处理方式
  • 所有请求 service()方法
  • Get请求 doGet()方法
  • Post请求 doPost()方法
Get与Post应用场景
  • Get常用于不包含敏感信息的查询功能
  • Post用于安全性要求比较高的功能或者服务器的"写"操作
    例如:用户登录,用户注册,更新公司账目等等

Get与Post示例程序:
RequestMethodServlet类:

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

public class RequestMethodServlet extends HttpServlet {

    // 处理 get 请求
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        resp.getWriter().println("<h1 style='color:green'>" + name + "</h1>");
    }

    // 处理 post 请求

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        resp.getWriter().println("<h1 style='color:red'>" + name + "</h1>");
    }
}

使用get方式提交表单时:



使用post方式提交表单:



并且可以看到提交的请求体中有用户的信息:

Servlet的生命周期

  • 装载 : 解析web.xml
  • 创建:构造函数
  • 初始化:init()
  • 提供服务 service()
  • 销毁 destroy()

示例程序如下:

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

public class FirstServlet extends HttpServlet {

    public FirstServlet() {
        System.out.println("正在创建FirstServlet对象");
    }

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("正在初始化FirstServlet对象");
    }



    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String name = req.getParameter("name");
        String html = "<h1 style='color:red'>" + name + "</h1>";
        PrintWriter out = resp.getWriter();
        System.out.println("service提供服务");
        out.println(html);
    }

    @Override
    public void destroy() {
        System.out.println("正在销毁FirstServlet对象");
    }
}

输入URL:



可以看到输出发生了变化:



改变URL中的Parameter:

控制台输出为:



可以看到,并没有重新创建Servlet对象,而是一直由一个Servlet对象提供service服务;当我们重启Servlet时候,Servlet销毁:

使用注解配置Servlet

注解简化配置

  • Servlet 3.x之后引入了注解
  • 注解用于简化Web应用程序的配置过程
  • Servlet核心注解: @WebServlet

示例程序如下:

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

@WebServlet("/annotation")
public class AnnotationServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().println("I'am AnnotationServlet");
    }
}

在Servlet类前面添加@WebServlet注解,括号里面是映射地址,这样就可以通过注解简化在web.xml里面的配置

启动时加载Servlet

  • web.xml使用<load-on-startup>设置启动加载
  • 推荐的使用范围<load-on-startup>0~9999</load-on-startup>;0的优先级最高
  • 启动时加载在工作中常用于系统的预处理

对于启动时加载Servlet同样可以使用两种方式

  • web.xml中配置
  • 使用注解

示例程序:
Process1:

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;

public class Process1 extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("执行process1");
    }
}

Process1在web.xml中配置:

    <servlet>
        <servlet-name>process1</servlet-name>
        <servlet-class>Process1</servlet-class>
        <load-on-startup>0</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>process1</servlet-name>
        <url-pattern>/process1</url-pattern>
    </servlet-mapping>

Process2:

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;

@WebServlet(urlPatterns = "/process2",loadOnStartup = 1)
public class Process2 extends HttpServlet {
    @Override
    public void init() throws ServletException {
        System.out.println("执行process2");
    }
}

在控制台输出结果如下:



通过在web.xml中设置load-on-startup或者通过注解进行配置可以在启动时加载在工作中常用于系统的预处理,例如示例程序中,process1和process2是预处理需要执行的程序,我们可以在启动Tomcat时,加载Servlet类。

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

推荐阅读更多精彩内容