Response笔记

今日内容

1. HTTP协议:响应消息
2. Response对象
3. ServletContext对象

HTTP协议:

  1. 请求消息:
  • 数据格式
    1. 请求行
    2. 请求头
    3. 空行
    4. 请求体
  1. 响应消息
  • 数据格式

    1. 响应行

    2. 组成:HTTP/1.1 200 OK—> 协议/版本 响应的状态码 状态码的描述

    3. 响应的状态码:服务器告诉浏览器响应的状态

    4. 状态码都是3位数字

    5. 分类

    6. 1XX:服务器接收到客户端消息,但没有接收完成,过一段时间,会给你回复1XX状态码

    7. 2XX:这一类型的状态码,代表请求已成功被服务器接收、理解、并接受。200 OK

    8. 3XX: 重定向,代表:(302),304(访问缓存)

    9. 4XX:客户端错误(从客户端找问题)

        * 代表
          * 404 :Not Found(请求的资源未找到)
          * 405 :Method Not Allowed
      5. ==5XX :服务器错误。代表:500(服务器内部出现错误)==
    
    1. 响应头

    2. 格式:头名称:值

    3. 常见的响应头:

    4. Content-Type:服务器告诉浏览器收到了什么格式的数据

      text/html;charset=utf-8、jpg、png、、、

      详细介绍

    5. Content-disposition: 服务器告诉浏览器以什么格式打开响应体数据

    6. 值:

        * in-line:默认值,在当前页面打开
        * attachment; filename="xxx":以附件的形式打开响应体。文件下载
    
    1. 响应空行
    2. 响应体:传输数据
  • ​ 响应数据格式

		HTTP/1.1 200 OK
		Content-Type: text/html;charset=UTF-8
		Transfer-Encoding: chunked
		Connection: keep-alive
		Server: nginx

		<!DOCTYPE html>
		<html>
			<head>
				<title>搜狐</title>
				<meta name="Keywords" content="搜狐,门户网站,新媒体,网络媒体,新闻,财经,体育,娱乐,时尚,汽车,房产,科技,图片,论坛,微博,博客,视频,电影,电视剧"/>		
				<link href="//statics.itc.cn/web/v3/static/css/main-93133d8821.css" rel="stylesheet"/>
				<script>
					//  加载监控代码
				</script>
				<!--[if lt IE 9]>
				<script src="//statics.itc.cn/web/v3/static/js/es5-shim-08e41cfc3e.min.js"></script>
			</head>

			<body class="sohu-index-v3" data-spm="home">
				<header class="sohu-head">
					<div class="area sohu-head-box">
						<div class="right head-right">
						
						</div>
					</div>
				</header><div class="sohu-ph" id="sohuTopc" style="display:none;">
				<div class="ph-link">
			</body>
		</html>

Response对象

  • 功能: 设置响应消息

    1. 设置响应行

    2. 组成:HTTP/1.1 200 OK 协议/版本 响应的状态码 状态码的描述

    3. 设置响应的状态码:
      setStatus(int sc)

    4. 设置响应头:
      void setHeader(String name,String value)

    编码

    1. 设置Content-Type
      // 1. 第一种方式
    ```java
    //作用:设置流的编码,也就是writer()里面数据的编码方式 
    response.setCharacterEncoding("UTF-8");  
    //浏览器收到我得文档之后,采用什么编码显示
      response.setHeader("Content-Type","text/html;charset=utf-8"); 
      response.getWriter().Write("中文");
    ```
    
    //2. 第二种方式: 
    
    setContentType 直接代替第一种方式中的两句
    
    ```java
    //两个作用:一是规定流的以什么方式编码,二是规定浏览器以什么方式解码
    response.setContentType("text/html;charset=utf-8");
    response.getWriter().Write("中文");
    ```
    

2. 设置流的打开方式:
  * 按照文件下载方式打开
    response.setHeader("Content-disposition","attachment; filename=aa.jpg");

    > 会跳出一个窗口让你下载文件。
  1. 设置响应体:

响应体就是返回给客户端浏览器的东西。可以是一个页面,也可以是一个字符串;当然,你的

​ 页面也是使用字符串拼接的。

  • 使用步骤

    1. 获取输出流
    方式1. :获取**字符**输出流
       PrintWriter getWriter()
    方式2.:获取**字节**输出流
       ServletOutputStream getOutputStream()
    
    1. 使用输出流
    方式一:字符输出流--getWriter().Write();
    > 字符流处理不了图片等文件。
    方式二:字节输出流--getOutputStream().Write();
    

字节流是万能的,全部都可以给你处理。
```

  1. 重定向与转发
  • 重定向:response.sendRedirect(ctxPath + “/responseDemo2”);

    重定向在客户端发生,所以必须带虚拟路径。

  • 转发:通过request获取请求转发对象:
    RequestDispatcher requestDispatcher = request.getRequestDispatcher(String path);
    requestDispatcher.forward(request,response);

    转发在服务器内部发生,默认带有虚拟路径

  • 对比:
    转发是一次请求,重定向是新的请求
    转发可以使用request传递参数
    重定向不可以使用request域传递参数
    转发地址栏不发生改变
    重定向地址栏转向新地址

  1. 服务器输出字符数据到浏览器
  • 步骤:

    1. 获取字符输出流
    2. 输出数据
  • 注意:

    • 乱码问题:

      1. PrintWriter pw = response.getWriter();获取的流的默认编码是ISO-8859-1
      2. 设置该流的默认编码
      3. 告诉浏览器响应体使用的编码

      //简单的形式,设置编码,是在获取流之前设置
      response.setContentType(“text/html;charset=utf-8”);

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

    • 步骤:
      1. 获取字节输出流
      2. 输出数据

    * 注意:

    ​ * 乱码问题:

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

    ​ 2. 设置该流的默认编码

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

    //简单的形式,设置编码,是在获取流之前设置

    ​ response.setContentType(“text/html;charset=utf-8”);

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

    ​ * 步骤:

    1. 获取字节输出流

    2. 输出数据

    1. 验证码
    1. 本质:图片,但图片是动态生成的

    2. 目的:防止恶意攻击

路径问题:

相对路径:

通过相对路径不可以确定唯一资源
两个资源的访问路径的相对,不是你在创建项目的时候文件的相对位置。

也就是说,并不是根据你眼睛看到的文件的位置在哪肉眼判断谁相对谁绝对,而是根据地址栏你访问的路径间具体的关系判断。

如下:

http://localhost:8080/day14_response/pathdemo.html
http://localhost:8080/day14_response/responseDemo5?color=aa

上面两个地址,pathdemo.html是一个页面,responseDemo5?color=aa是一个servlet;

​ 我告诉你,他俩是相对路径。

  • 如:./index.html
  • 不以/开头,以.开头路径
  • 规则:找到当前资源和目标资源之间的相对位置关系
    • ./:当前目录,如果默认不写也是当前目录如:./a.jpg == a.jpg
    • …/:前进一级目录

绝对路径:

通过绝对路径可以确定唯一资源

  • 如:http://localhost/day15/responseDemo2 /day15/responseDemo2
  • 以/开头的路径
  • 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
    • 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
      • 建议虚拟目录动态获取:request.getContextPath()
      • , 重定向…
    • 给服务器使用:不需要加虚拟目录
      • 转发路径

区分/和./

从客户端浏览器出发:

/ 代表根目录host,host指的是—http://localhost:8080/; -------------/是绝对路径,后面不要忘了加虚拟路径

./ 代表的是当前目录。 ---------------./是相对路径

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>路径问题</title>
</head>
<body>
    <!--相对路径-->
    <div>相对路径</div>
    <a href="test.html">test.html</a>
    <a href="./index.jsp">index.jsp</a>
    <a href="responseDemo5?color=aa">responseDemo5</a>

    
    
    
    <!--绝对路径-->
    <!--http://localhost:8080/context/-->
    <hr>
    <div>绝对路径</div>
    <div>在客户端(浏览器端)直接写/是只到host的根,到不了虚拟路径的根</div>
    <div>错误的</div>
    <a href="/index.jsp">index.jsp</a>
    <hr>
    <div>正确的,可以认为 /day14_response/index.jsp </div>
    <div>是http://localhost:8080/day14_response/index.jsp 的简写</div>
    <a href="/day14_response/index.jsp">index.jsp</a>
    <a href="http://localhost:8080/day14_response/index.jsp">index.jsp</a>

    <hr>
    <div>服务器端</div>
    <a href="/day14_response/responseDemo7">demo7</a>

</body>
</html>

前台标签请求问题

前台标签如:a标签的href属性、img标签的src属性等,

不仅仅可以指向某个资源—href的跳转页面、src的图片;

还可以向后台发送请求。

img

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>验证码</title>
    <script type="text/javascript">
        window.onload = function (ev) {
            //1.获取图片对象
            var img = document.getElementById("checkCode");
            //2. 添加点击事件
            img.onclick = function (ev2) {
                // img.src="img/eg_tulip.jpg";

                //3.解决缓存的问题
                var dt = new Date().getTime();
                //4. 动态生成图片,  向后台发送请求
                img.src = "/day14_response/responseDemo9?" + dt;
            }
        }

    </script>
</head>
<body>
    <img id="checkCode" src="/day14_response/responseDemo9" helo="hello"/>
    <a id="change" href="">看不清楚换一张?</a>

</body>
</html>

img.src = “/day14_response/responseDemo9?” + dt;

这是向后台发送请求,请求中带着value,且这个value是时间,

时间是一定不同的,这才能保证每一次请求是新发的,要不然浏览器只是从内存里面读取;

浏览器每次从内存里面读取的话,我们的图片验证码每次点击更换发现都是一样的。

@WebServlet("/responseDemo9")
public class CheckCodeServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
//        ImageIO.write(image,"jpg",response.getOutputStream());

        int width = 100;
        int height = 50;

        //1.创建一对象,在内存中图片(验证码图片对象)
        BufferedImage image = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);


        //2.美化图片
        //2.1 填充背景色
        Graphics g = image.getGraphics();//画笔对象
        g.setColor(Color.PINK);//设置画笔颜色
        g.fillRect(0,0,width,height);

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

        String str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz0123456789";
        //生成随机角标
        Random ran = new Random();

        for (int i = 1; i <= 4; i++) {
            int index = ran.nextInt(str.length());
            //获取字符
            char ch = str.charAt(index);//随机字符
            //2.3写验证码
            g.drawString(ch+"",width/5*i,height/2);
        }


        //2.4画干扰线
        g.setColor(Color.GREEN);

        //随机生成坐标点

        for (int i = 0; i < 10; i++) {
            int x1 = ran.nextInt(width);
            int x2 = ran.nextInt(width);
            int y1 = ran.nextInt(height);
            int y2 = ran.nextInt(height);
            g.drawLine(x1,y1,x2,y2);
        }


        //3.将图片输出到页面展示。 字节流返回给前台。
        //  ImageIO是专门处理图片的类。
        ImageIO.write(image,"jpg",response.getOutputStream());
    }

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

ImageIO.write(image,“jpg”,response.getOutputStream());

以流的方式返回给前台。

ServletContext对象

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

  2. 获取:

​ 1. 通过request对象获取

​ ServletContext servletContext = request.getServletContext();

​ 2. 通过HttpServlet对象获取

​ ServletContext servletContext1 = this.getServletContext();

1.域对象

​ 1.setAttribute(String name,Object value)

​ 2. getAttribute(String name)

​ 3. removeAttribute(String name)

​ * 所有用户的所有请求

2. 获取真实文件的路径

  1. 方法:getRealPath(String path)

    获取文件在真实电脑上面的位置。

    url是获取当前域名:localhost:8080;

    contextPath()是获取虚拟路径。

    servletPath()是获取当前请求访问路径。

在这里插入图片描述

@WebServlet("/servletContextDemo3")
public class ServletContextDemo3 extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //我们来找一下虚拟路径对应的真的电脑上的文件路径
        ServletContext servletContext = this.getServletContext();
        //后台的“/”的后面默认会有虚拟路径。
        System.out.println(servletContext.getRealPath("/"));  //D:\EasyTrain\javaWeb\day14_Response\code\day14_response\out\artifacts\day14_response_war_exploded

     
        // 其实/aa.txt == localhost:8080/虚拟路径/aa.txt
        System.out.println(servletContext.getRealPath("/aa.txt"));
        System.out.println(servletContext.getRealPath("/WEB-INF/bb.txt"));
        System.out.println(servletContext.getRealPath("/WEB-INF/classes/cc.txt"));

    }

在后台,/后面自动会带上虚拟路径

getRealPath(“/a.txt”)其实就是localhost:8080/虚拟路径/a.txt在真实电脑上面的位置。

getRealPath(“/WEB-INF/bb.txt”)其实就是localhost:8080/虚拟路径/WEB-INF/bb.txt在真实电脑上面的位置。

但是,注意,WEB-INF/目录只能在后台访问,你在前台访问WEB-INF/是访问不了的。

2.获取MIME类型

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

​```java

@WebServlet("/servletContextDemo4")
public class ServletContextDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//我们来找一下虚拟路径对应的真的电脑上的文件路径
ServletContext servletContext = this.getServletContext();

    //获取MIME类型
    System.out.println(servletContext.getMimeType("aa.jpg"));
    System.out.println(servletContext.getMimeType("aa.mp4"));


}
​```

3.文件下载的功能

WEB-INF在前台是不能访问的。只能在后台访问。

  1. 页面显示超链接

  2. 点击超链接提示下载

  3. 保存完成文件的下载

​ * 分析:

​ \1. 超链接指向一个程序

​ \2. 点击超链接,使用字节流的方式返回数据

​ \3. 使用响应头设置资源的打开类型:

​ * content-disposition:attachment;filename=xxx

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>下载</title>
</head>
<body>
    <!--超链接,路径跳转-->
    <a href="img/img1.jpg">图片</a>
    <div>HTTP Status 404 – Not Found</div>
    <!--WEB-INF  前台是不能访问他下面的文件的-->
    <a href="/day14_response/WEB-INF/bb.txt">bb</a>

    <hr>
    <!--前台href像后台发请求, 带着参数过去-->
    <a href="/day14_response/downloadDemo1?filename=中文abc国家.jpg">下载</a>

</body>
</html>
@WebServlet("/downloadDemo1")
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");
        // 找到真实路径
        String realPath = this.getServletContext().getRealPath("/img/" + filename);

        ServletOutputStream outputStream = response.getOutputStream(); //获取字节流
        byte[] bytes = new byte[1024*8];  //缓冲区

//        for(byte i=0;i<100;i++){
//            bytes[i] =i;
//        }

        //2. 打开文件
        FileInputStream fis = new FileInputStream(realPath);

        //3. 读取字节流

        //4. 将字节流写入管道(网络),以字节流的方式返回数据

        // content-disposition:attachment;filename=?????.jpg
        // content-disposition:attachment;filename=中文服务器.jpg
//        response.setHeader("content-disposition","attachment;filename=中文服务器.jpg");
//        response.setHeader("content-disposition","attachment;filename=%e4%b8%ad%e5%9b%bd.jpg");

        //获取浏览器类型

        //把浏览器类型当做参数传给getFileName方法

        //不同的浏览器对中文文件名称的处理还不一样,需要做另外的处理
        response.setHeader("content-disposition","attachment;filename=" + getFileName("chrome",filename));


        int len;
        while((len=fis.read(bytes))!=-1){
            //返回给前台
            outputStream.write(bytes,0,len);
        }

        fis.close();
    }

    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();
            filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
        } else {
            // 其它浏览器
            filename = URLEncoder.encode(filename, "utf-8");
        }
        return filename;
    }
}

edEncodingException {
if (agent.contains(“MSIE”)) {
// IE浏览器
filename = URLEncoder.encode(filename, “utf-8”);
filename = filename.replace("+", " ");
} else if (agent.contains(“Firefox”)) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = “=?utf-8?B?” + base64Encoder.encode(filename.getBytes(“utf-8”)) + “?=”;
} else {
// 其它浏览器
filename = URLEncoder.encode(filename, “utf-8”);
}
return filename;
}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@来杯咖啡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值