web开发(六)Response对象、重定向、中文乱码

Response对象

1.1 Response概述

什么是Response

开发的软件是B/S结构的软件,可以通过浏览器访问服务器的软件。

  • 从浏览器输入一个地址访问服务器(将这个过程称为是请求)。
  • 服务器接收到请求,需要进行处理,处理以后需要将处理结果显示回浏览器端(将这个过程称为是响应Response)。
    在这里插入图片描述

1.2 Response对象的API

在这里插入图片描述

关于响应行的方法

方法 返回值 描述
setStatus(int sc) void 设置响应的状态码
  • 设置响应的状态码
    • 200 正确
    • 302 重定向
    • 304 查找本地缓存
    • 404 请求资源部存在
    • 500 服务器内部错误
代码演示:
//设置响应的状态码

public class ResponseDemo1 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置响应的状态码:
        response.setStatus(404);
        //response.setStatus(500);
    }

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

关于响应头的方法

响应头里放的都是键值对(键值对 k:v)

方法 返回值 描述
setDateHeader(String name, long date) void 设置响应头
setHeader(String name, String value) void 设置响应头
setIntHeader(String name, int value) void 设置响应头
  • set开头的方法:针对一个key对应一个value的情况。
    • 举例:比如已有一个响应头 content-Type:text/html ,然后执行 setHeader(“content-Type”,”text/plain”);
    • 最终得到响应头的结果:content-Type:text/plain
方法 返回值 描述
addDateHeader(String name, long date) void 设置响应头
addHeader(String name, String value) void 设置响应头
addIntHeader(String name, int value) void 设置响应头
  • add开头的方法:针对一个key对应多个value的情况(一键多值)。但需要多次设置,一次只能设置一个键值对。
    • 举例:比如已有一个响应头content-Type:text/html ,然后执行addHeader(“content-Type”,”text/plain”);
    • 最终得到响应头的结果:content-Type:text/html,text/plain
代码演示:
/*
 * 使用状态码和Location头完成重定向
 */
public class ResponseDemo1 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 完成重定向
        response.setStatus(302);
        // 设置响应头
        response.setHeader("Location", "/web01/ResponseDemo2");
        //实际开发中可以使用下面的代码,替换重定向两句写法
        //response.sendRedirect("/web01/ResponseDemo2");
    }

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

关于响应体的方法

方法 返回值 描述
getOutputStream() ServletOutputStream 返回一个字节流,用于向浏览器发送数据
getWriter() PrintWriter 放回一个字符流,用于向浏览器发送数据
  • Response设置响应体:页面中显示正文(body中显示内容)
    • 字符流:只能读写文本文件–>使用记事本打开能看懂
      getWriter() 返回值是打印流PrintWrite
    • 字节流:可以读写任意文件(文本,图片,音乐,文件…)
      getOutputStream() 返回字节输出流OutputStream

字符流:response对象获取到字符流PrintWriter(字符打印流)

  1. 继承自父类Wirter中的方法
    write() : 写的数据会查询编码表 100–>d

  2. 自己特有的方法
    print(): 写数据原样输出 100–>100
    println(): 写数据原样输出,带换行 100–>100

代码演示:
@WebServlet(urlPatterns = "/body")
public class Demo03BodyServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取字符打印流
        PrintWriter pw = response.getWriter();
        pw.write(100);		//d

        pw.println(100);
        pw.println("aaa");
        pw.println('#');
        pw.println(5.5);
    }

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

使用字节输出流:响应非文本文件

getOutputStream() 返回字节输出流OutputStream

案例:文件复制:一读(本地流)一写(网络流,给客户端写)

客户端/服务器:读写本地文件(硬盘中)必须使用自己创建的流对象(本地流)
客户端/服务器:之间进行交互必须使用response或者request中提供的流对象(网络流)
package com.ccc.demo03Response;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.FileInputStream;
import java.io.IOException;

@WebServlet(urlPatterns = "/img")
public class Demo05InputStreamServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        //获取要读取的文件的绝对路径
        String realPath = getServletContext().getRealPath("1.jpg");
        //创建一个字节输入流对象
        FileInputStream fis = new FileInputStream(realPath);
        //获取response对象中提供的字节输出流对象
        ServletOutputStream sos = response.getOutputStream();
        //一读一写复制文件
        byte[] bytes = new byte[1024];
        int len = 0;
        while ((len = fis.read(bytes))!=-1){
            sos.write(bytes,0,len);
        }
        fis.close();
    }

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

其他常用的API

方法 放回值 描述
sendRedirect(String location) void 重定向方法
setContextType(String type) void 设置浏览器打分页面时采用的字符集
setCharacterEncoding(String charset) void 设置响应字符流的缓冲区字符集
代码演示:
/**
 * 定时刷新
 */
public class ResponseDemo1 extends HttpServlet {
	
	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        
		// 定时刷新
		response.setContentType("text/html;charset=UTF-8");
		response.getWriter().println("5秒以后页面跳转!");
		response.setHeader("Refresh", "5;url=/web01/ResponseDemo2");
	}

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

}
/**
 3. 重定向后的页面
 */
public class ResponseDemo2 extends HttpServlet {

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.getWriter().println("ResponseDemo2...");
	}

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

重定向:让客户端浏览器重新再请求一次服务器(客户端会请求两次服务器)

  1. 设置响应行中状态码为:302
  2. 指导浏览器再次请求服务器的地址:设置响应头
    key:“location”                value:"/day12_web/servlet2"
    最终,Apache很善良,把两个方法合二为一
    下面是重定向的最终版代码:
    	response.sendRedirect("/day12_web/servlet2");
    

注意:重定向的地址可以是外网

重定向案例:

在这里插入图片描述

代码演示:
package com.ccc.demo04redirect;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/servlet1")
public class Servlet1 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

        System.out.println("Servlet1 我是刘备");
        //response.setStatus(302);
        //response.setHeader("location","/day12_web/servlet2");
        //上面两可以用下面这一行简化
        response.sendRedirect("/day12_web/servlet2");
        
        //也可以不把项目名称写成一个固定的地址,如下面所示
        //response.sendRedirect(getServletContext().getContextPath()+"/servlet2");
        
        //重定向的地址可以是外网地址
        response.sendRedirect("http://www.baidu.com");
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}
package com.ccc.demo04redirect;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet(urlPatterns = "/servlet2")
public class Servlet2 extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        System.out.println("Servlet2 我是关羽");
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().write("二哥借你500");
    }

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

注意事项:

  1. 重定向之后不要再写代码,没有意义,因为后面的代码浏览器读取不到(地址已经跳转了)
  2. 只能重定向一次
  3. getWriter()字符流和getOutputStream()字节流,互斥,只能选择一个使用。因为写数据是把数据写在response对象的缓冲区中,缓冲区中的数据不能既是字符又是字节。

1.3 Response对象响应中文乱码处理

提问:在Servlet中编写以下代码,向页面输出中文是否会产生乱码?

response.getWriter().println("中文");

会乱码:

  • 原因:编码和解码不一致
  • 给客户端使用response响应数据(通过IO流),不是直接把数据写给浏览器,而是存储到response对象的缓冲区中,response设计默认的缓冲区编码是ISO-8859-1。这个字符集不支持中文的。
  • 解决:
    • 设置response获得字符流缓冲区的编码和设置浏览器默认打开时候采用的字符集一致即可。
      1.设置response对象的缓冲区的编码为UTF-8格式编码
      response.setCharacterEncoding("utf-8");
      pw.write("你好"); 	//输出的是  浣犲ソ  此时还有问题,因为浏览器默认使用GBK解码
      
      2.通知浏览器以utf-8编码格式读取数据
      <meta charset="UTF-8">
      最终,Apache很善良,把两个方法合二为一
      下面是解决中文乱码的最终版代码:
      respons.setContextType("text/html;charset=utf-8");
      

使用字节流响应中文

/**
 * Response响应中文的处理
 */
public class ResponseDemo3 extends HttpServlet {

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

    /**
	 * 使用字节流输出中文
	 */
    private void test1(HttpServletResponse response) throws IOException, UnsupportedEncodingException {
        // 使用字节流的方式输出中文:
        ServletOutputStream outputStream = response.getOutputStream();
        // 设置浏览器默认打开的时候采用的字符集
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        // 设置中文转成字节数组字符集编码
        outputStream.write("中文".getBytes("UTF-8"));
    }

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

使用字符流响应中文

/**
 * Response响应中文的处理
 */
public class ResponseDemo3 extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        test2(response);
    }
    /**
	 * 使用字符流输出中文
	 */
    private void test2(HttpServletResponse response) throws IOException, UnsupportedEncodingException {
        // 设置浏览器默认打开的时候采用的字符集:
        // response.setHeader("Content-Type", "text/html;charset=UTF-8");
        // 设置response获得字符流的缓冲区的编码:
        // response.setCharacterEncoding("UTF-8");
        // 简化代码
        response.setContentType("text/html;charset=UTF-8");
        // 会不会产生乱码
        response.getWriter().println("中文");
    }

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

猜你喜欢

转载自blog.csdn.net/qq_45083975/article/details/92446467
今日推荐