Response

Response对象代表响应

响应由三部分组成:

  1. 响应行(状态码)
  2. 响应头
  3. 响应数据

用处:

  • 向客户端浏览器输出中文
  • 下载一个图片
  • 向页面中加入动态图片(验证码)
  • 控制浏览器定时刷新(使用refresh)
  • 控制浏览器缓存(使用expires)
  • 使用重定向

相关方法:

      getStatus

      setHeader

      getWrite和getOutputStream

其中写数据可以分为两种方式

  • 字节流  可以写任何格式的数据 
  • 字符流  只能写字符数据

1 如何向客户端浏览器输出中文

输出中文就涉及到编码和乱码形成的问题

不是把汉字写到客户端,而是先写到response里面

计算机或者网络之间的通信是没有汉字通信的,都是数字(二进制)通信

所以要把汉字通过一定的方式转化为数字

首先是把汉字通过编码(比如java内部的unicode编码翻译成十六进制等,然后再通过TCP/ip协议向下封装,最后转化为二进制)

1. 字节流

使用字节流,必须先把字符串转化为字节

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

        String dataString = "中国";
        OutputStream outputStream  = response.getOutputStream();
        //要以字节流输出,所以要先把汉字转化为字节
        outputStream.write(dataString.getBytes());
    }

这种方式在浏览器上是没有问题的

但是在实际开发中,为了全球通用,一般是使用UTF-8

但是如果指定传输字节格式

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

        String dataString = "中国";
        OutputStream outputStream  = response.getOutputStream();
        //指定汉字传输格式
        outputStream.write(dataString.getBytes("UTF-8"));
    }

把汉字变成字节的过程就是把从编码表上查出汉字对应的数字,然后把数字放在一个数组里面给客户机

这里查的是UTF-8编码表

那么在浏览器上就会出现乱码(即是其他的字)

原因:

  • 当把汉字定义成UTF-8时,传输的并不是汉字,而是其中对应的编码,即是数字。
  • 当把数字传给浏览器时,浏览器要进行解码,但是浏览器默认的解码方式是国标gb2312

所以会解析成其他的字

servlet写给浏览器的不是汉字中国,而是它所对应的编码

解决:

  • 在浏览器设置里面改动编码方式
  • 在服务器代码里设定浏览器的解码方式
public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        //加入响应头
        response.setHeader("Content-type", "text/html;charset=UTF-8");

        String dataString = "中国";
        OutputStream outputStream  = response.getOutputStream();
        
        outputStream.write(dataString.getBytes("UTF-8"));
    }

这样的话就没有问题了。

2. 字符流

因为汉字本身是字符串,所以用字符流会更方便一些

 直接向response内写入一个字符流就行了,同时要注意编码

response在进行字符编码的时候默认使用的是java默认的unicode编码

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

        //设置response使用的码表,以控制respose以什么码表向浏览器写出数据
        response.setCharacterEncoding("UTF-8");
        //指定浏览器以什么码表打开服务器发送来的数据
        response.setHeader("content-type","text/html;charset=UTF-8");
        
        //以上两句的设置可以用这一句代替
        //response.setContentType("text/html;charset=UTF-8");
        
        String data = "中国";
        PrintWriter out = response.getWriter();
        out.write(data);        
    }

2 如何使用response下载一个图片

public class ResponseDemo extends HttpServlet {

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

        //1.读这个文件(这个文件其实就是web里面的资源,在servlet里读的话用servletcontext,在普通类中使用类加载器)
        //2.读资源的话有两种方式,一种是把资源作为资源流输出, 一种是使用资源的绝对地址(这种方法可以得到文件的一些信息,比如文件名)
        String  path = this.getServletContext().getRealPath("/DownLoad/1.jpg");
        String filename = path.substring(path.lastIndexOf("\")+1);
        
        //通知浏览器怎么打开
        //如果下载文件是中文名称,需要使用url编码
        response.setHeader("content-disposition", "attachment;filename="+URLEncoder.encode(filename,"UTF-8"));
        InputStream in= null;
        OutputStream out= null;
        try{
            in = new FileInputStream(path);
            int len = 0;
            byte buffer[] = new byte[1024];
            out = response.getOutputStream();
            while((len = in.read(buffer))>0){
                out.write(buffer,0,len);
            }
        }finally{
            if(in !=null){
                try{
                   in.close();
                }catch(Exception e){
                   e.printStackTrace();
                }
            }
            if(out !=null){
                try{
                   out.close();
                }catch(Exception e){
                   e.printStackTrace();
                }
            }
        }
        
        
    }

3. 如何向页面中加入动态图片(验证码)

//构建一副图片(含有汉字的验证码图片)
public class ResponseDemo2 extends HttpServlet {
    
//定义图片的长和宽
public static final int WIDTH = 200; public static final int HEIGTH = 50; public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { //1.首先在内存中构造一个图片 bufferimage 内存中的一张图片 //2.构造图象 //3.把内存中的图像输出到浏览器 //在内存中构建图像 BufferedImage image = new BufferedImage(WIDTH,HEIGTH ,BufferedImage.TYPE_INT_BGR); //向图像中写数据,拿到这个图像 Graphics g = image.getGraphics(); //1.设置背景色 setBackGround(g); //2.设置边框 setBorder(g); //3.画干扰线 drawRandomLine(g); //4.写随机数 //Graphics2D 可以旋转字符 drawRandomNumber((Graphics2D)g); //把图像写给浏览器,通过severlet的输出流 //先通知浏览器以什么格式打开,否则默认以文本打开 response.setContentType("image/jpeg"); //同时控制浏览器不能存放图片的缓存,不然刷新浏览器不能更新图片 response.setHeader("Cache-Control", "no-cache"); response.setHeader("Pragma", "no-cache");


//向浏览器中输出图片 ImageIO.write(image,
"jpg", response.getOutputStream()); } private void drawRandomNumber(Graphics2D g) { g.setColor(Color.RED); g.setFont(new Font("宋体",Font.BOLD, 20)); //汉字区间 ,java使用的是unicode码表,汉字在内存中存的不是汉字,都是它所对应的码值 //所有汉字都在unicode码表的4e00到9fa5
//用正则表达式测试一个字符是不是汉字 [^u4e00-u9fa5] //常用汉字 String base = "u7684u4e00u662fu4e86u6211u4e0du4ebau5728u4ed6u6709u8fd9u4e2au4e0au4eecu6765u5230u65f6u5927u5730u4e3au5b50u4e2du4f60u8bf4u751fu56fdu5e74u7740u5c31u90a3u548cu8981u5979u51fau4e5fu5f97u91ccu540eu81eau4ee5u4f1au5bb6u53efu4e0bu800cu8fc7u5929u53bbu80fdu5bf9u5c0fu591au7136u4e8eu5fc3u5b66u4e48u4e4bu90fdu597du770bu8d77u53d1u5f53u6ca1u6210u53eau5982u4e8bu628au8fd8u7528u7b2cu6837u9053u60f3u4f5cu79cdu5f00u7f8eu603bu4eceu65e0u60c5u5df1u9762u6700u5973u4f46u73b0u524du4e9bu6240u540cu65e5u624bu53c8u884cu610fu52a8u65b9u671fu5b83u5934u7ecfu957fu513fu56deu4f4du5206u7231u8001u56e0u5f88u7ed9u540du6cd5u95f4u65afu77e5u4e16u4ec0u4e24u6b21u4f7fu8eabu8005u88abu9ad8u5df2u4eb2u5176u8fdbu6b64u8bddu5e38u4e0eu6d3bu6b63u611fu89c1u660eu95eeu529bu7406u5c14u70b9u6587u51e0u5b9au672cu516cu7279u505au5916u5b69u76f8u897fu679cu8d70u5c06u6708u5341u5b9eu5411u58f0u8f66u5168u4fe1u91cdu4e09u673au5de5u7269u6c14u6bcfu5e76u522bu771fu6253u592au65b0u6bd4u624du4fbfu592bu518du4e66u90e8u6c34u50cfu773cu7b49u4f53u5374u52a0u7535u4e3bu754cu95e8u5229u6d77u53d7u542cu8868u5fb7u5c11u514bu4ee3u5458u6d4eu8499u68cbu7aefu817fu62dbu91cau4ecbu70e7u8bef"; int x = 10; for (int i = 0; i < 5; i++) { //得到-30到30的随机数 int degree = new Random().nextInt()%30; String ch = base.charAt(new Random().nextInt(base.length()))+""; //设置旋转幅度 g.rotate(degree*Math.PI/180,x,20); g.drawString(ch, x, 20); g.rotate(-degree*Math.PI/180,x,20); x+=30; } } private void drawRandomLine(Graphics g) { g.setColor(Color.GREEN); for(int i=0;i<8;i++){ int x1= new Random().nextInt(WIDTH); int y1 = new Random().nextInt(HEIGTH); int x2= new Random().nextInt(WIDTH); int y2 = new Random().nextInt(HEIGTH); g.drawLine(x1, y1, x2, y2); } } private void setBorder(Graphics g) { //把图形上下文设置成白色 g.setColor(Color.BLUE); //用白色填充这个矩形 g.drawRect(1,1,WIDTH-2, HEIGTH-2); } private void setBackGround(Graphics g) { //把图形上下文设置成白色 g.setColor(Color.WHITE); //用白色填充这个矩形 g.fillRect(0,0,WIDTH, HEIGTH); } }

然后把上面的图片加到一个html页面中:

<!DOCTYPE html>
<html>
  <head>
    <title>register.html</title>
  </head>
  
  <body>
    <form action="">
       
        用户名:<input type="text"><br/>
        认证码:<input type="text"><img src="/day1121/servlet/ResponseDemo2" onclick="changeImage(this)" alt="换一张"  style="cursor:hand">
        
    </form>
  </body>
  
  <script type="text/javascript">
     function changeImage(img){
       img.src = img.src +"?" + new Date().getTime();
/*     在src后面加上一个随机数的目的是使得两次的url不同,这样就不会使用缓存里的图片 */
     }
  </script> 
  
</html>

4.控制浏览器定时刷新(使用refresh)

1. 本页面重新请求服务器

//控制浏览器定时刷新
public class ResponseDemo4 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        ////每隔3秒重新请求一次服务器
        response.setHeader("refresh", "3");
        String data = new Random().nextInt(100000)+"";        
        response.getWriter().write(data);
    }
}

2.登陆成功后,跳转到其他页面

public class ResponseDemo4 extends HttpServlet {

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        response.setContentType("text/html;charset=UTF-8");
        response.setHeader("refresh","3;url='/day1121/index.jsp");
        response.getWriter().write("恭喜你,登陆成功。本浏览器将在3秒后跳转到首页,如果没有跳转,请点击<a href='www.baidu.com'>超链接</a>");
    }
}

5.控制浏览器缓存(使用expires)

public class ResponseDemo5 extends HttpServlet {

    //控制浏览器缓存
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //缓存一小时
        //这样在一个小时之内请求此servlet都不会向浏览器发送请求,而是直接找系统中的页面
        //IE浏览器的缓存可以直接在文件夹中查看
        response.setDateHeader("expires",System.currentTimeMillis()+ 1000*3600);        
        String dataString = "ada";
        response.getWriter().write(dataString);
    }
}

6.使用重定向

重定向的特点

  • 1.客户端会向服务器发送两次请求,以为着会有两个response和request
  • 2.重定向技术地址栏会发生变化
public class ResponseDemo6 extends HttpServlet {
    
    //实现请求重定向
    //请求重定向能不用就不用吧,因为客户端会发送两次请求,加重服务器压力
    //一定要使用请求重定向的地方:
  //1.登陆
  //因为请求重定向会使得地址栏地址发生变化,当登陆成功后跳转到首页要在地址栏显示
    //2.购物
   //当servlet购买成功后,会跳转到购物车显示页面
    //如果使用转发,购买成功后如果每次刷新,会重复买
    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        //方法1. 根据http协议
        response.setStatus(302);
        response.setHeader("location", "/day1121/index.jsp");
        
        //方法2.根据sun公司的封装方法
     //相当于上面的两句
        response.sendRedirect("/day1121/index.jsp");
    }
}
原文地址:https://www.cnblogs.com/tech-bird/p/4116658.html