Java Web(八)--Servlet(一)

介绍

官网:Servlet 3.1 API Documentation - Apache Tomcat 8.0.53

学习文档:Overview (Servlet 3.1 API Documentation - Apache Tomcat 8.5.99)

为什么需要?

提出需求: 请用你现有的html css javascript,开发网站,比如可以让用户留言/购物/支付?

引入我们动态网页(能和用户交互)技术===>Servlet

是什么?

Servlet是Server Applet的简称,是用Java编写的服务器端程序,是JavaEE平台下的技术标准。其主要功能在于和浏览器交互并生成动态Web内容。狭义的Servlet是指Java语言实现的一个接口,广义的Servlet是指任何实现了这个Servlet接口的类,一般情况下,人们将Servlet理解为后者。

   Servlet通常通过 HTTP(超文本传输协议)接收和响应来自 Web 客户端的请求。从原理上来讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器

Servlet是Tomcat的一个组件,Servlet的功能需要依赖一个servlet-api.jar,这个包是由Tomcat提供的,Tomcat在初始化Servlet时,首先读取web.xml文件,根据web.xml文件中的参数信息初始化ServletConfig、ServletContext对象,同时帮助我们创建HttpServletRequest和HttpServletResponse对象一并交给Servlet实例,此时,Servlet就具有了相关的功能。

Servlet技术的核心是Servlet,它是所有Servlet类必须直接或者间接实现的一个接口。在编写实现Servlet接口的类时,直接实现它,在扩展实现Servlet这个接口的类时,间接实现它。Servlet有三种实现方式:实现Servlet接口、继承抽象类GenericServlet、继承HttpServlet。

在一个应用程序中,每种Servlet类型只能有一个实例(单例模式)【在Servlet中要尽量避免使用全局变量】。

【Tomcat部分详见Java Web(七)__Tomcat(二)-CSDN博客Java Web(七)__Tomcat(一)-CSDN博客 】

 比如访问http://localhost:8080/app/servlet.

  • 1.地址栏打出该地址,浏览器首先帮助你构建一个请求报文
  • 2.传输到目标机器,到达指定端口8080的connector,然后connector接收到该请求,将请求报文转成request对象
  • 3.connector将request对象,同时还会生成一个空的response对象,然后将这两个对象传给engine
  • 4.engine接着选择host,将这两个对象传给host
  • 5.host选择Context(/app),将这两个对象传给Context
  • 6.Context在当前应用下去寻找/servlet,如果找到,则往response对象里面写入对应的数据
  • 7.这两个对象依次返回,给connector
  • connector读取response对象里面的数据,然后生成一个响应报文,发送出去。

注:

 Servlet 类没有 main() 函数,不能独立运行,只能作为一个模块被载入到 Servlet 容器,然后由 Servlet 容器来实例化,并调用其中的方法;

一个动态页面对应一个 Servlet 类,开发一个动态页面就是编写一个 Servlet 类;【当用户请求到达时,Servlet 容器会根据配置文件(web.xml)来决定调用哪个类】 

浏览器访问 Servlet 流程分析 

注:

servlet3.0 前使用 web.xml 
servlet3.0 版本以后(包括 3.0)支持注解, 同时支持 web.xml。


Servlet的继承结构

Servlet接口,只负责定义Servlet程序的访问规范;

GenericServlet抽象类实现了Servlet接口,做了很多空实现,并持有一个ServletConfig类的引用,并提供了一些ServletConfig的使用方法;

HttpServlet抽象类实现了service方法,并实现了请求分发处理; 


Servlet的开发

所有的 Servlet 功能都是通过一个名为Servlet的接口(Interface)向外暴露的,编写 Servlet 代码,可以从实现 Servlet 接口开始。

返回值方法备注
voidinit(ServletConfig config)Servlet 实例化之后,由 Servlet 容器调用,用来初始化 Servlet 对象。该方法只能被调用一次。

参数 config 用来向 Servlet 传递配置信息【即Servlet的初始化参数】。

voidservice(ServletRequest req,ServletResponse res)

Servlet 容器调用该方法处理客户端请求。

【每次请求都会调用该方法】

voiddestroy()服务器关闭、重启或者 Servlet 对象被移除时,由 Servlet 容器调用,负责释放 Servlet 对象占用的资源。
ServletConfiggetServletConfig()该方法用来获取 ServletConfig 对象,该对象中包含了 Servlet 的初始化参数。
StringgetServletInfo()该方法用于获取 Servlet 的信息,例如作者、版本、版权等。

注:

init( )、service( )、destroy( )是Servlet生命周期的方法。init()、destroy( )各自只执行一次,即Servlet创建和销毁时。而Service会在每次有新请求到来时被调用。也就是说我们的业务代码需要写在service()方法中。

Tomcat反射创建Servlet后,会调用init()时传入ServletConfig对象,并创建ServletRequest和ServletResponse对象传递给service()方法。


实现Servlet接口

需要重写其全部的方法,比较繁琐。

需求:
1、开发一个 HelloServlet
2、当浏览器 访问 http://localhost:8080/web 应用名/helloServlet 时,后台输出 "hiHelloServelt"

实现:

1、编写类HelloServlet,实现  Servlet 接口

  •     1.创建javaweb工程,并配置好Tomcat
  •     2.添加servlet.jar(在Tomcat/lib)到工程web/WEB-INF/lib中
  •     3.在src 下 包 com.hspedu.servlet.HelloServlet.java ,并实现Servlet接口

2、实现  service 方法,处理请求,并响应数据

package com.lhyedu.servlet;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * 1. 开发一个Servlet 需要 实现Servlet接口
 * 2. 实现Servlet接口的方法5个
 */
public class HelloServlet02 implements Servlet {

    /**
     * 1.初始化 servlet
     * 2.当创建HelloServlet 实例时,会调用init方法
     * 3. 该方法只会被调用一次
     */
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    }

    /**
     * 返回ServletConfig 也就是返回Servlet的配置
     */
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }

    /**
     * 1. service方法处理浏览器的请求(包括get/post)
     * 2. 当浏览器每次请求Servlet时,就会调用一次service
     * 3. 当tomcat调用该方法时,会把http请求的数据封装成实现ServletRequest接口的request对象
     * 4. 通过servletRequest 对象,可以得到用户提交的数据
     * 5. servletResponse 对象可以用于返回数据给tomcat->浏览器
     */
    @Override
    public void service(ServletRequest servletRequest,
                        ServletResponse servletResponse) throws ServletException, IOException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        String method = httpServletRequest.getMethod();
        if("GET".equals(method)) {
            doGet(); //用doGet() 处理GET请求
        } else if("POST".equals(method)) {
            doPost(); //用doPost() 处理POST请求
        }
    }

    /**
     * 用于响应get请求的
     */
    public void doGet() {
        System.out.println("doGet() 被调用..");
    }

    /**
     * 用于响应post请求的
     */
    public void doPost() {
        System.out.println("doPost() 被调用..");
    }

    /**
     * 返回servlet信息,使用较少
     */
    @Override
    public String getServletInfo() {
        return null;
    }

    /**
     * 1. 该方法是在servlet销毁时,被调用
     * 2. 只会调用一次
     */
    @Override
    public void destroy() {
        System.out.println("destroy() 被调用...");
    }
}

3、在  web.xml  中去配置  servlet 程序的访问地址,即:给hello.servlet提供对外访问的地址。  

<?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">

    <!--web.xml主要用来配置该web应用使用到的Servlet-->
    <!-- 配置HelloServlet -->
    <!--servlet标签: 给tomcat配置Servlet程序-->

    <servlet>
        <!--servlet-name标签: 给Servlet程序取一个别名(程序员决定), 该名字唯一;一般跟写的Servlet类名相同-->
        <!--servlet-class标签:Servlet的全限定类名,即Servlet类的位置: Tomcat在反射生成该Servlet需要使用。-->
        <servlet-name>HelloServlet</servlet-name>
        <servlet-class>HelloServlet</servlet-class>

        <!--load-on-startup 表示在tomcat 启动时,会自动的加载servlet实例-->
        <!--<load-on-startup>1</load-on-startup>-->
    </servlet>

    <!--servlet-mapping标签: 给Servlet程序配置方位地址-->

    <servlet-mapping>
        <!--servlet-name标签:告诉服务器,当前配置的地址给哪个Servlet使用-->
        <!--url-pattern标签:对外提供访问Servlet的url地址:http://ip[域名]:port/工程路径/helloServlet
            取名是程序员决定的,相当于项目名。【/符号一定要加上】-->

        <servlet-name>HelloServlet</servlet-name>
        <url-pattern>/helloServlet</url-pattern>

    </servlet-mapping>

执行步骤:

【1】首先浏览器通过http://localhost:8080/servletDemo/helloServlet来找到web.xml中的url-pattern;

【2】匹配到url-pattern后,就会找到servlet的名字helloServlet;

【3】通过servlet-name找到servlet-class【即servlet的位置】,然后到其中找到对应的处理方式进行处理。

 <load-on-startup>标签:

  • <load-on-startup>节点必须写在<servlet>节点的内部,且作为最后一个节点,取值必须是整数;
  • 如果是大于等于0的整数:表示在服务器启动时就被创建并初始化。【避免第一次访问时被创建并初始化的,减少第一次访问的耗时】
  • 如果有多个Servlet设置了<load-on-startup>节点的值,那么值越小越优先执行;
  • 如果是负数则表示第一次被访问时创建并初始化,也就是默认情况,可以省略不写。

 4、通过浏览器访问HelloServlet ,进行验证;

  • 浏览器输入:http://localhost:8080/web/HelloServlet
  • 服务后台输出:  hi,helloservlet......  

实现GenericServlet

一个通用的 Servlet 类,并没有针对某种场景进行特殊处理,尤其是 HTTP 协议,我们必须手动分析和封装 HTTP 协议的请求信息和响应信息;

实现了 Servlet 接口,并提供了除 service() 方法以外的其他四个方法的简单实现

通过继承 GenericServlet 类创建 Servlet ,只需要重写 service() 方法即可,大大减少了创建 Servlet 的工作量。

GenericServlet做了如下工作:
• 提升init方法中原本是形参的servletConfig对象的作用域(成员变量 , 方便其他方法使用)
• init方法中还调用了一个init空参方法, 如果我们希望在servlet创建时做一些什么初始化操作,可以继承GenericServlet后,覆盖init空参方法
• 由于其他方法内也可以使用servletConfig, 于是写了一个getServletContext方法
• 但没有实现service()方法。


实现HttpServlet类__推荐方式

用于开发基于 HTTP 协议的 Servlet 程序,在 GenericServlet 的基础上专门针对 HTPP 协议进行了处理。

它继承了GenericServlet类且为抽象类。

通过源码发现,HttpServlet已经实现了service方法,但不希望被实例化,需要子类重写doGet、doPost方法。

创建示意图:

package com.hspedu.servlet;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;

public class OKServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//可以写自己的业务处理代码
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//可以写自己的业务处理代码
    }
}

说明:

【1】重写方法分析 

Pretected修饰,希望子类重写

若不重写get和post方法,浏览器页面会显示:405 (http.method get not supported)。HttpServlet虽然在service中帮我们写了请求方式的判断。但是针对每一种请求,业务逻辑代码是不同的,HttpServlet无法知晓子类想干嘛,所以就抽出七个方法,并且提供了默认实现

Servlet采用模板方法模式【即父类把能写的逻辑都写完,把不确定的业务代码抽成一个方法,调用它。就等子类重写该方法,实现整个业务代码】。

 【2】热加载选项说明

on update action

  •     表示当我们更新操作时, Tomcat 会自动更新类和资源 
  •    当jsp/html 文件修改时,可以生效;但是如果你修改的 java 文件,需要 Redepoly 才会生效。

on frame deactivation

  •     表示 IDEA 失去焦点(比如最小化),也会导致  jsp/html 发生更新
  •    但是 java 修改了,还是需要 redeploy

【3】端口修改

只会影响到当前的项目,而不是去修改 server.xml。


DOS部署

在默认情况下,Tomcat 会自动加载 webapps 目录下的 JavaWeb 应用,并把它发布到名为 localhost 的虚拟主机中。

部署 JavaWeb 应用最快捷的方式:直接将 JavaWeb 应用的所有文件复制到 Tomcat 的 /webapps 目录下

运行方式:

  1.     开放式目录结构(只编译不打包);在开发阶段采用,方便调试
  2.     打包文件(WAR 文件):产品发布阶段时,应该将整个应用打包成 WAR 文件,再进行部署。Tomcat 启动时也会将 WAR 文件自动展开为开放式的目录结构。

 开放式目录结构__部署步骤

1. 进入 Windows DOS 命令行窗口

  •     使用快捷键 “Windows + R”,打开运行对话框
  •     在对话框输入cmd,点击“确定”,进入 Windows 系统命令行窗口

2. 引入 javax.servlet 包

先在命令行中输入set classpath=,然后将 servlet-api.jar 文件拖进命令行内,回车执行 。

  •     命令:set classpath = path
    •         path 表示引入 jar 包的路径
    •         set classpath命令用来为当前窗口设置临时环境变量,只在当前窗口下有效。

3. 编译 Servlet

  •     1)在命令提示符中使用 cd命令进入 MyServlet.java 所在的目录
  •     2)使用 javac -encoding UTF-8 -d . MyServlet.java 命令进行编译
  •     3)进入 MyServlet.java 文件所在的目录,可发现新增了编译后的目录和 .classes 字节码文件,即完成对 Servlet 的编译工作

4. 创建目录结构

    依照 JavaWeb 应用的固定目录结构,在 Tomcat 中为该 Servlet 创建目录。

  •     目录
    •         在 Tomcat 的 webapps 目录中创建 servletDemo(web 应用的名字,由自己定义)文件夹;
    •         在 servletDemo 文件夹内创建 WEB-INF 文件夹;
    •         在 WEB-INF 内创建 classes 文件夹;
    •         在 WEB-INF 内创建配置文件 web.xml(可以复制 \webapps\ROOT\WEB-INF 中的 web.xml 使用)

5. 将 Servlet 移动到 Tomcat 目录中

  •     编译好的字节码和目录移动到 Tomcat\webapps\servletDemo\WEB-INF\classes 目录下

6. 配置 web.xml

  •     对 webapps\servletDemo\WEB-INF 目录的 web.xml 中进行配置

7、访问

  •     进入 Tomcat\bin 目录下双击 startup.bat,启动 Tomcat。
  •     浏览器的地址栏中输入“http://localhost:8080/servletDemo/MyServlet”,访问 MyServlet

Servlet的生命周期

 Servlet 的生命周期由 Servlet 容器管理;在 javax.servlet.Servlet 接口中定义3 个方法:init()、service()、destory(),它们分别在 Servlet 生命周期的不同阶段被 Servlet 容器调用。

【1】初始化阶段

Servlet 容器(比如: Tomcat)加载 Servlet,加载完成后,Servlet 容器会创建一个 Servlet 实例并调用init()方法,init()方法只会调用一次。

    (1)加载和实例化Servlet

        加载成功后,容器会通过反射对 Servlet 进行实例化【编写 Servlet 类时,需要一个无参构造方法】;

        Servlet 容器装载 Servlet的情形:

  •             当容器启动或首次请求某个 Servlet 时,容器会读取 web.xml 或 @WebServlet 中的配置信息,对指定的 Servlet 进行加载;
  •             Servlet 重新装载时,浏览器再向 Servlet 发送请求的第 1 次;比如 tomcat 进行 redeploy;【redeploy 会销毁所有的Servlet 实例】。
通过在 web.xml 文件中添加<load-on-startup>1</load-on-startup>
 1 表示装载的顺序,默认值为0;

load-on-startup 是 web.xml 中的一个节点,是 servlet 元素的子元素,用来标记 Servlet 容器启动时是否初始化当前 Servlet,以及当前 Servlet 的初始化顺序

    (2)调用init()方法初始化Servlet实例

        在 Servlet 的整个生命周期内,init() 方法只能被调用一次。

        初始化期间,Servlet 实例可以通过 ServletConfig 对象获取在 web.xml 或者 @WebServlet 中配置的初始化参数。

【2】处理浏览器请求阶段(service 方法)

当初始化完成后,Servlet 容器会将该实例保存在内存中,通过调用它的 service() 方法,为接收到的请求服务。    

每收到一个 http 请求,服务器就会产生一个新的线程去处理;对于 Servlet 的每一次请求,Servlet 容器都会调用一次 service() 方法,并创建新的 ServletRequest 和 ServletResponse 对象;即 service() 方法在 Servlet 的整个生命周期中会被调用多次。

    Servlet 容器接收到来自客户端请求时,容器会针对该请求分别创建一个 ServletRequst 对象和 ServletResponse 对象,将它们以参数的形式传入 service() 方法内,并调用该方法对请求进行处理;

  •          ServletRequst 对象获取客户端的相关信息和请求信息;
  •         ServletResponse 对象将响应信息进行包装,返回给客户端;
  •         当 Servlet 容器将响应信息返回给客户端后,ServletRequst 对象与 ServletResponse 对象就会被销毁。
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
        //count值,在不断的累计,说明HelloServlet是单例的
         count++;
       //tomcat每处理一次http请求,就生成一个新的线程
        System.out.println("hi,helloservlet......" + count + Thread.currentThread().getId());
    }

   注:执行 service() 方法前,init() 方法必须已成功执行;

【3】终止阶段 destory 方法(体现 Servlet 完整的生命周期)

    当web 应用被终止,或者Servlet 容器终止运行,或者Servlet 类重新装载时,会调用destroy()方法,释放该实例使用的资源;

比如重启tomcat ,或者  redeploy web 应用;例如:关闭数据库连接,关闭文件的输入流和输出流等,随后该实例被 Java 的垃圾收集器所回收。

    对于每个 Servlet 实例来说,destory() 方法只能被调用一次;

    注:要看到 destory 效果,需要保证 servlet 实例被创建过或者 Servlet 重新装载时(比如 redeploy)。


其他

部署动态网站

一般至少需要三个组件,分别是 Web 服务器、脚本语言运行时和数据库。例如,部署 PHP 网站一般选择「Apache + PHP 运行时 + MySQL」的组合。

【1】web服务器 

一种对外提供 Web 服务的软件,可以接收浏览器的 HTTP 请求,并将处理结果返回给浏览器。

  •             运行 PHP 网站一般选择 Apache 或者 Nginx;
  •             运行 ASP/ASP.NET 网站一般选择 IIS;
  •             运行 Python 网站一般选择内置的 WSGI 服务器模块——wsgiref

    通常所说的 Web 服务器,功能往往都比较单一,一般只能提供 http(s) 服务,让用户访问静态资源(HTML 文档、图片、CSS 文件、JavaScript 文件等)。它们不能执行任何编程语言,也不能访问数据库,更不能让用户注册和登录。

   若只有 Web 服务器,那您只能部署静态网站,不能部署动态网站。

【2】运行环境(运行时)

    习惯将以上各种支持脚本语言运行的部件统称为运行环境,或者运行时(Runtime)。开发网站使用的编程语言一般都是脚本语言(比如 PHP、ASP、Python)。

    部署网站时都是将源代码直接扔到服务器上,然而源代码自己并不能运行,必须要有解释器的支持。当用户访问动态页面时,解释器负责分析、编译和执行源代码,然后得到处理结果。

    解释器:执行脚本语言的核心部件。包含如下辅助性的部件:

  •             垃圾回收器:负责及时释放不需要的内存,腾出资源供其它页面使用
  •             标准库:任何编程语言都会附带标准库;它们提供了很多通用性的功能,极大地提高了开发效率,避免重复造轮子

【3】数据库

    Web 服务器不带数据库,编程语言也不带数据库。数据库是一款独立的软件,若要实现用户注册、发布文章、提交评论等功能,就必须安装一款数据库。

  •         比如 MySQL、Oracle、SQL Server 等。

虚拟路径映射

客户端通过 URL 地址来访问 Web 服务器中的资源,Servlet 程序若想被外界访问,就必须被映射到一个 URL 地址上。

通常客户端访问的URL 地址和 Servlet 程序的物理路径(在硬盘上的存储位置)并不一致,因此它被称为虚拟路径。

Servlet 与虚拟路径的对应关系就叫做 Servlet 虚拟路径映射,分为单一映射和多重映射。


规则

当 Servlet 容器接收到请求后,容器会将请求的 URL 减去当前应用的上下文路径,使用剩余的字符串作为映射 URL 与 Servelt 虚拟路径进行匹配,匹配成功后将请求交给相应的 Servlet 进行处理。

以 servletDemo 为例,若 URL 为“http://localhost:8080/servletDemo/myServlet”,其应用上下文是 servletDemo,容器会将“http://localhost:8080/servletDemo”去掉,使用剩余的“/myServlet”与 Servlet 虚拟路径进行匹配。

匹配规则使用规则虚拟路径可访问的URL
完全路径匹配
(精确匹配)
/开始,不能包含通配符
必须完全匹配
/myServlet
/user/myServlet
/product/index.action
http://localhost:8080/servletDemo/myServlet
http://localhost:8080/servletDemo/user/myServlet
http://localhost:8080/servletDemo/product/index.action
目录匹配/字符开头,并以/*结尾的字符串。
用于路径匹配
/user/*
/*
http://localhost:8080/servletDemo/user/aaa
http://localhost:8080/servletDemo/aa
扩展名匹配以通配符*.开头的字符串。
用于扩展名匹配
*.do
*.action
*.jsp
http://localhost:8080/servletDemo/user.do
http://localhost:8080/servletDemo/myServlet.action
http://localhost:8080/servletDemo/bb.jsp
缺省匹配(默认匹配)映射路径为/,表示这个 Servlet 为当前应用的缺省 Servlet 或默认 Servlet,默认处理无法匹配到虚拟路径的请求。/可以匹配任意请求 URL

缺省 Servlet:

在 Tomcat 安装目录的 \conf\web.xml 文件中,注册了一个名称为 org.apache.catalina.servlets.DefaultServlet 的 Servlet;

Tomcat 服务器中的 Web 应用没有缺省 Servlet 时,会将 DefaultServlet 作为其缺省 Servlet。当客户端访问 Tomcat 服务器中某个静态 HTML 文件或者图片时,DefaultServlet 会判断该 HTML 或图片是否存在,若存在,则将数据以流的形式返回客户端,否则会报告 404 错误。


实现方式

【1】使用web.xml

使用 <servlet> 和 <servlet-mapping> 元素实现,通过在一个 <servlet-mapping> 元素中配置多个 <url-pattern> 子元素,也可以实现 Servlet 的多重映射。

<?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">
    <!--web.xml 主要用于配置该web应用使用到的Servlet-->
    <!-- servlet标签 给tomcat配置Servlet程序-->

    <!--1. servlet-name: 给Servlet取名(程序员决定), 该名字唯一
            2. servlet-class: Servlet的类的全路径: Tomcat在反射生成该Servlet需要使用
            3. url-pattern: 这个就是该servlet访问的 url的配置 (路径)
            4. 这时我们应该这样访问servlet http://localhost:8080/servlet/helloServlet
            5. url-pattern 取名是程序员决定的
            6. load-on-startup 表示在tomcat 启动时,会自动的加载servlet实例-->

    <servlet>        <servlet-name>MyServlet</servlet-name>        <servlet-class>net.biancheng.www.MyServlet</servlet-class>
    </servlet>

    <servlet-mapping>        <servlet-name>MyServlet</servlet-name>
        <url-pattern>/myServlet</url-pattern>
    </servlet-mapping>

</web-app>



对以上标签说明如下:
<servlet> 元素用于注册 Servlet,即给 Servlet 起一个独一无二的名字。
<servlet> 包含两个主要的子元素 <servlet-name> 和 <servlet-class>,分别用于指定 Servlet 的名称和 Servlet 的完整限定名(包名+类名,Tomcat在反射生成该servlet需要使用)。
<servlet-mapping> 元素用于定义 Servlet 与虚拟路径之间的映射。
<servlet-mapping> 包含两个子元素 <servlet-name> 和 <url-pattern>,分别用于指定 Servlet 的名称和虚拟路径。
【2】使用@webServlet注解

在 Servlet 中,web.xml 可以将所有的 Servlet 的配置集中进行管理, 若项目中 Servelt 数量较多时,web.xml 的配置会变得十分的冗长;

采用注解解决该问题,注解不需要依赖于配置文件,它可以直接在类中使用,其配置只对当前类有效。

常用注解:@WebServlet、@WebInitParm 、@WebFilter 和 @WebLitener 等;

参数说明:

用于将一个类声明为 Servlet,该注解会在部署时被容器处理,容器根据其具体的属性配置将相应的类部署为 Servlet。

属性名类型标签描述是否必需
nameString<servlet-name>指定 Servlet 的 name 属性。
如果没有显式指定,则取值为该 Servlet 的完全限定名,即包名+类名。
valueString[ ]<url-pattern>该属性等价于 urlPatterns 属性,两者不能同时指定。
如果同时指定,通常是忽略 value 的取值。
urlPatternsString[ ]<url-pattern>指定一组 Servlet 的 URL 匹配模式。
loadOnStartupint<load-on-startup>指定 Servlet 的加载顺序。
initParamsWebInitParam[ ]<init-param>指定一组 Servlet 初始化参数。
asyncSupportedboolean<async-supported>声明 Servlet 是否支持异步操作模式。
descriptionString<description>指定该 Servlet 的描述信息。
displayNameString<display-name>指定该 Servlet 的显示名。

实现方式: 

//通过实现 Serlvet 接口或继承 GenericServlet 创建的 Servlet 类无法使用 @WebServlet 注解;

//若同时使用 web.xml 与 @WebServlet 配置同一 Servlet 类,则 web.xml 中 <servlet-name> 的值与注解中 name 取值不能相同,否则容器会忽略注解中的配置。


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

/**
 * 注解的方式来配置
 */

/**
 * 1. @WebServlet 是一个注解 => java基础->注解
 * 2. @WebServlet 源码
 * @Target({ElementType.TYPE})
 * @Retention(RetentionPolicy.RUNTIME)
 * @Documented => 在javadoc工具生成文档有记录
 * public @interface WebServlet {
 *     String name() default "";
 *
 *     String[] value() default {};
 *
 *     String[] urlPatterns() default {};
 *
 *     int loadOnStartup() default -1;
 *
 *     WebInitParam[] initParams() default {};
 *
 *     boolean asyncSupported() default false;
 *
 *     String smallIcon() default "";
 *  }
 *  3. urlPatterns 对应 web.xml 的 <url-pattern></url-pattern>
 *  4. {"/ok1", "/ok2"} 可以给OkServlet配置多个 url-pattern
 *  5. 相当于这个@WebServlet(urlPatterns = {"/ok1", "/ok2"}) 代替了 web.xml的配置
 *     底层使用了 反射+注解+IO+集合 来完成一个支撑
 *  6. 浏览器可以这样访问OkServlet时,可以 http://localhost:8080/servlet/ok1 或者
 *     http://localhost:8080/servlet/ok2
 *  7. 我们可以根据 @interface WebServlet 源码知道可以配置哪些
 *  web.xml init-param 在注解中,如何指定呢? 看源码
 *          <init-param>
 *             <param-name></param-name>
 *             <param-value></param-value>
 *         </init-param>
 *  9. 注解方式开发Servlet和 web.xml配置servlet 流程机制是一样
 *  10. /ok1/aa /ok1/bb /ok1/cc /ok1/aa/bb/cc /ok2
 *  11. *.action 这时 zs.action ls.action
 *  12. http://localhost:8080/servlet/register.html
 */

@WebServlet(urlPatterns = {"/ok1/aa"})
public class OkServlet extends HttpServlet {

    @Override
    public void init(ServletConfig config) throws ServletException {
        System.out.println("注解方式 OkServlet init()被调用");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("注解方式 OkServlet doPost()");

    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(10/0);//报错
        System.out.println("注解方式 OkServlet doGet()");
        System.out.println(req.getRemoteAddr());
    }

}

  • 25
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hahaha2221

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值