Day55.Servlet — 生命周期、HttpServlet、ServletContext、路径映射

本文详细介绍了Servlet的基本概念,包括Servlet的生命周期、ServletConfig、HttpServlet的使用以及Servlet的映射路径配置。通过实例展示了如何创建和配置Servlet,以及如何通过ServletContext获取全局初始化参数和资源路径。同时,讲解了url和uri的区别,Web应用的目录结构,以及相对路径和绝对路径的应用。
摘要由CSDN通过智能技术生成

目录

一、Servlet的概念

编写 Hello Servlet

Web 概念梳理

二、Servlet 的生命周期

ServletConfig的介绍

三、Servlet体系结构 (HttpServlet)

使用IDEA创建Servlet​

ServletContext类 (全局的初始化参数 | 全局域对象 | 资源真实路径)

四、Servlet的三种映射路径的配置

url(统一资源定位符) 与  uri(统一资源标识符)

Web中的相对路径和绝对路径

动态获取上下文路径(部署的项目名)


一、Servlet的概念

Web资源就是运行在服务器上的资源,它一共分为两类::
静态资源:html css js 图片...
动态资源 :通过代码控制展示的动态数据。

什么是Servlet?

1. Servlet 是sun公司提供的一套定义动态资源的规范 (接口)

2. Servlet 是JavaWeb三大组件之一。(Servlet程序  Filter过滤器  Listener监听器)

3. Servlet 是运行在服务器上的一个Java小程序,用来接收客服端送过来的请求并响应数据给客户端。 (服务员)


准备工作:导入jar包,模块添加依赖


编写 Hello Servlet

1. 编写一个类去实现Servlet接口,重写方法
2. 实现service方法,处理请求,并响应数据 (不要用中文)
3. 到web.xml中配置servlet程序的访问地址


代码实现:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
<h1>HelloServlet</h1>
<a href="helloServlet">点我</a>


</body>
</html>
public class HelloServlet implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
    }
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {

        System.out.println("HelloServlet!");
        //调用业务层方法(暂略)

        //反馈信息到客户端 (此时中文会乱码!!)
        servletResponse.getWriter().println("Success!");
    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {
    }
}
<?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">

    <!--配置HelloServlet的映射路径 -->
    <servlet>
        <!--给Servlet取名,建议使用类名-->
        <servlet-name>HelloServlet</servlet-name>
        <!--配置的Servlet的全类名,Tomcat内部的Servlet容器通过反射创建Servlet对象-->
        <servlet-class>com.atguigu.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>HelloServlet</servlet-name>
        <!--拦截路径-->
        <url-pattern>/helloServlet</url-pattern>
    </servlet-mapping>

</web-app>

  • 常见错误1:url-pattern 中配置的路径没有以斜杠打头。
  • 常见错误2:servlet-name 配置的值不存在。(打错字)

Web 概念梳理

原生Tomcat

安装在电脑上的实实在在的Tomcat软件

IDEA中的Tomcat实例

通过idea的配置在idea上集成的Tomcat实例,其实还是使用的原生的Tomcat软件

IDEA中的Web工程

程序员使用IDEA编写的动态Web工程,该工程只是用于程序员编码,实际上部署运行在Tomcat服务器中的并不是这个工程。

根据Web工程生成的war包

根据程序员创建的动态Web工程,IDEA会将其打包成一个war包,而真正部署运行在Tomcat服务器中的其实是war包

访问资源的地址

访问静态资源:/Web应用名称/静态资源本身的路径(就是静态资源在web文件夹中的路径)

访问动态资源:/Web应用名称/映射路径

Web应用名称(项目名)

注意Web应用名不是你工程或者Module的名字,而是你在部署时候的ApplicationContext的内容

工程目录 vs 部署目录

部署目录:一般在out文件夹内

二、Servlet 的生命周期

Servlet在容器中是单例的、线程不安全的。(尽量不要修改成员变量、通过成员变量判断)

① Servlet对象的创建:构造器

  • 默认情况下,Tomcat内的Servlet容器第一次收到HTTP请求时创建对应Servlet对象

  • 容器之所以能做到这一点是由于我们在注册Servlet时提供了全类名,容器使用反射技术创建了Servlet的对象。

② Servlet对象初始化:init()

  • Servlet容器创建Servlet对象之后,会调用init(ServletConfig config)方法。

  • init()方法只在创建对象时执行一次,以后再接到请求时,就不执行了

  • 可以通过<load-on-startup>X</load-on-startup> 设置初始化时机,X值越小启动越早。

③ 处理请求:service()

  • service(ServletRequest req, ServletResponse res)方法处理HTTP请求在每次接到请求后都会执行。Servlet的作用,主要在此方法中体现。(由Toncat容器调用)

④ Servlet对象销毁:destroy()

  • 服务器重启、服务器停止执行或Web应用卸载时会调用public void destroy()方法,销毁Servlet对象。

  • 此方法用于销毁之前执行一些诸如释放缓存、关闭连接、保存内存数据持久化等操作。

/**
 * 注解的方式访问Servl(暂时了解)
 * @Author by:Plisetsky
 */
@WebServlet("/anno")
public class AnnoServlet implements Servlet {
    //Servlet对象由Tomcat内部的Servlet容器通过反射创建

    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //init()只会执行一次,可以处对处理请求做准备。
        
    }
    @Override
    public ServletConfig getServletConfig() {
        return null;
    }
    @Override
    public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
       //处理请求的逻辑写在此处,每一次请求都会执行

    }
    @Override
    public String getServletInfo() {
        return null;
    }
    @Override
    public void destroy() {
        //关闭、重启服务器,会导致Servlet销毁,可以进行关闭资源操作
    }
}

ServletConfig的介绍

在web.xml中对Servlet配置的初始化参数,可以在Servlet的init()方法中获取初始化参数的值。

方法名作用
getServletName()获取<servlet-name>HelloServlet</servlet-name>定义的Servlet名称
getServletContext()获取ServletContext对象
getInitParameter()获取配置Servlet时设置的『初始化参数』,根据名字获取值
getInitParameterNames()获取所有初始化参数名组成的Enumeration对象

代码:

web.xml 内设置参数: <init-param>
    <servlet>
        <servlet-name>Servlet</servlet-name>
        <servlet-class>com.atguigu.setvlet.Servlet1</servlet-class>
        <!--配置初始化参数-->
        <init-param>
            <param-name>uname</param-name>
            <param-value>zs</param-value>
        </init-param>
        <init-param>
            <param-name>pwd</param-name>
            <param-value>123456</param-value>
        </init-param>
    </servlet>

    <servlet-mapping>
        <servlet-name>Servlet</servlet-name>
        <url-pattern>/test1</url-pattern>
    </servlet-mapping>
servlet init()内获取参数
public class Servlet1 implements Servlet {
    @Override
    public void init(ServletConfig servletConfig) throws ServletException {
        //获取初始化参数
        //getInitParameter: 根据name获取value
        String unameValue = servletConfig.getInitParameter("uname");
        String pwdValue = servletConfig.getInitParameter("pwd");

        System.out.println(unameValue + "-->" + pwdValue);//zs-->123456

        //getInitParameterNames: 获取所有初始化参数的名字
        Enumeration<String> names = servletConfig.getInitParameterNames();
        while (names.hasMoreElements()){
            String name = names.nextElement();
            //根据name获取value
            String value = servletConfig.getInitParameter(name);
            System.out.println(name+ "-->" + value);//uname-->zs  pwd-->123456
        }
    }

三、Servlet体系结构 (HttpServlet)

创建Servlet时,继承 HttpServlet 需要处理什么业务,重写什么方法。
doGet()
doPost()

使用IDEA创建Servlet

 

之后添加 <servlet-mapping> 即可,如果没有该选项参考:IDEA——万能青年操作指南_焰火青年·的博客-CSDN博客

public class Servlet3Http extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do Get 执行了...");
        
        resp.getWriter().println("get Success");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("do Post 执行了...");

        resp.getWriter().println("Post Success");
    }
}

ServletContext类 (全局的初始化参数 | 全局域对象 | 资源真实路径)

1.ServletContext是一个接口,它表示Servlet上下文对象

2.一个web工程,只有一个ServletContext对象实例

3.ServletContext对象是一个域对象。

4.ServletContext是在web工程部署启动的时候创建。在web工程停止的时候销毁。

  • 一、ServletContext获取全局的初始化参数

web.xml
    <!--配置全局初始化参数-->
    <context-param>
        <param-name>username</param-name>
        <param-value>123456</param-value>
    </context-param>


//获取全局初始化参数,通过servletContext对象
String username = servletContext.getInitParameter("username");
  • 二、ServletContext作为全局的域对象

域对象,是可以像Map一样存取数据的对象。

域对象就是在一定的作用域范围内进行数据共享的对象,ServletContext 作为全局域对象可以在整个项目的所有动态资源(包含所有Servlet)中进行数据共享

			存数据				取数据			  删数据
Map			put()				get()			  remove()	
域对象		setAttribute()		getAttribute()	  removeAttribute()
public class Servlet4Context extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("一、获取servletContext的三种方式");
        //1.获取servletContext上下文(全局)对象
        ServletContext s1 = getServletContext();
        System.out.println("s1 =" + s1);
        //2.通过请求对象来获取
        ServletContext s2 = req.getServletContext();
        System.out.println("s2 = " + s2);
        //3.通过ServletConfig 获取
        ServletContext s3 = getServletConfig().getServletContext();
        System.out.println("s3 = " + s3);

        System.out.println("二、全局初始化参数");
        //获取全局初始化参数 可以被全局共享 所有Servlet共享,一个程序只有一个
        String value = s3.getInitParameter("username");
        System.out.println("username----> "+value);

        System.out.println("三、全局域");
        //向全局域中添加值
        s1.setAttribute("hero","安其拉");

        //获取全局域中的值
        Object hero = s2.getAttribute("hero");
        System.out.println("hero = " + hero);
    }
}
  • 三、获取资源的真实路 

工程目录 
部署目录:

public class Servlet5Attribute extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取全局上下文对象
        ServletContext s1 = req.getServletContext();

        //获取资源在部署目录的路径 (只有部署到服务器中的文件才可以被访问)
        String realPath = s1.getRealPath("/img/wH6gilRG.png");
        System.out.println("realPath = " + realPath);
        //E:\代码\World\out\artifacts\day07Servlet_war_exploded\img\wH6gilRG.png
    }
}

四、Servlet的三种映射路径的配置

一个Servlet可以配置多个映射路径,但是多个Servlet不能配置相同的映射路径

映射路径的分类:完全路径匹配、目录匹配、扩展名匹配

web.xml
    <!--完全路径匹配 -->
    <servlet-mapping>
        <servlet-name>ServletPath1</servlet-name>
        <url-pattern>/path1</url-pattern>
    </servlet-mapping>

    <!--路径模糊匹配(目录匹配) /xxx/* 能够匹配所有`/xxx/任意字符串`的请求路径-->
    <servlet-mapping>
        <servlet-name>ServletPath2</servlet-name>
        <url-pattern>/path1/*</url-pattern>
    </servlet-mapping>

    <!--后缀名匹配(扩展名匹配) *.xxx 能够匹配所有以`.相同扩展名`结尾的请求路径-->
    <servlet-mapping>
        <servlet-name>ServletPath3</servlet-name>
        <url-pattern>*.path</url-pattern>
    </servlet-mapping>
Servlet实现类
public class ServletPath1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("完全路径匹配");

        response.getWriter().println("success!");
    }
}
public class ServletPath2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("路径模糊匹配(目录匹配)");

        response.getWriter().println("success!");
    }
}
public class ServletPath3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("后缀名匹配(扩展名匹配)");

        response.getWriter().println("success!");
    }
}
index.html
<body>
<h1>路径匹配规则</h1>

<a href="path1">完全路径匹配</a>
<a href="path1/12345">路径模糊匹配(目录匹配)</a>
<a href="12345.path">后缀名匹配(扩展名匹配)</a>

</body>

url(统一资源定位符) 与  uri(统一资源标识符)

url:既可以访问本项目资源 也可以访问其他项目资源

uri:标记【当前项目】下的资源 (使用url访问本项目资源,地址太长了,省略一点)

     url:统一资源定位符
     协议    主机名    端口号    应用名/项目名           资源名
     http://localhost:8080/day06Servlet/success.html
     既可以访问本项目资源 也可以访问其他项目资源

<a href="http://localhost:8080/day06Servle/success.html">Success</a>
<a href="http://localhost:8080/day06Servlet/s"> SecondServlet</a>
<a href="http://www.baidu.com">百度一下</a>

     uri:统一资源标识符
        标记【当前项目】下的资源
       
       /应用名/资源名
       <a href="/day06Servlet/success.html">Success</a> <br>
       <a href="/day12Servlet/s"> SecondServlet</a>
 

Web中的相对路径和绝对路径

  • 相对路径:相对自身资源而言

​ .    表示当前目录

​ ../  表示上一级目录

​ 资源名 表示当前目录下/资源名

  • 绝对路径:永远以"/"开头(建议使用)

  • /  如果被浏览器解析,得到的地址是: http://ip:port/ (服务器根目录)

  • 使用时需要加上 / 应用名(项目名)/ 资源名
    http://ip:port/工程路径/资源路径

动态获取上下文路径(部署的项目名)

上下文路径(context path)=/Web应用名称

在使用资源的uri路径中使用绝对路径,项目名一旦修改,将无法定位资源(404)。

request.getContextPath()

public class ServletPath4ContextPath extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("动态获取上下文路径(项目名)");

        //响应一个 a标签到客户端,一旦项目名修改会报错(404)
        // http://localhost:8080/day07ServletPath/success.html
        // response.getWriter().println("<a href="/day07ServletPath/success.html">成功界面</a>");

        //获取 /应用名   /day07ServletPath
        String contextPath = request.getContextPath();

        System.out.println("contextPath = " + contextPath);
        response.getWriter().println("<a href='"+contextPath+"/success.html'>成功界面</a> ");

    }
<body>
<h1>路径匹配规则</h1>

<a href="contextPath">动态获取上下文路径(项目名)</a> <br>

<a href="/day07ServletPath/success.html">Success</a>

</body>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值