request和response简介

摘要:
Tomcat从客户端接收http请求。对于每个请求,它创建一个表示请求的请求对象和一个表示响应的响应对象。响应对象表示http响应,因此我们可以将数据输出到浏览器并找到响应对象。HTTP响应表示服务器将数据发送回浏览器。HttpServletResponse对象封装了http响应信息。响应标头位置:http://www.it315.org/index.jspServer:apachetomcatContent-编码:gzipContent长度:80内容语言:zh-cnContent类型:text/html;charset=GB2312上次修改时间:2000年7月11日星期二18:23:51GMTRefresh:1;url=http://www.it315.orgContent-Disposition:attachment ; 文件名=aaa。zipTransfer编码:chunkedSet Cookie:SS=Q0=5Lb_nQ;路径=/searchExpires:-1Cache-Control:no cachePragma:no cakeConnection:close/Keep AliveDate:Tue,11Jul200018:23:51GMResponse调用getOutputStream()方法将数据输出到浏览器。getOutputStream()方法可以使用print()或write()。他们之间有什么区别?

Tomcat收到客户端的http请求,会针对每一次请求,分别创建一个代表请求的request对象、和代表响应的response对象。

既然request对象代表http请求,那么我们获取浏览器提交过来的数据,找request对象即可。response对象代表http响应,那么我们向浏览器输出数据,找response对象即可。

http响应由状态行、实体内容、消息头、一个空行组成。一个HTTP响应代表着服务器向浏览器回送数据,HttpServletResponse对象就封装了http响应的信息。

一个完整http请求应该包含三个部分:

  1. 请求行【描述客户端的请求方式请求的资源名称,以及使用的HTTP协议版本号

  2. 多个消息头【描述客户端请求哪台主机,以及客户端的一些环境信息等】

  3. 一个空行

请求行

请求行:GET /java.html HTTP/1.1

请求行中的GET称之为请求方式,请求方式有:POST,GET,HEAD,OPTIONS,DELETE,TRACE,PUT。

请求头

  • Accept: text/html,image/* 【浏览器告诉服务器,它支持的数据类型】

  • Accept-Charset: ISO-8859-1 【浏览器告诉服务器,它支持哪种字符集

  • Accept-Encoding: gzip,compress 【浏览器告诉服务器,它支持的压缩格式

  • Accept-Language: en-us,zh-cn 【浏览器告诉服务器,它的语言环境】

  • Host: www.it315.org:80【浏览器告诉服务器,它的想访问哪台主机】

  • If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT【浏览器告诉服务器,缓存数据的时间】

  • Referer: http://www.it315.org/index.jsp【浏览器告诉服务器,客户机是从那个页面来的---反盗链

  • 8.User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)【浏览器告诉服务器,浏览器的内核是什么】

  • Cookie【浏览器告诉服务器,带来的Cookie是什么

  • Connection: close/Keep-Alive 【浏览器告诉服务器,请求完后是断开链接还是保持链接】

  • Date: Tue, 11 Jul 2000 18:23:51 GMT【浏览器告诉服务器,请求的时间】

一个完整的HTTP响应应该包含四个部分:

  1. 一个状态行【用于描述服务器对请求的处理结果。

  2. 多个消息头【用于描述服务器的基本信息,以及数据的描述,服务器通过这些数据的描述信息,可以通知客户端如何处理等一会儿它回送的数据

  3. 一个空行

  4. 实体内容【服务器向客户端回送的数据

状态行

格式: HTTP版本号 状态码 原因叙述

状态行:HTTP/1.1 200 OK

状态码用于表示服务器对请求的处理结果,它是一个三位的十进制数。响应状态码分为5类。

响应头

  • Location: http://www.it315.org/index.jsp 【服务器告诉浏览器要跳转到哪个页面

  • Server:apache tomcat【服务器告诉浏览器,服务器的型号是什么】

  • Content-Encoding: gzip 【服务器告诉浏览器数据压缩的格式

  • Content-Length: 80 【服务器告诉浏览器回送数据的长度】

  • Content-Language: zh-cn 【服务器告诉浏览器,服务器的语言环境】

  • Content-Type: text/html; charset=GB2312 【服务器告诉浏览器,回送数据的类型

  • Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT【服务器告诉浏览器该资源上次更新时间】

  • Refresh: 1;url=http://www.it315.org【服务器告诉浏览器要定时刷新

  • Content-Disposition: attachment; filename=aaa.zip【服务器告诉浏览器以下载方式打开数据

  • Transfer-Encoding: chunked 【服务器告诉浏览器数据以分块方式回送】

  • Set-Cookie:SS=Q0=5Lb_nQ; path=/search【服务器告诉浏览器要保存Cookie

  • Expires: -1【服务器告诉浏览器不要设置缓存

  • Cache-Control: no-cache 【服务器告诉浏览器不要设置缓存

  • Pragma: no-cache 【服务器告诉浏览器不要设置缓存

  • Connection: close/Keep-Alive 【服务器告诉浏览器连接方式】

  • Date: Tue, 11 Jul 2000 18:23:51 GMT【服务器告诉浏览器回送数据的时间】

response调用getOutputStream()方法向浏览器输出数据,getOutputStream()方法可以使用print()也可以使用write()它们有什么区别呢

request和response简介第1张

  • 为什么会出现异常呢?在io中我们学过,outputStream是输出二进制数据的print()方法接收了一个字符串print()方法要把“中国”改成二进制数据,Tomcat使用IOS 8859-1编码对其进行转换,“中国”根本对ISO 8859-1编码不支持。所以出现了异常

  • 我们再看看write()方法

    response.getOutputStream().write("aaa".getBytes());//正常显示
response.getOutputStream().write("你好呀我是中国".getBytes());//正常显示
  • 为什么使用write()方法能够正常向浏览器输出中文呢?"你好呀我是中国".getBytes()这句代码在转成byte[]数组的时候使用平台默认字符集(某中文编码),而浏览器正好编码字符集也是某中文编码,所以中文可以正常显示出来。

  • 但是,程序要实现通用性,应该使用的是UTF-8编码,我们在字符串转换成字节数组时指定UTF-8编码,看看会怎么样。

   response.getOutputStream().write("你好呀我是中国".getBytes("UTF-8"));//乱码了,乱不乱码是跟每个电脑的字符集息息相关的,不同电脑,可能显示结果不一样。
  • 为什么它变成了乱码呢?原因是这样的:我在向服务器输出的中文是UTF-8编码的,而浏览器采用的是GBK,GBK想显示UTF-8的中文数据,不乱码才怪呢

  • 既然如此,我将浏览器的编码改成UTF-8试试。
  • 乱码问题又解决了。可是,每次编写UTF-8程序时都要去网页上改编码格式吗?这样明显不可能的
  • 既然HTTP响应有对浏览器说明回送数据是什么类型的消息头,那么HttpServletResponse对象就应该有相对应的方法告诉浏览器回送的数据编码格式是什么
  • 于是乎就去查找Servlet API,找到了设置消息头的方法
  •     //设置头信息,告诉浏览器我回送的数据编码是utf-8的,浏览器会自动拿utf-8解码
    response.setHeader("Content-Type", "text/html;charset=UTF-8");
    response.getOutputStream().write("你好呀我是中国".getBytes("UTF-8"));
  • 浏览器在显示数据时,自动把页面的编码格式置换成UTF-8,乱码问题也解决了
  • 另外,除了使用HttpServletResponse对象设置消息头的方法,我可以使用html的标签模拟一个http消息头
  • 下面是代码:
  • //获取到servletOutputStream对象
  • ServletOutputStream servletOutputStream = response.getOutputStream();
    //使用meta标签模拟http消息头,告诉浏览器回送数据的编码和格式
    servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes());
    servletOutputStream.write("我是中国".getBytes("UTF-8"));
  • 对于getWriter()方法而言,是Writer的子类,那么只能向浏览器输出字符数据,不能输出二进制数据

  • 使用getWriter()方法输出中文数据,代码如下:

    //获取到printWriter对象
PrintWriter printWriter = response.getWriter();
printWriter.write("看完博客点赞!");;//乱码了
  • 为什么出现乱码了呢?由于Tomcat是外国人的写,Tomcat默认的编码是ISO 8859-1即(response.getCharacterEncoding()是iso-8859-1),当我们输出中文数据的时候,Tomcat会依据ISO 8859-1码表给我们的数据编码,中文不支持这个码表呀,所以出现了乱码(不识别的话就显示问号)

  • 既然如此,我设置一下编码不就好了吗,代码如下:

    //原本是ISO 8859-1的编码,我设置成UTF-8
response.setCharacterEncoding("UTF-8");
//获取到printWriter对象
PrintWriter printWriter = response.getWriter();
printWriter.write("看完博客点赞!");//乱码了
  • 为什么乱码问题还没有解决?细心的朋友会发现,我只是在中文转换的时候把码表设置成UTF-8,但是浏览器未必是使用UTF-8码表来显示数据的呀

  • 好的,我们来看看浏览器的编码格式,果然,浏览器使用GB2312显示UTF-8的数据,不乱码才怪呢

  • 这个问题我们在上面已经是有两种方法解决了【使用标签模拟消息头、设置消息头】,Servlet还提供了一个方法给我们

    //设置浏览器用UTF-8编码显示数据
response.setContentType("text/html;charset=UTF-8");
  • 既然Servlet有那么多方法解决乱码问题,是不是有一种是最简便的呢?没错!下面这个方法是最简便的,它不仅设置浏览器用UTF-8显示数据,内部还把中文转码的码表设置成UTF-8了,也就是说response.setContentType("text/html;charset=UTF-8");response.setCharacterEncoding("UTF-8")的事情也干了!

  • 使用getWriter()显示中文数据,只需要一个方法就搞掂了!

    //设置浏览器用UTF-8编码显示数据,
response.setContentType("text/html;charset=UTF-8");
//获取到printWriter对象
PrintWriter printWriter = response.getWriter();
printWriter.write("看完博客点赞!");
response应用2-实现文件下载
request和response简介第2张

既然浏览器发送所有的请求都是去找Servlet的话,那么我就写一个Servlet,当别人访问我这个Servlet的时候,它们就可以下载我这个图片了。

  • java的文件上传下载都是通过io流来完成的,既然要下载图片,首先要能够读取到它

      //获取到资源的路径
        String path = this.getServletContext().getRealPath("/download/1.png");

        //读取资源
        FileInputStream fileInputStream = newFileInputStream(path);

        //获取到文件名,路径在电脑上保存是\形式的。
        String fileName = path.substring(path.lastIndexOf("\") + 1);
  • 告诉浏览器,我要下载这个文件

   //设置消息头,告诉浏览器,我要下载1.png这个图片
        response.setHeader("Content-Disposition", "attachment; filename="+fileName);
  • 将读取到的内容回送给浏览器

        //把读取到的资源写给浏览器
        int len = 0;
        byte[] bytes = new byte[1024];
        ServletOutputStream servletOutputStream =response.getOutputStream();

        while ((len = fileInputStream.read(bytes)) > 0) {
            servletOutputStream.write(bytes, 0, len);
        }

        //关闭资源
servletOutputStream.close();
        fileInputStream.close();

request和response简介第3张

request和response简介第4张

  • 为了解决文件名乱码,我们要进行URL编码,代码如下:

  response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));

应用3-实现自动刷新

以规定的时间让页面刷新,更新资源
让浏览器实现自动刷新,那肯定又是修改消息头了。
  //每3秒自动刷新网页一次
        response.setHeader("Refresh", "3");
为了更好的看效果,我们加入时间值进去
   response.getWriter().write("time is :" + System.currentTimeMillis());
我们登陆完网站,很多时候都会看见【登陆成功,3秒后自动跳转….】,其实这个就是用Refresh来完成的。
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("3秒后跳转页面.....");

        //三秒后跳转到index.jsp页面去,web应用的映射路径我设置成/,url没有写上应用名
        response.setHeader("Refresh", "3;url='/index.jsp'");

应用4-设置缓存

浏览器本身就存在着缓存机制,当我第一次访问index.jsp时,浏览器向服务器发了两次请求【一个是网页的,一个是图片的】

当我第二次访问index.jsp的时候,浏览器将图片缓存起来了!图片不是重新加载的,是从缓存里面取出来的

像股票类型的网页是不能取缓存的数据的,数据都是要不断更新的。下面我就禁止缓存的功能

        //浏览器有三消息头设置缓存,为了兼容性!将三个消息头都设置了
        response.setDateHeader("Expires", -1);
        response.setHeader("Cache-Control","no-cache");
        response.setHeader("Pragma", "no-cache");


        //这里为了看效果
        PrintWriter printWriter =response.getWriter();
        printWriter.print("你好啊" + new Date().toString());

如果页面有些数据不长期更新,你就将它设置成缓存,这样可以提高服务器的性能

应用5-实现数据压缩

网页上的信息量是很大的,如果不将数据压缩再回送给浏览器,这样就十分耗费流量

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

        String ss = "fsdfhsdfhuisdhfusdhfuids" +
                "fsdfdsfsdfsdfdsfdafdsfhsdjfhsdjkfhkjds" +
                "fdsfjdslkfjsldkfjsdlkfjsdkfsdjkff" +
                "fsjdfjdsklfjdsklfjkldsfjlksdjflksdjflkds" +
                "dsjfklsdjflsdjfkldsfkjsdkfjsldkfjsdlfk" +
                "fdsjlkfjdslkfjsdlkfjlkasjflk";
        response.getWriter().write("原来的长度是:"+ss.getBytes().length+"</br>");

        //输出给浏览器
        response.getWriter().write(ss);
  • 压缩的原理是什么?我们知道getOutputStream()和getWriter()都是直接把数据输出给浏览器的。现在我要做的就是让数据不直接输出给浏览器,先让我压缩了,再输出给浏览器java提供了GZIP压缩类给我们

  • 就让我们使用GZIP类来对数据压缩吧

 //GZIP的构造方法需要一个OutputStream子类对象,究竟哪个对象适合,我们看下write()方法
        GZIPOutputStream gzipOutputStream = newGZIPOutputStream();

        //查看了下API,write()接收的是byte[]类型的。
        gzipOutputStream.write();
  • 于是我就在构造函数上传递个ByteArrayOutputStream给它

    //既然是byte[]类型,那么我就给他一个ByteArrayOutputStream
        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new ByteArrayOutputStream());
  • 而用GZIPOutputStream写数据的时候,是把数据写到ByteArrayOutputStream上的,等会还要把数据取出来,再写给浏览器,于是就不能以匿名内部类的方式给GZIPOutputStream,必须把ByteArrayOutputStream定义出来

  •   //创建GZIPOutputStream对象,给予它ByteArrayOutputStream
            ByteArrayOutputStream byteArrayOutputStream = newByteArrayOutputStream();
            GZIPOutputStream gzipOutputStream = newGZIPOutputStream(byteArrayOutputStream);
    
            //GZIP对数据压缩,GZIP写入的数据是保存在byteArrayOutputStream上的
    gzipOutputStream.write(ss.getBytes());
    
            //gzipOutputStream有缓冲,把缓冲清了,并顺便关闭流
            gzipOutputStream.close();
  把压缩后的数据取出来,写给浏览器
          //将压缩的数据取出来
        byte[] bytes =byteArrayOutputStream.toByteArray();

        //将压缩的数据写给浏览器
        response.getOutputStream().write(bytes);//浏览器显示乱码
  • 数据的确是压缩了,然而,为什么又乱码了啊?很简单,既然你压缩了数据,你写给浏览器,浏览器是不知道你这是压缩后的数据,它是以正常的方式打开数据的。这当然造成乱码啦!,现在我要告诉浏览器我这是压缩数据

  //告诉浏览器这是gzip压缩的数据
        response.setHeader("Content-Encoding","gzip");

        //再将压缩的数据写给浏览器
        response.getOutputStream().write(bytes);

应用6-生成随机图片

生成随机图片这是非常常见的。在我们登陆的时候经常要写验证码,而那些验证码是一张图片,就是通过HttpServletResponse写给浏览器的。

  • 要生成一张图片,java提供了BufferedImage类供我们使用

        //在内存中生成一张图片,宽为80,高为20,类型是RGB
        BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB);

        //获取到这张图片
        Graphics graphics =bufferedImage.getGraphics();

        //往图片设置颜色和字体
graphics.setColor(Color.BLUE);
        graphics.setFont(new Font(null, Font.BOLD, 20));

        //往图片上写数据,先写个12345,横坐标是0,纵坐标是20【高度】
        graphics.drawString("12345", 0, 20);
  • 好的,现在我们在内存中创建了一张图片,并写上了12345。接着,我们要把图片写给浏览器了把图片写给浏览器,java又提供了图片流【ImageIO】给我们使用

   //要往浏览器写一张图片,那要告诉浏览器回送的类型是一张图片
        response.setHeader("ContentType", "jpeg");

        //java提供了图片流给我们使用,这是一个工具类
        //把图片传进去,类型是jpg,写给浏览器
        ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
  • 好的,我们的图片数字不可能是人工写的,数字应该是随机产生的!这个就简单了。现在我要生成7位的随机数,生成随机数的方法如下

  privateString makeNum() {

        Random random = newRandom();

        //这样就会生成0-7位的随机数,现在问题又来了,如果随机数不够7位呢?如果不够7位,我们加到7位就行了
        int anInt = random.nextInt(9999999);

        //将数字转成是字符串
        String num =String.valueOf(anInt);

        //判断位数有多少个,不够就加
        StringBuffer stringBuffer = newStringBuffer();
        for (int i = 0; i < 7 - num.length(); i++) {
            stringBuffer.append("0");
        }

        returnstringBuffer.append(num).toString();

    }

应用7-重定向跳转

什么是重定向跳转呢?点击一个超链接,通知浏览器跳转到另外的一个页面就叫重定向跳转。是通知浏览器去跳转,这很重要。页面之间的跳转有两种方式:重定向和转发,至于什么时候用重定向,什么用转发,我在讲完HttpServletRequest对象的时候会详细说明。

//重定向到index.jsp页面
        response.sendRedirect("/zhongfucheng/index.jsp");

重定向是通过302状态码和跳转地址实现的。于是乎,我们设置http消息头就可以实现重定向跳转

        //设置状态码是302
        response.setStatus(302);

        //HttpServletResponse把常用的状态码封装成静态常量了,所以我们可以使用SC_MOVED_TEMPORARILY代表着302
response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);

        //跳转的地址是index.jsp页面
        response.setHeader("Location", "/zhongfucheng/index.jsp");
  • 其实sendRedirect()方法就是对setStatus()和setHeader()进行封装,原理就是setStatus()和setHeader()

最后再说下getWriter和getOutputStream细节
  1. getWriter()和getOutputStream()两个方法不能同时调用。如果同时调用就会出现异常

  2. Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎从response里面获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端

  3. Servlet的serice()方法结束后【也就是doPost()或者doGet()结束后】,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象.

免责声明:文章转载自《request和response简介》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇ASP.net MVC、Extjs多级目录(理论上可以无限级、非递归)treepanel显示和数据库(多级目录)存储结构的设计(上篇)nginx在mac下的安装与基本操作下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Ext.js弹窗上传文件

1.构建上传组件 var fileUpload = new Ext.FormPanel({ id:'fileUpload', frame:true, fileUpload:true, items:[{ xtype: 'filefield',...

NODE_ENV判断node服务器环境的设置

build->webpack.sit.conf.js 拷贝webpack.prod.conf.js,新建webpack.sit.conf.js、webpack.uait.conf.js,根据环境修改env的引入文件 config->sit.env.js build->bulid.js src -> config文件夹 -&...

服务器常用的状态码

常见HTTP状态码 Type Reason-phrase Note 1XX Informational 信息性状态码,表示接受的请求正在处理 2XX Success 成功状态码,表示请求正常处理完毕 3XX Redirection...

Nginx关闭危险的HTTP请求

在 server { listen 80; server_name 127.0.0.1 www.baidu.com; 下一行添加一下代码即可关闭除GET|POST|HEAD外的请求方式。 if ($request_method !~* GET|POST|HEAD) {...

kafka 基础知识梳理-kafka是一种高吞吐量的分布式发布订阅消息系统

一、kafka 简介 今社会各种应用系统诸如商业、社交、搜索、浏览等像信息工厂一样不断的生产出各种信息,在大数据时代,我们面临如下几个挑战: 如何收集这些巨大的信息 如何分析它 如何及时做到如上两点 以上几个挑战形成了一个业务需求模型,即生产者生产(produce)各种信息,消费者消费(consume)(处理分析)这些信息,而在生产者与消费者之间,需要...

jquery的ajax()函数传值中文乱码解决方法介绍

代码如下: $.ajax({   dataType : ‘json',type : ‘POST',url : ‘http://localhost/test/test.do',data : {id: 1, type: ‘商品'},success : function(data){ } } ); 问题: 提交后后台action程序时,取到的type是乱码...