首页 > 其他分享 >day14 --> (HTTP协议响应消息、Response对象、ServletContext对象)

day14 --> (HTTP协议响应消息、Response对象、ServletContext对象)

时间:2022-11-09 12:56:19浏览次数:48  
标签:浏览器 String -- filename day14 响应 服务器 HTTP response

HTTP协议:

1、请求消息:客户端发送给服务器端的数据

数据格式:

1.请求行

2.请求头

3.请求空行

4.请求体

2、响应消息:服务器端发送给客户端的数据

数据格式:

1.响应行

1、组成:协议 / 版本   响应状态码   状态码描述

2、响应状态码:服务器告诉客户端浏览器本次请求和响应的一个状态

状态码都是3位数字

分类:

1、1xx : 服务器接收客户端消息,但是没有接收完成,等待一段时间后,发送1xx状态码,“1开头的意思是...”

2、2xx : 成功。代表200

3、3xx : 重定向【资源跳转的一种方式】

代表:302:

例如: 浏览器 --> 访问服务器资源A,A无法成功处理,返回给浏览器服务器资源C的地址,说:“我干不了,你让C去干吧~”,并给出本次响应状态位302。然后浏览器去找C

代表:304【访问缓存】:

例如:浏览器 --> 访问服务器资源a.png,因为图片这样的信息一般不会发生变化,浏览器的缓存中会保存这张图片a.png,如果第二次浏览器依然向服务器访问a.png,服务器会告诉浏览器说:“访问缓存吧”,并给出此次访问的状态码304。从而达到缓解服务器压力的目的

4、4xx : 客户端错误

代表:404:

请求路径没有对应的资源

代表:405:

请求方式没有对应的 doGet 或者 doPost

5、5xx : 服务器错误,内部出现异常

代表:

500:服务器内部出现异常

 

2.响应头

1、格式:头名称 :值

2.常见的响应头:

1、Content - Type : 服务器告诉客户端本次响应体(HTML格式)数据格式以及编码格式

2、Content - disposition : 服务器告诉客户端以什么格式打开响应体数据

值:

in - line : 默认值,在当前页面内打开

attachment ; filename = xxx :以附件形式打开响应体。【文件下载】

3.响应空行

4.响应体

真实的,传输的数据

Response 对象

功能:设置响应消息

1. 设置响应行 :

1、格式:HTTP/1.1  200 ok

2、设置状态码:setStatus(int sc)

2.设置响应头 :

setHeader(String name, String value)

3.设置响应体 :

使用步骤:

1、获取输出流

字符输出流 : PrintWriter getWriter() 【打印流】

字节输出流 : ServletOutputStream getOutputStream() 【当作OutputStream使用】

2、使用输出流将数据输出到客户端浏览器

案例:

1.完成重定向

关键代码:

        //1.设置状态码:302
        response.setStatus(302);
        //2.设置响应头location
        response.setHeader("location","/day15/responseDemo2");

 

如果想要实现重定向的功能,设置状态码 和 设置响应头中的 location 都是固定的,只有 location 的值的有所变化的,因此以上代码可以被替换为:

response.sendRedirect("/day15/responseDemo2");

常见面试题:redirect 和 forward 的区别

重定向【redirect】的特点:

1.地址栏发生变化

2.重定向可以访问其他站点(其他服务器资源)

3.重定向是两次请求,不能使用 request 对象来共享数据

转发【forward】的特点:

1.转发地址栏路径不变

2.转发只能访问当前服务器下的资源

3.转发是一次请求

路径的写法:

1.路径分类:

1、相对路径 :通过相对路径不可以确定唯一资源

如:./index.html 【标识当前目录下】

不以斜杠开头,以 . 开头

规则:找到当前资源和目标资源之间的相对位置关系

./ : 标识当前目录,如果知识当前目录,那么 ./ 可以省略

../ : 标识上一级目录

2、【JSP常用】绝对路径:通过绝对路径可以确定唯一资源

如:http://localhost:8080/day15/responseDemo2   --> 绝对路径【省略协议、IP地址、端口号】:/day15/responseDemo2 ,以斜杠开头

规则:判断定义的路径是给 谁(浏览器 || 服务器) 用的?判断请求将来从哪发出

给浏览器用 :需要加 虚拟目录(项目的访问路径)【重定向√】

建议虚拟目录动态获取:request.getContextPath()

<a>、<form>、重定向

给服务器用: 不需要加 虚拟目录

转发路径

2.服务器输出字符数据到浏览器

步骤:

1、获取字符输出流

2、输出数据

 

 

 

 乱码问题:

1.PrintWriter pw = response.getWriter(); 获取的流的默认编码是ISO-8859-1,即GBK

2.设置改流的默认编码

3.告诉浏览器响应体使用的编码

【注意:】在获取流之前设置编码:response.setContentType("text/html;charset=utf-8");

3.服务器输出字节数据到浏览器

4.验证码

@WebServlet("/checkCodeServlet")
public class CheckCodeServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        int width = 100;
        int height = 50;
        //1、创建一个对象,在内存中的图片
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
        //2、美化图片
        //2.1 填充背景色
        Graphics graphics = image.getGraphics(); //获取画笔对象
        //设置画笔颜色
        graphics.setColor(Color.PINK);
        //填充方框背景色
        graphics.fillRect(0,0,width,height);

        //2.2画边框
        graphics.setColor(Color.BLUE);
        graphics.drawRect(0,0,width-1,height-1);

        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        Character ch = null;
        //2.3写验证码
        for (int i = 1; i <= 4; i++) {
            ch = str.charAt(random.nextInt(str.length()));
            graphics.drawString(ch+"",i*20,25);
        }
        //2.4画干扰线
        graphics.setColor(Color.GREEN);
        graphics.drawLine(1,1,30,30);

        int x1,y1,x2,y2;
        for (int i = 1; i <= 10 ; i++) {
            x1 = random.nextInt(width);
            x2 = random.nextInt(width);
            y1 = random.nextInt(height);
            y2 = random.nextInt(height);
            graphics.drawLine(x1,y1,x2,y2);
        }


        //2.3写验证码
//        graphics.drawString("A",20,25);
//        graphics.drawString("B",40,25);
//        graphics.drawString("C",60,25);
//        graphics.drawString("D",80,25);

        //3、将图片输出到页面上展示
        ImageIO.write(image,"jpg",response.getOutputStream());
    }
}
<body>
  <img id="checkCode" onclick="changeImg()" src="/day15/checkCodeServlet"/>
  <br>
  <hr>
  <a href="">看不清?换一张</a>
</body>

<script>
  function changeImg(){
    let checkCode = document.getElementById("checkCode");
    let date = new Date().getTime();//欺骗服务器这是新的请求,否则会加载缓存中的验证码,验证码不会改变
    checkCode.src = "/day15/checkCodeServlet?" + date;
  }
</script>

 

ServletContext对象

1.概念:代表整个web应用,可以和程序的容器(服务器)来通信

2.获取:

1、通过request对象获取

request.getServletContext();

2、通过HttpServlet获取

this.getServletContext();

 

 访问后控制台打印:

 

 ServletContext对象代表整个Web应用,而改Web应用只有一份,因为:两种不同的方式访问到的对象均为同一个

3.功能:

1、获取 MIME 类型:

MIME 类型:在互联网通信过程中定义的一种文件数据类型

格式:大类型 / 小类型;

例如:text / html  --> 标识这是一个纯文本的、html格式的文件

image / jpeg 

获取:String getMimeType(String file) 

 

控制台打印:

 

2、域对象 :共享数据

1.setAttribute(String name,Object value)

2.getAttribute(String name)

3.removeAttribute(String name)

注:ServletContext【谨慎使用】 对象范围:所有用户所有请求数据

先访问:/servletContextDemo3:doPost

 

    在访问: /servletContextDemo4:doPost

 

 控制台打印输出:

3、获取文件的真实路径(服务器的路径)

 

 方法【重要】:String getRealPath(String path)

 

 

 

 控制台打印:

 案例:

文件下载需求:

1、页面显示超链接

2、点击超链接后弹出下载提示框

3、完成图片文件下载

 

分析:

1.超链接指向的资源如果能够被浏览器解析,则在浏览器中展示,如果不能解析,则弹出下载提示框,不满足需求

2.任何资源都必须弹出下载提示框

3.使用响应头设置资源的打开方式:

content-disposit : attachment ; filename = xxx

 步骤:

1.定义页面,编辑超链接 href 属性,指向Servlet,传递资源名称 filename

2.定义Servlet

1.获取文件名称

2.使用字节输入流加载文件进内存进内存

3.指定 response 的响应头

4.将数据写出到 response 输出流

 问题:

中文文件名无法正常显示:

解决思路:

1.获取客户端使用的浏览器的版本信息

2.根据不同的版本信息,响应不同的数据,设置 filename 的编码方式不同

<body>
 <a href="/day15/img/natural_view.jpeg">图片</a>
<hr/>
<a href="/day15/img/video1.mp4">视频</a>
<hr color="red"/>
 <a href="/day15/downloadServlet?filename=自然风景.jpeg">图片</a>
 <hr/>
 <a href="/day15/downloadServlet?filename=video1.mp4">视频</a>
</body>

 

@WebServlet("/downloadServlet")
public class DownloadServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }

    @Override
    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);
        //用字节流关联
        FileInputStream fis = new FileInputStream(realPath);

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

        //3、设置response响应头
        //3.1设置响应头类型:content-type
        String mimeType = servletContext.getMimeType(filename);
        response.setHeader("content-type",mimeType);
        //3.2设置响应头打开方式
        response.setHeader("content-disposition","attachment;filename=" + filename);
        //4将输入流的数据写出到输出流中
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] buff = new byte[1024 * 8];
        int len = 0;
        while ((len = fis.read(buff)) != -1){
            outputStream.write(buff,0,len);
        }

    }
}

 

工具类:

//import sun.misc.BASE64Encoder; //导入BASE64Encoder报错的
import java.util.Base64; //导入此包,【从网上查资料说是JDK版本不一致,JDK9之后更新为此包,】
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

public class DownLoadUtils {

    public static String getFileName(String agent, String filename) throws UnsupportedEncodingException {
        if (agent.contains("MSIE")) {
            // IE浏览器
            filename = URLEncoder.encode(filename, "utf-8");
            filename = filename.replace("+", " ");
        } else if (agent.contains("Firefox")) {
            // 火狐浏览器
            //BASE64Encoder base64Encoder = new BASE64Encoder();
            Base64.Encoder base64 = Base64.getEncoder();
            filename = "=?utf-8?B?" + base64.encode(filename.getBytes("utf-8")) + "?=";
        } else {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
}

 

 

标签:浏览器,String,--,filename,day14,响应,服务器,HTTP,response
From: https://www.cnblogs.com/yumengqifei/p/16871764.html

相关文章

  • 关于AP的一些知识点
     FAT模式是指AP可以独立配置,有独立的管理接口,就像普通的无线AP一样;胖模式主要用于不使用交流电的小型网络。FIT模式是指AP由TP-LINKAC(无线控制器)统一控制和设置。 ......
  • thread互斥测试
    thread互斥测试编译运行附件中的代码,并说明程序的功能根据自己的理解,提交不少于3张图片代码#include<stdio.h>#include<stdlib.h>#include<pthread.h>#incl......
  • 小作文
    小作文审题书信Letter 通知Notice 海报Poster 简历Resume 假条Requesta.背景 b.体裁+内容要求(描述) c.正式/非正式+格式三段论首段1-2句a.写给熟人:首句寒暄,二句目的。......
  • CF1750题解
    A.IndirectSort首先,如果\(a_i>a_k\),\(a_i\)就会变大,而这样的操作是没有意义的.因此操作可以转换为\(\forallj,k(j<k)\),如果\(\existsi,i<j\),使得\(a[i]<=a[k]\),......
  • php 设计模式
    <?php//协程生成器函数并发classTest{publicfunctionasync(){$start=microtime(true);$url="https://money.finance.sina.com.c......
  • zookeeper启动闪退问题
    在配置zookeeper集群时,遇到启动zookeeper后几秒就闪退经过一系列疯狂查找后解决问题方法一:在zookeeper的配置文件zoo.cfg中在/zkData/installed里面查找zookeeper_serv......
  • 实验2
    1.2.2阅读材料并思考请阅读北航陈彦吉同学的这篇博客中的各参考资料,并回答如下问题:(1)回顾你过去将近3年的学习经历当初你报考的时候,是真正喜欢计算机这个专业吗?  ......
  • 网 易 云 神 评
    ......
  • 拓端tecdat|R语言代写辅导中绘制ROC曲线和PR曲线
      ROC曲线可能是评估评分分类器的预测性能的最常用的度量。预测正类(+1)和负类(-1)的分类器的混淆矩阵具有以下结构:预测/参考类+1-1+1TPFP-1FNTN这里,TP表示真阳性的数量(模型......
  • 我服了!SpringBoot升级后这服务我一个星期都没跑起来!(上)
    最近由于各方面的原因在准备升级SpringCloud和SpringBoot,经过一系列前置的调研和分析,决定把SpringBoot相关版本从2.1.6升级到2.7.5,SpringCloud相关版本从Green......