总结30 WEB服务器中HTTP的Response与ServletContext对象之应用,以及Mime

Response概念

Response是HTTP中的一种应用对象.
它同Request对象属于对等关系,Request负责请求,Response负责响应(即传递数据给浏览器)

响应行/响应头/响应体的介绍

响应行

当你访问某个服务器的资源时,服务器的响应行都会给你一个代码,依照代码不同代表多种含义.
分类:

一,代码:1xx 服务器就收客户端消息,但没有接受完成,等待一段时间后,发送1xx多(今后不会见到)
二,代码:2xx 客户端的请求正确,服务器也成功的完成了响应。其中的’200’代表完全OK
三,代码3xx 重定向。其中302代表重定向,304代表访问缓存
四,代码:4xx 客户端错误。其中404为请求路径没有对应的资源, 405为请求方式没有对应的doXxx方法
五,代码:5xx 服务器端错误。其中500为服务器内部出现异常

响应头

响应头就是一些协议头
而Response毕竟是用来响应的(即发送数据给客户浏览器),所以也没什么好介绍的.
接下来介绍几种常用的响应头,这里只侧重介绍,以后才会将怎么用.
格式:response.setHeader("响应头名字",对应着该响应头的值);
列如:

        //3.1设置响应头类型:content-type
        response.setHeader("content-type",mimeType);
        //3.2设置响应头打开方式:content-disposition
        response.setHeader("content-disposition","attachment;filename="+filename);

常见的响应头名字:
一. Content-Type
服务器告诉客户端本次响应体数据格式以及编码格式(即:你要让客户端打开或下载的文件是哪个mime类型的)
格式:response.setHeader("content-type",String类型的mime格式类型);
列如:

response.setHeader("content-type",mimeType );

二. Content-disposition
服务器告诉客户端以什么格式打开响应体数据
Content-disposition响应头的属性有:

  1. in-line:默认值,可省略,在当前页面内打开
    2.attachment;filename=资源链接:以附件形式打开响应体。文件下载
    格式: response.setHeader("content-disposition", "attachment;filename="+String类型的本地资源链接);
    列如:
 response.setHeader("content-disposition", "attachment;filename=1.jpg");

响应体

是什么不用我介绍了吧,在Response对象中用于数据传输

Response对象的重定向

概念及和Request的区别

重定向是Response对象的一个功能,可以同Request对象的’请求转发’功能对等.
都是将当前服务器的资源转向另一个资源(可以理解为页面),只是区别不同
Response和Request的区别如下:

重定向的特点(英语为:redirect)
1. 地址栏发生变化
2. 重定向可以访问其他站点(服务器)的资源
3. 重定向是两次请求。不能使用request对象来共享数据
4. 当指向目标资源时,不仅需要写配置菜单中的虚拟路径,还需要写WebServlet注解的路径

5. 重定向时,默认定向到在目标资源的doGet方法内,(可以通过解决这个问题)
转发的特点(英语为:forward)
1. 转发地址栏路径不变
2. 转发只能访问当前服务器下的资源
3. 转发是一次请求,可以使用request对象来共享数据
4. 当指向目标资源时,3.转发不需要写配置菜单中的虚拟路径,只需要写WebServlet注解的路径

5.转发时,同时转发到目标资源的doGet和doPost方法内

创建方式一(不推荐)

步骤一: 先将其响应状态设置为302,以告诉浏览器访问成功,可以进行重定向
固定格式: response.setStatus(302);
步骤二:指定协议头和虚拟路径,进行重定向
格式:response.setHeader("location", "虚拟路径");
列如:

     response.setStatus(302);//设置状态码为302
response.setHeader("location", "/test/Redirect");

创建方式二(推荐)

格式:response.sendRedirect("虚拟路径");
列如:

 response.sendRedirect("/test/Redirect");

重定向的doGet和doPost解决

在重定向中,当你从定向处定向到某个资源时,只会定向到该资源的doGet方法内,因此,如果想要在该资源的doPost方法内使用的话,需要解决.解决办法也很简单.
解决办法:在doGet方法内第一行写上代码doPost(request, response);
在这里插入图片描述

重定向时,虚拟路径的注意点

在Request的请求转发中,仅需要填写被定向处WebServlet注解里头的虚拟路径即可.
但是在Response的重定向中,不仅需要填写被定向处WebSerlvet注解里头的虚拟路径,还需要填写配置文件中的虚拟路径才行.
在这里插入图片描述

路径的扩展写法(不重要)

  * 路径写法:
  	1. 路径分类
  		1. 相对路径:通过相对路径不可以确定唯一资源(不推荐)
  			* 如:./index.html
  			* 不以/开头,以.开头路径

  			* 规则:找到当前资源和目标资源之间的相对位置关系
  				* ./:当前目录
  				* ../:后退一级目录
  		2. 绝对路径:通过绝对路径可以确定唯一资源(推荐)
  			* 如:http://localhost/day15/responseDemo2		/day15/responseDemo2
  			* 以/开头的路径

  			* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
  				* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
  					* 建议虚拟目录动态获取:request.getContextPath()
  					* <a> , <form> 重定向...
  				* 给服务器使用:不需要加虚拟目录
  					* 转发路径

Response输出数据

Response身为响应对象,必然是要对浏览器传输各种数据的,因此它可以输出数据到网页或浏览器上,既可以是字符流的可见式文本内容,也可以是图片,视频,文件等字节流数据.

设置编码

当你要在网页上输出数据时,那么可能会出现乱码情况.
因此,为了你所输出的文本不会乱码,那么需要在输出字符数据前要设置编码.
目前已经有三种设置编码的方法,前二种已经淘汰
注意:当你使用字节流输出数据的同时,却不用来输出文本时,则没必要用.

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

在这里插入图片描述

输出字符流数据

步骤一:获取字符流输出对象
格式:PrintWriter 自定义字符流输出对象名 = response.getWriter();
列如:

PrintWriter pw = response.getWriter();

步骤二 输出字符到网页
格式:自定义字符流输出对象名.write(String类型文本);
列如:

 pw.write("输出文本哦1!");

输出字节流数据

步骤一:获取字节流输出对象
格式:ServletOutputStream 自定义字节流输出对象名 = response.getOutputStream();
列如:

ServletOutputStream os = response.getOutputStream();

步骤二:输出字节数据到浏览器(如文件,图片)
格式:自定义字节流输出对象名.write(byte类型的数组);
列如:

        os.write("你好".getBytes());

实现验证码

用Java编写生成验证码

不需要具体掌握,能看懂代码就行.
此为固定格式,假如哪天真轮到自己要写生成验证码的源码,直接拿来用就行了.
代码如下:

@WebServlet("/codetest")
public class ImgCode extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//用于生成验证码
        //定义图片宽度
        int width = 100;

        //定义图片高度
        int height = 50;

        //创建图片对象,并设置宽度,高度,和图片色素类型(此处为RGB)
        //格式:BufferedImage 自定义图片对象名= new BufferedImage(宽度,高度 ,图片色素类型 );
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);

        //根据图片对象来获取画笔对象
        //格式: Graphics 自定义画笔对象名 = 自定义图片对象名.getGraphics();
        Graphics gs = image.getGraphics();

        //设置画笔颜色 用于充填背景颜色
        //格式:自定义画笔对象名.setColor(Color.颜色名);
        gs.setColor(Color.PINK);

        //设置矩形,并自动根据画笔颜色和矩形高宽来充填背景颜色
        //格式:自定义画笔对象名.fillRect(0, 0, 宽度, 高度);
        gs.fillRect(0,0,width,height);

        //设置画笔颜色,用于充填边框颜色
        //格式:自定义画笔对象名.setColor(Color.颜色名);
        gs.setColor(Color.BLUE);

        //设置边框,并自动根据画笔颜色和边框高宽来充填边框颜色
        //格式:自定义画笔对象名.drawRect(0, 0, 宽度-1, 高度-1);
        gs.drawRect(0,0,width - 1,height - 1);


        //设置验证码要随机的单个生成大小写字母,数字之范围
        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";

        //定义Random对象,用于验证码的随机字符
        Random ran = new Random();

        //根据每个验证码图片内的字符数量之需求,通过设置循环次数来选出n个验证码
        for (int i = 1; i <= 4; i++) {
            //根据验证码的随机字符范围,来生成一个随机数
            //格式:int index = Random对象名.nextInt(定义了验证码自定义范围的字符串.length());
            int index = ran.nextInt(str.length());

            //通过Random生成的随机数来获取要选择的验证码字符
            //格式:char 自定义随机字符结果接收变量 = 定义了验证码自定义范围的字符串.charAt(index);
            char ch = str.charAt(index);

            //根据随机选择出来字符,定义验证码图片中的字符,并依据循环次数的'i'来变换并生成x和y的坐标点
            //格式:gs.drawString(自定义随机字符结果接收变量+"",验证码单个字符在图片中的x坐标点/5*i,验证码单个字符在图片中的y坐标点/2);
            gs.drawString(ch+"",width/5*i,height/2);//从左到右 第一个验证码字符
        }

        //根据画笔颜色,设置验证码干扰线的颜色
        //格式:自定义画笔对象名.setColor(Color.颜色名);
        gs.setColor(Color.GREEN);


        //根据干扰线的数量需求和图片的高度,用for循环随机生成n个'不高于图片高度的干扰线'的坐标
        for (int i = 0; i < 10; i++) {

            //获取每个生成出来的坐标值
            //格式:int 第一个x的坐标值 = random对象名.nextInt(图片宽度);
            int x1 = ran.nextInt(width);

            //格式:int 第二个x的坐标值 = random对象名.nextInt(图片宽度);
            int x2 = ran.nextInt(width);

            //格式:int 第一个y的坐标值 = random对象名.nextInt(图片高度);
            int y1 = ran.nextInt(height);

            //格式:int 第二个y的坐标值 = random对象名.nextInt(图片高度);
            int y2 = ran.nextInt(height);

            //将随机生成出来的四个值作为参数应用到画笔对象的drawLine方法中
            //格式:自定义画笔对象名.drawLine(第一个x的坐标值,第一个y的坐标值,第二个x的坐标值,第二个y的坐标值);
            gs.drawLine(x1,y1,x2,y2);

        }


        //定义图片输出流对象,以将图片输出到网页中
        //格式:ImageIO.write(自定义图片对象名, ".自定义图片格式后缀",response响应对象的字节输出流);
        ImageIO.write(image,"jpg",response.getOutputStream());
        System.out.println("访问验证码");

    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request, response);
    }
}

在网页中实现验证码

需求:单击验证码图片就会生成一个新的验证码,并获取
思路:
一,在HTML代码中定义一个img标签,并用’src’指向一个配置菜单路径+webservlet注解路径的虚拟路径
二.通过 window.onload赋值一个函数,来预先加载Js代码
三.通过document.getElementById来绑定图片的ID
四.通过onclick定义给图片定义一个单击事件,并赋值验证码更新函数
五.定义一个对象日期对象,并通过getTime方法获取当前日期毫秒值
六.setAttribute这个用来设置属性的方法,来设置图片的src属性指向虚拟路径,以便刷新图片达到更新验证码的目的
七.将获取的毫秒值也添加在src属性内,虚拟路径的后面,以"虚拟路径?毫秒值"的形式.
列如: codeId.setAttribute("src","/test/codetest?"+time);
五和六的原因:
因为浏览器会自动缓存相同http地址的图片,因此,如果验证码的图片地址要是不变化,那么尽管刷新了,也会自动获取此前的验证码图片,因此只有让验证码的http地址不断变化(通过毫秒值实现),才不会造成一个已经被缓存的相同验证码图片出现

在这里插入图片描述

ServletContext对象

在这里插入图片描述

概念

记录了当前项目在运行时候的基本的信息。一个项目有且只有唯一的一个ServletContext对象。

创建

分为两种创建方式,没有任何本质上的区别
方式一:根据Request对象创建
格式:ServletContext 自定义Context对象名 = request.getServletContext();
列如:

ServletContext servletContext = request.getServletContext();

方式二:直接创建
格式:ServletContext 自定义Context对象名 = getServletContext();
列如:

ServletContext contextObj = getServletContext();

路径须知

在ServetContext对象中,getRealPath和getMimeType两个方法
他们的参数都需要填写某个文件的路径.
但是这个路径相当有讲究,他有一个默认的相对路径,这个相对路径是以IDEA的WEB项目输出目录为准

 String b = context.getRealPath("/b.txt");//web目录下资源访问
         System.out.println(b);

        String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
        System.out.println(c);

        String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
        System.out.println(a);
        
        
        注意:当需要调用getRealPath方法访问硬盘上的真实路径资源时,实际上访问这个'真实路径'的资源就是IDEA的Out输出目录(D:\IdeaProjects\basic-code\out\)
        在IDEA的Out输出目录下,'artifacts'目录专门用于存放WEB模块的输出文件(D:\IdeaProjects\basic-code\out\artifacts\)
        (重点)在每个WEB模块的输出文件目录下,WEB-INF目录下'classes'目录,对应着IDEA中,模块的'src'目录(D:\IdeaProjects\basic-code\out\artifacts\day31_Senior_Response_war_exploded\WEB-INF\classes).
        也就是说,getRealPath所访问的默认'真实资源路径'为:Out目录 --> artifacts目录 --> 对应着模块名的目录

在这里插入图片描述

通过getRealPath方法获取文件路径

意义
通过指定一个项目宏观宏观路径,进而获取到完整的绝对路径
格式:String path = contextObj.getRealPath("/某文件的项目宏观输出路径");
列如:

String path = contextObj.getRealPath("/index.jps");

通过getMimeType方法获取文件类型

意义:
我们都知道,当一个文件存储在我们硬盘上是,可以是多种格式,比如txt,exe,jpg,mp4等等.
当我们把这些硬盘中的文件共享到网页上时,或者从网页上下载这些文件时,浏览器同样也有特殊的规则表示这些文件类型
而这种类型,我们称之为"Mime类型"的格式
jpg图片格式,在Mime类型中就为:image/jpeg
或者mp4格式,在Mime类型种被称之为:video/mp4

和getRealPath的区别在于:
两者虽然都是要填写路径,但getMimeType返回的是一个转换为mime类型格式的结果,而getRealPath单单只是返回一个路径
在这里插入图片描述
格式:String 自定义Mime类型结果名 = 自定义Context对象名.getMimeType("/某文件的项目宏观输出路径")
列如:

String mimeType = contextObj.getMimeType("/WEB-INF/classes/test.jpg")

Context对象中的数据共享

Context对象也可以进行数据共享,跟请求转发和重定向不同的是,不需要指定一个虚拟路径,只要是属于该WEB模块中的Java文件,都可以直接共享.
如下方法是基于Context对象上实现的,要使用如下方法,需要先创建Context对象,此处略过.

​ 跟request域对象的区别:

​ request对象:域范围多大

​ 时间:从服务器接收到客户端的请求,直到响应完成。

​ 空间:可以在请求经过的所有Servlet中访问。如果存在转发,经过的所有Servlet都可以使用。

​ 作用:就是在转发时,携带一些临时数据到另外的Servlet。

​ ServletContext对象:

​ 时间:服务器启动时创建,在服务器正常关闭时销毁。

​ 空间:当前项目下所有的Servlet都可以访问。

​ 作用:不适合存储私有的数据。更适合整个项目都需要用到的数据。

创建步骤
步骤一:定义一个要被共享的数据名称和数据参数(在数据共享定义处)
格式:自定义Context对象名.setAttribute("自定义欲共享的数据名",自定欲共享的任意类型的数据内容);
列如:

contextObj.setAttribute("测试","哈哈哈哈,这是测试context的数据共享" );

步骤二:根据被共享的数据名称来获取其参数(在数据共享获取处)
格式:Object 自定义结果接收名 = 自定义Context对象名.getAttribute("自定义欲获取的共享数据名");
列如:

String test = (String) contextObj.getAttribute("测试");

步骤三(可选):删除共享数据
格式:自定义Context对象名.removeAttribute("自定义欲删除的共享数据名");

综合应用:资源下载

待实现

参考代码:

@WebServlet("/downloadServlet") public class DownloadServlet extends
HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.获取请求参数,文件名称
String filename = request.getParameter(“filename”);
//2.使用字节输入流加载文件进内存
//2.1找到文件服务器路径
ServletContext servletContext = this.getServletContext();
String realPath = servletContext.getRealPath("/img/" + filename);
//2.2用字节流关联
FileInputStream fis = new FileInputStream(realPath);

    //3.设置response的响应头
    //3.1设置响应头类型:content-type
    String mimeType = servletContext.getMimeType(filename);//获取文件的mime类型
    response.setHeader("content-type",mimeType);
    //3.2设置响应头打开方式:content-disposition

    //解决中文文件名问题
    //1.获取user-agent请求头、
    String agent = request.getHeader("user-agent");
    //2.使用工具类方法编码文件名即可
    filename = DownLoadUtils.getFileName(agent, filename);

    response.setHeader("content-disposition","attachment;filename="+filename);
    //4.将输入流的数据写出到输出流中
    ServletOutputStream sos = response.getOutputStream();
    byte[] buff = new byte[1024 * 8];
    int len = 0;
    while((len = fis.read(buff)) != -1){
        sos.write(buff,0,len);
    }

    fis.close();


}

protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    this.doPost(request,response);
} }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值