03【Response、ServletContext】

追求适度,才能走向成功;人在顶峰,迈步就是下坡;身在低谷,抬足既是登高;弦,绷得太紧会断;人,思虑过度会疯;水至清无鱼,人至真无友,山至高无树;适度,不是中庸,而是一种明智的生活态度。

导读:本篇文章讲解 03【Response、ServletContext】,希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com,来源:原文

03【Response、ServletContext】

一、HTTP响应概述

1.1 什么是HTTP响应:

我们之前学习过HTTP协议,一个完整的HTTP报文分为HTTP请求报文和HTTP响应报文;一个完整的HTTP响应报文中封装了服务器端响应给浏览器的数据,我们学习HTTP响应就是学习HTTP协议中,到底封装了什么数据响应给浏览器;

1.2 响应信息的组成:

一个完整的HTTP响应报文由三个部分组成:响应行,响应头,响应体

  • 编写一个Servlet:
package com.dfbz.response;

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("/demo01")
public class Demo01Servlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.getWriter().write("hello~");
    }
}

发送请求:http://localhost:8080/demo01


  • 打开浏览器按F12,Network—>Headers;查看响应行/响应头:

在这里插入图片描述

  • 响应体:

在这里插入图片描述

Tips:如果是文字,显示文字,如果是图片或音频,视频数据,响应体就是一些二进制的数据

1.2.1 响应行

一个完整的响应行由三个组成部分:协议和版本、响应状态码、状态信息

  • 示例:
HTTP/1.1 200 OK
  • HTTP/1.1:协议和版本
  • 200:响应状态码
  • OK:响应的状态信息

响应状态码分为1xx、2xx、3xx、4xx、5xx,我们可以通过响应的状态码得知请求之后服务器端做的处理,常用于定位错误等

下列是五种状态码的大致含义:

状态码 含义
1xx 指示信息;表示请求已接收,继续处理。
2xx 成功;表示请求已被成功接收、理解、接受。
3xx 重定向;要完成请求必须进行更进一步的操作。
4xx 客户端错误;请求有语法错误或请求无法实现。
5xx 服务器端错误;服务器未能实现合法的请求。

下列是一些常见状态码的具体含义:

状态码 含义
200 正确的从服务器得到响应的数据
302 表示页面重定向
304 使用的是本地缓存,并没有从服务器上再次下载网页
400 请求参数错误
404 找不到服务器上指定的资源
405 如果客户端使用GET/POST方法提交,而服务器端没有doGet/doPost方法,就会出现405错误
415 服务器无法处理请求附带的媒体格式(无法识别请求中携带的参数)
500 服务器出现内部错误,一般是Servlet中的代码有错误

HTTP响应状态码大全:http://tools.jb51.net/table/http_status_code

1.2.2 响应头

响应头由各种键值组成,响应头是固定的,值是可以变的。

响应头信息 说明
Location: http://www.10086.cn 重定向要跳转到的地址
Server:apache tomcat 访问的服务器名字
Content-Encoding: gzip 服务器压缩格式,如果服务器端数据量比较大的时候,首先会将数据进行压缩,这就是指定它的压缩格式。浏览器得到服务器发送过来的数据,浏览器根据这个格式进行解压。
Content-Length: 80 响应的长度
Content-Type: text/html; charset=utf-8 服务器发送过来的数据类型和字符集
Refresh: 1;url=/response/hello.html 表示1秒以后,跳转到/response/hello.html页面
Content-Disposition: attachment; filename=hello.zip Content-Disposition: 内容的处理方式
attachment:以附件的方式下载
filename:下载时候的文件名,不建议使用汉字,汉字有乱码 将服务器上的数据以附件的方式下载
Date: Fri, 05 Feb 2021 01:17:00 GMT 告诉浏览器,服务器响应时间
expires: Mon, 08 Feb 2021 02:27:18 GMT 告诉浏览器回送的资源缓存多长时间。如果是-1或者0,表示不缓存

1.2.3 响应体

响应体就是服务器发送给浏览器的数据,这个数据可以是任何格式,如响应一个html,响应一张图片,一个音频等任意文件

编写一个Servlet,给客户端响应一张图片:

package com.dfbz.response;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo02")
public class Demo02Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 去磁盘上读取一个文件
        FileInputStream fis = new FileInputStream("D:/000.png");

        // 获取与前端的输出流
        ServletOutputStream out = resp.getOutputStream();

        int data;
        while ((data=fis.read())!=-1){
            out.write(data);
        }
        fis.close();
        out.close();
    }
}

访问:http://localhost:8080/demo02

在这里插入图片描述

Tips:此时后端响应的是一张图片

1.3 Http协议小结

  • Http请求
    • 请求行
      • 提交的方式
      • 请求的地址
      • 采用的协议和版本
    • 请求头
      • host
      • connection
      • referer
      • content-type
      • Cookie
      • Accept
    • 请求体(GET提交方式没有请求体)
  • Http响应
    • 响应行
      • 采用的协议
      • 状态码
        • 200
        • 302
        • 304
        • 404
        • 405
        • 500
      • 响应的状态信息
    • 响应头
      • Refresh
      • Content-Disposition
      • ContentType
      • set-cookie
    • 响应体

二、HttpServletResponse对象

HttpServletResponse是JavaEE中用来封装HTTP响应报文的对象,我们可以通过改对象获取HTTP响应报文中响应行,响应头,响应体的详细数据;

2.1 设置响应行

2.2.1 设置响应状态码

  • void setStatus(int status):设置响应状态码

示例代码:

package com.dfbz.response;

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("/demo03")
public class Demo01 extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置响应的状态码
        response.setStatus(222);
    }
}

访问:http://localhost:8080/demo03

在这里插入图片描述

2.2.2 常见响应码

1)404状态码

  • 404的含义:找不到指定的资源
404常见的情况 描述
地址栏错误 地址栏打错,区分大小写。
web.xml配置问题 如果web.xml中出现配置信息,会导致整个项目启动失败,所有的资源都找不到。
项目未部署 项目没有部署到服务器
访问WEB-INF /web/WEB-INF/下面资源是受保护,不能直接访问。

在这里插入图片描述

总结:404就是资源找不到

2)405状态码

  • 405的含义:如果客户端使用GET/POST方法提交,而服务器端没有doGet/doPost方法,就会出现405错误

提供一个Servlet:

405简单的来说就是找不到对应的方法;Get方式—>doGet方法,Post方式—>doPost方法

package com.dfbz.response;

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;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo04")
public class Demo04Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello~");
    }
}

访问:http://localhost:8080/demo04

在这里插入图片描述

3)500状态码

  • 500状态码含义:服务器出现异常后没有即使处理抛给WEB服务器(Tomcat)处理将默认响应500状态码;

示例代码:

package com.dfbz.response;

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;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo05")
public class Demo05Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        int i = 1 / 0;
    }
}

访问:http://localhost:8080/demo05

在这里插入图片描述

2.3 设置响应头

  • 响应头相关方法:
响应头的方法 描述
void setHeader(String name, String value) 设置响应头,指定名字和值
void setContentType(String type) 设置响应的内容类型,功能上与 setHeader(“content-type”, “值”) 相同

2.3.1 Refresh

示例一:过3秒浏览器去请求另一个网站

  • 开发步骤:
  1. 创建一个Servlet

  2. 调用setHeader,设置消息头("refresh","3;url=http://www.jd.com"

  3. 调用setStatus,设置响应状态码200,可选。

  • 代码:
package com.dfbz.response;

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;
import java.io.PrintWriter;

/**
 * 案例: 3秒后跳转到另一个网站
 */
@WebServlet("/demo06")
public class Demo06Servlet extends HttpServlet {

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

        // 设置响应类型和响应的编码
        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();
        out.print("过3秒以后跳转到京东首页");

        // 设置响应头
        response.setHeader("refresh", "3;url=https://www.jd.com");
    }
}

2.3.2 Location

示例二:使用location进行页面跳转(重定向)

Tips:Location必须搭配302状态一起使用,否则将不能重定向

  • 302的含义:进行页面重定向
package com.dfbz.response;

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("/demo07")
public class Demo07Servlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置响应头 需要搭配状态码一起使用
        response.setHeader("location", "http://www.jd.com");
        // 设置状态码为302
        response.setStatus(302);

        //专门重定向方法
//        response.sendRedirect("http://www.jd.com");
    }
}

访问:http://localhost:8080/demo07

在这里插入图片描述

Tips:302代表该资源发生了重定向行为;

2.3.3 Content-Disposition

Content-disposition 是 MIME 协议的扩展,设置客户端如何显示附加的文件。Content-disposition可以设置用户请求所得的内容为一个文件的时候提供一个默认的文件名,文件直接在浏览器上显示或者在访问时弹出文件下载对话框。

  • Content-Disposition响应头有两个参数:
    • inline:直接在页面显示(这也是大部分浏览器的默认值)
    • attachment:以附件形式下载
package com.dfbz.response;

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

@WebServlet("/demo08")
public class Demo08Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 设置Content-Disposition响应头
//        resp.setHeader("Content-Disposition","inline");           // 直接在页面显示
//        resp.setHeader("Content-Disposition","attachment");        // 以附件形式下载
        // resp.setHeader("Content-Disposition","attachment;filename=abc.png");     // 以附件形式下载,顺便设置文件名

        // 如果是中文记得要编码
        resp.setHeader("Content-Disposition","attachment;filename=图片.png");
        
        // 使用输入流关联一个磁盘文件
        FileInputStream fis = new FileInputStream("D:/000.png");

        // 获取与前端的输出流
        ServletOutputStream out = resp.getOutputStream();

        int data;

        while ((data = fis.read()) != -1) {
            out.write(data);
        }

        fis.close();
        out.close();
    }
}
  • URL编码有关的方法如下:
URL编码有关的方法 描述
java.net.URLEncoder.encode(字符串, “utf-8”) 对字符串进行utf-8编码
java.net.URLDecoder.decode(字符串, “utf-8”) 对字符串进行utf-8解码
package com.dfbz.demo;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
public class TestCode {
    public static void main(String[] args) throws UnsupportedEncodingException {
        String str = "图片";
        System.out.println(str);
        //编码
        String encode = URLEncoder.encode(str, "utf-8");
        System.out.println(encode);
        //解码
        String decode = URLDecoder.decode(encode, "utf-8");
        System.out.println(decode);
    }
}

2.3.4 Content-Type

Content-Type响应头用于告诉客户端,服务器将要响应什么数据格式给前端,前端按照这个数据类型进行解析;

  • 常见的响应类型:
text/html HTML格式
Content-Type类型 说明
text/plain 纯文本格式
text/xml XML格式
image/gif gif图片格式
image/jpeg jpg图片格式
image/png png图片格式
application/xhtml+xml XHTML格式
application/xml XML数据格式
application/json JSON数据格式
application/pdf pdf格式
application/msword Word文档格式
application/octet-stream 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded 表单中默认的encType,form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)

Content-Type对照表:https://tool.oschina.net/commons/

由于后期Content-Type响应头用的太多了,因此HttpServletResponse对象提供setContentType()方法单独来设置Content-Type响应头,当然也可以使用setHeader()方法来设置Content-Type响应头;

示例:

package com.dfbz.response;

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("/demo09")
public class Demo09Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().write("abc<h1>hello</h1>");
    }
}

访问:http://localhost:8080/demo09

在这里插入图片描述

设置响应头:

package com.dfbz.response;

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("/demo09")
public class Demo09Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

//        resp.setContentType("text/html;charset=utf8");
        resp.setHeader("Content-Type","text/html;charset=utf8");        // 等价于上面

        resp.getWriter().write("abc<h1>hello</h1>");
    }
}

访问:http://localhost:8080/demo09

在这里插入图片描述

3.3 设置响应体

响应体的方法 描述
OutputStream getOutputStream() 字节输出流,如果从服务器上返回是二进制数据,使用字节输出流。 也可以返回字符。
PrintWriter getWriter() 字符输出流,如果从服务器上返回的是字符数据,文字之类。

我们之前一直使用的是reponse的getWriter()方法,此方法返回一个字符打印输出流,默认指向的是来请求的客户端,使用该类可以很方便的向客户端写出文本数据,但是如果我们希望往客户端写出其他数据,如图片、视频、压缩包等,我们就需要使用response的getOutputStream()方法了;

  • 案例:服务器往客户端写回一张图片
package com.dfbz.response;

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

@WebServlet("/demo10")
public class Demo10Servlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        // 响应响应类型
        resp.setContentType("image/png");

        // 读取服务器本地的图片
        FileInputStream fis = new FileInputStream("D://000.png");

        // 获取一个字节输出流,该流指向的是客户端
        ServletOutputStream out = resp.getOutputStream();

        byte[] data = new byte[1024];

        int len;

        while ((len = fis.read(data)) != -1) {
            out.write(data, 0, len);
        }

        // 释放资源
        fis.close();
        out.close();
    }
}

三、ServletContext上下文对象

3.1 ServletContext简介

ServletContext官方叫servlet上下文。WEB容器在启动时,它会为每个WEB应用程序都创建一个对应的ServletContext对象,它代表当前web应用。而且工程内部的所有servlet都共享这个对象。

ServletContext:代表当前web应用

  • 回顾Servlet的继承结构

在这里插入图片描述

所有的HttpSerlvet都实现了ServletConfig接口,ServletConfig对象中维护了ServletContext对象的引用,开发人员在编写servlet时,可以通过ServletConfig.getServletContext方法获得ServletContext对象,由于一个WEB应用中的所有Servlet共享同一个ServletContext对象,因此Servlet对象之间可以通过ServletContext对象来实现通讯。

  • ServletContext getServletContext():获取ServletContext对象

在这里插入图片描述

3.2 ServletContext的作用

3.2.1 获取当前工程的资源文件

  • 相关的方法:
ServletContext的方法 功能
InputStream getResourceAsStream(String path) 得到web目录下的资源,转成一个输入流对象
String getRealPath(String path) web目录下的资源,得到它在服务器上部署的真实路径

1)访问WEB-INF下的资源访问

  • 示例:读取WEB-INF下面的图片文件显示在浏览器上

示例代码:

package com.dfbz.demo;

import javax.servlet.ServletContext;
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;
import java.io.InputStream;
import java.io.OutputStream;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo01")
public class Demo01_GetWebInfoResource extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //得到上下文对象
        ServletContext application = getServletContext();

        //得到一个文件输入流
        InputStream in = application.getResourceAsStream("/WEB-INF/000.png");

        //得到一个输出流
        OutputStream out = response.getOutputStream();   //字节流

        //设置响应头
        response.setContentType("image/png");

        //输出到浏览器上
        byte[] buf = new byte[1024];

        int len;

        while ((len = in.read(buf)) != -1) {
            out.write(buf, 0, len);
        }
    }
}

2) 得到指定资源的真实地址

package com.dfbz.demo;

import javax.servlet.ServletContext;
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;
import java.io.PrintWriter;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo02")
public class Demo02_RealPath extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 得到上下文对象
        ServletContext application = getServletContext();

        // 得到某个资源的真实地址
        String realPath = application.getRealPath("/index.html");

        // 输出到浏览器
        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();

        out.print("真实地址是:" + realPath);
    }
}

在这里插入图片描述

问:资源文件如果不存在会怎么样?

  • 不会有影响,只是将项目部署的真实路径+我们的资源路径

在这里插入图片描述

Tips:项目中并没有/abc/demo/abca.html资源;

3.2.2 获取作用域对象的值

在这里插入图片描述

域对象的功能:在Servlet之间进行数据的共享;底层是一个Map对象,由键和值集合组成

1)上下文域的作用范围:

只有服务器没有关闭,所有的用户都可以访问,每个用户的每次请求都可以读取或修改上下文域中的数据。

  • 域对象相关方法:
ServeltContext的方法 作用
void setAttribute(“键”,Object数据) 向上下文域中添加键和值
Object getAttribute(“键”) 从上下文域中得到值
void removeAttribute(“键”) 删除上下文域中的键值对

2)统计登录人数小案例

原理:当第一次初始化登录Servlet时初始化count值为0,每一个用户登录成功后,取出count值+1再次存入到域对象,此域对象必须所有的servlet共享;

  • 开发步骤:

    • 1)在LoginServlet的init()方法中创建count=0,并且将值放入上下文域中.
    • 2)在登录成功的代码中从上下文域中取出count,并且加1,再更新上下文域中的值。
    • 3)跳转到另一个CountServlet,在另一个CountServlet中取出上下文域中的值,显示在页面上。
  • 登录的表单:

<!DOCTYPE html>
<html>
<head>
    <title>登录页面</title>
    <meta charset="UTF-8">
</head>
<body>
<h2>用户登录</h2>
<form action="login" method="post">
    用户名: <input type="text" name="username"/><hr>
    密码: <input type="password" name="password"/><hr/>
    <input type="submit" value="登录"/>
</form>
</body>
</html>
  • Demo03_LoginServlet:
package com.dfbz.demo;

import javax.servlet.ServletContext;
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;
import java.io.PrintWriter;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/login")
public class Demo03_LoginServlet extends HttpServlet {


    // 在初始化的方法中,向上下文域中放入一个初始值count = 0
    @Override
    public void init() throws ServletException {
        getServletContext().setAttribute("count", 0);
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        PrintWriter out = response.getWriter();

        //得到上下文对象
        ServletContext application = getServletContext();

        // 1.登录判断用户名和密码是否正确
        String username = request.getParameter("username");
        String password = request.getParameter("password");

        if ("admin".equals(username) && "123".equals(password)) {
            // 2. 如果登录成功,将上下文域中的数据取出,加1,放回到上下文域中
            int count = (int) application.getAttribute("count");
            application.setAttribute("count", ++count);

            // 重定向到另一个Servlet显示登录人数
            response.sendRedirect("/count");
        }
        //登录失败
        else {
            out.print("<script>");
            out.print("alert('用户名或密码不正确');");
            out.print("location.href='/login.html';");
            out.print("</script>");
        }
    }
}
  • Demo04_CountServlet:
package com.dfbz.demo;

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;
import java.io.PrintWriter;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/count")
public class Demo04_CountServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        response.setContentType("text/html;charset=utf-8");

        PrintWriter out = response.getWriter();

        // 从上下文域中取出数据,并且显示出来
        out.print("<h1>你是第" + getServletContext().getAttribute("count") + "个登录的用户</h1>");
    }
}

3.2.3 配置全局参数

我们知道ServletContext是随着容器的启动而创建,有的时候我们希望配置一些全局参数,让这些参数也随着容器的启动而初始化,这个时候我们可以在web.xml配置一些全局参数,如:让mysql的连接随着容器的创建而创建

配置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">


    <!--配置全局参数-->
    <context-param>
        <param-name>username</param-name>
        <param-value>root</param-value>
    </context-param>
    <context-param>
        <param-name>password</param-name>
        <param-value>admin</param-value>
    </context-param>
    <context-param>
        <param-name>url</param-name>
        <param-value>jdbc:mysql://localhost:3306/test</param-value>
    </context-param>
    <context-param>
        <param-name>driverClassName</param-name>
        <param-value>com.mysql.jdbc.Driver</param-value>
    </context-param>
</web-app>
  • Demo06_GetInitParams:读取全局参数
package com.dfbz.demo;

import javax.servlet.ServletContext;
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;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo06")
public class Demo06_GetInitParams extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        ServletContext app = getServletContext();

        // 使用getInitParameter方法获取全局参数
        Object username = app.getInitParameter("username");
        Object password = app.getInitParameter("password");
        Object url = app.getInitParameter("url");
        Object driverClassName = app.getInitParameter("driverClassName");

        response.getWriter().println("username: " + username);
        response.getWriter().println("password: " + password);
        response.getWriter().println("url: " + url);
        response.getWriter().println("driverClassName: " + driverClassName);
    }
}

访问:http://localhost:8080/demo06

在这里插入图片描述

3.2.4 获得MIME类型

MIME:全称Multipurpose Internet Mail Extensions,多功能Internet邮件扩充服务。它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。MIME类型就是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

Tips:MIME就是文件的媒体类型。浏览器可以根据它来区分文件,然后决定什么内容用什么形式来显示。

  • 常见文件的MIME类型:
文件拓展名 MIMEType
png image/png
bmp\dib image/bmp
jpg\jpeg\jpg image/ipeg
gif image/gif
mp3 audio/mpeg
mp4\mpg4\m4v\mp4v video/mp4
js application/javascript
pdf application/pdf
text\txt text/plan
json application/json
xml text/xml

示例代码:

package com.dfbz.demo;

import javax.servlet.ServletContext;
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;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo07")
public class Demo07_GetMIMEType extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 获取上下文对象
        ServletContext app = getServletContext();

        // 设置响应的类型
        response.setContentType("text/html;charset=utf8");

        // image/ipeg
        response.getWriter().write("【a.jpg】--->【" + app.getMimeType("a.jpg") + "】<hr>");

        // image/png
        response.getWriter().write("【a.png】--->【" + app.getMimeType("a.png") + "】<hr>");

        // application/pdf
        response.getWriter().write("【a.pdf】--->【" + app.getMimeType("a.pdf") + "】<hr>");

        // null
        response.getWriter().write("【a.word】--->【" + app.getMimeType("a.word") + "】<hr>");

        // application/javascript
        response.getWriter().write("【a.js】--->【" + app.getMimeType("a.js") + "】<hr>");
    }
}

访问:http://localhost:8080/demo07

在这里插入图片描述

3.2.5 ServletRegistration注册器

ServletContext对象很大程度上代表了当前的WEB容器(或当前项目),我们可以获取当前WEB容器已经注册的Servlet信息;

1)获取注册的Servlet信息

  • Map<String, ? extends ServletRegistration> getServletRegistrations():获取当前WEB容器所有的注册器
  • ServletRegistration getServletRegistration(String var1):根据servlet的名称(默认是该servlet的全路径)获取指定的注册器

示例代码:

package com.dfbz.demo;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo08")
public class Demo08_GetRegistrationServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置响应类型
        response.setContentType("text/html;charset=utf8");

        // 获取与前端的字符输出流
        PrintWriter out = response.getWriter();

        // 获取上下文对象
        ServletContext app = getServletContext();

        // 获取当前WEB容器中注册的所有Servlet
        Map<String, ? extends ServletRegistration> registrationMap = app.getServletRegistrations();

        for (String servletName : registrationMap.keySet()) {
            out.println("【servletName】----【" + servletName + "】<hr>");
        }

        // 根据类的全路径获取指定的注册器
        ServletRegistration servletRegistration = app.getServletRegistration("com.dfbz.demo.Demo08_RegisterServlet");
        out.println("【Demo08_RegisterServlet的注册器】----【" + servletRegistration + "】<hr>");
    }
}

访问:http://localhost:8080/demo08

在这里插入图片描述

2)ServletRegistration注册器

ServletRegistration注册器用于获取Servlet的一系列信息;

  • 1)编写Servlet,ServletRegistration注册器使用获取Demo08Servlet的Mapping信息:
package com.dfbz.demo;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo09")
public class Demo09_GetRegistrationServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 获取上下文对象
        ServletContext app = getServletContext();

        // 获取与客户端的字符输出流
        PrintWriter out = response.getWriter();

        // 根据类的全路径获取指定的注册器
        ServletRegistration registration = app.getServletRegistration("com.dfbz.demo.Demo08_GetRegistrationServlet");

        // 获取servlet的mapping映射
        Collection<String> mappings = registration.getMappings();

        for (String mapping : mappings) {
            out.println(mapping + "<hr>");
        }
    }
}

访问:http://localhost:8080/demo09

在这里插入图片描述

  • 2)使用注册器注册新的Mapping信息:
package com.dfbz.demo;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo10")
public class Demo10_addMappingServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 获取上下文对象
        ServletContext app = getServletContext();

        // 根据类的全路径获取指定的注册器
        ServletRegistration registration = app.getServletRegistration("com.dfbz.demo.Demo08_GetRegistrationServlet");

        // 新增servlet映射
        registration.addMapping("/demo08_1", "/demo08_2");
    }
}

访问:http://localhost:8080/demo10,再访问http://localhost:8080/demo09

在这里插入图片描述

此时使用http://localhost:800/demo08、http://localhost:800/demo08_1、http://localhost:800/demo08_2都可以访问到Demo08Servlet!


除此之外,注册器还可以帮助我们获取Servlet的其他信息:

  • String getClassName():获取该Servlet的全路径
  • String getName():获取该Servlet的名称

示例代码:

package com.dfbz.demo;

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

/**
 * @author lscl
 * @version 1.0
 * @intro:
 */
@WebServlet("/demo11")
public class Demo11_RegistrationMethod extends HttpServlet {
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        // 设置响应的类型
        response.setContentType("text/html;charset=utf8");

        // 获取与客户端的字符输出流
        PrintWriter out = response.getWriter();

        // 获取上下文对象
        ServletContext app = getServletContext();

        // 根据servlet的名称(默认为servlet的全路径)径获取指定的注册器
        ServletRegistration registration = app.getServletRegistration("com.dfbz.demo.Demo08_GetRegistrationServlet");

        // 获取servlet的全路径
        out.println("getClassName: " + registration.getClassName() + "<hr>");

        // 获取该servlet的名称
        out.println("getName: " + registration.getName() + "<hr>");
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/131642.html

(0)
飞熊的头像飞熊bm

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!