javaWeb——Request和Response03

javaWeb——Request和Response03

到了这一节我们开始学习Response。

一.Response重定向

Response的作用是设置响应消息。

1. 设置响应行
	1. 格式:HTTP/1.1 200 ok
	2. 设置状态码:setStatus(int sc):如果不设置会自动根据情况返回
2. 设置响应头:setHeader(String name, String value):可以自定义响应头,客户端可以收到
3. 设置响应体:
	1. 获取输出流
		* 字符输出流:PrintWriter getWriter()
		* 字节输出流:ServletOutputStream getOutputStream()
	2. 使用输出流,将数据输出到客户端浏览器

我们要学习一个新的概念:
重定向,即一种资源跳转的方式,前面我们讲过了转发,现在我们来比较一下二者:

  • 重定向的特点:redirect
    1. 地址栏发生变化
    2. 重定向可以访问其他站点(服务器)的资源
    3. 重定向是两次请求。不能使用request对象来共享数据
  • 转发的特点:forward
    4. 转发地址栏路径不变
    5. 转发只能访问当前服务器下的资源
    6. 转发是一次请求,可以使用request对象来共享数据

现在我们来实现一个重定向的例子来演示上面的特点:

@WebServlet("/demo")
public class ServletDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        System.out.println("访问了demo");
        req.setAttribute("aa","bb");
        resp.sendRedirect("/demo2");
        System.out.println(123);
    }
}
@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("访问了demo2");
        System.out.println(req.getAttribute("aa"));
    }
}

在这里插入图片描述
在这里插入图片描述
从结果来分析:

重定向地址栏发生了变化,且request共享的数据无法获取到,重定向两次请求可以通过F12抓包来看。上面这个例子没有体现可以访问外部资源的特点,可以将resp.sendRedirect("/demo2")改为resp.sendRedirect(“www.baidu.com”);来验证这里不做演示了,同时我们发现重定向发生在ServletDemo代码完全执行完后才发生

二.Tomcat项目中路径的写法及Response流的示例

1. 相对路径:通过相对路径不可以确定唯一资源
* 如:./index.html
* 不以/开头,以.开头路径
* 规则:找到当前资源和目标资源之间的相对位置关系
	* ./:当前目录
	* ../:后退一级目录
2. 绝对路径:通过绝对路径可以确定唯一资源
* 如:http://localhost:8080/jack/responseDemo2或者/jack/responseDemo2
*/开头的路径
* 规则:判断定义的路径是给谁用的?判断请求将来从哪儿发出
	* 给客户端浏览器使用:需要加虚拟目录(项目的访问路径)
		* 建议虚拟目录动态获取:request.getContextPath()
		* <a> , <form> 重定向...
	* 给服务器使用:不需要加虚拟目录
		* 请求转发时不需要
(上面两种方式在写页面超链接的时候也是适用的)

演示:
相对路径这里不展示。
绝对路径展示:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
	<!--这个路径是给浏览器在使用要加上虚拟目录-->
    <a href="/jack/demo2">超链接</a>
</body>
</html>

点击超链接:
在这里插入图片描述
下面我们来看一个Response流的示例:
SevletDemo的doGet方法代码如下:

PrintWriter writer = resp.getWriter();
writer.write("<h1>Hello World!  你好</h1>");

出现了乱码的现象:
在这里插入图片描述
将代码改为如下即可:

resp.setCharacterEncoding("gbk");\\(将流的字符集改为gbk与浏览器一致,浏览器一般都是gbk编码格式)
PrintWriter writer = resp.getWriter();
writer.write("<h1>Hello World!  你好</h1>");

在这里插入图片描述
不过上面这个方法不是很通用,比如我们的浏览器采用的字符集不是gbk我们可以使用下面的方式:

 resp.setCharacterEncoding("utf-8");
 resp.setContentType("text/html;charset=utf-8");
 PrintWriter writer = resp.getWriter();
 writer.write("<h1>Hello World!  你好</h1>");

在这里插入图片描述

三.文件下载

前面我们已经讲过了ServletContext对象了,这里再拓展一下:

1. 获取MIME类型:
	* MIME类型:在互联网通信过程中定义的一种文件数据类型
		* 格式: 大类型/小类型   text/html		image/jpeg
	* 获取:String getMimeType(String file)  
2. 域对象:共享数据
	1. setAttribute(String name,Object value)
	2. getAttribute(String name)
	3. removeAttribute(String name)
3. 获取文件的真实(服务器)路径
	1. 方法:String getRealPath(String path)  
	三个例子:
		 String b = context.getRealPath("/b.txt");//web目录下资源访问
         System.out.println(b);
        String c = context.getRealPath("/WEB-INF/c.txt");//WEB-INF目录下的资源访问
        System.out.println(c);
        String a = context.getRealPath("/WEB-INF/classes/a.txt");//src目录下的资源访问
        System.out.println(a);

对1,3做个演示:

ServletContext servletContext = req.getServletContext();
String mimeType = servletContext.getMimeType("login.html");
System.out.println(mimeType);
System.out.println(servletContext.getRealPath("/login.html"));
System.out.println(servletContext.getRealPath("/WEB-INF/web.xml"));
System.out.println(servletContext.getRealPath("/WEB-INF/classes/ServletDemo"));

在这里插入图片描述
接下来我们要实现下载这个图片:
在这里插入图片描述
代码如下:

 resp.setCharacterEncoding("utf-8");
        ServletContext servletContext = req.getServletContext();
        String mimeType = servletContext.getMimeType("a.png");
        mimeType+=mimeType+";charset=utf-8";
        resp.setContentType(mimeType);
        resp.setHeader("content-disposition", "attachment;filename=目标.png");
        ServletOutputStream outputStream = resp.getOutputStream();
        InputStream inputStream = new FileInputStream(servletContext.getRealPath("/WEB-INF/classes/Image/目标.png"));
        byte[] bytes = new byte[1024*200];
        while(inputStream.read(bytes)!=-1){
            outputStream.write(bytes);
            outputStream.flush();
        }
        inputStream.close();
        outputStream.close();

下载后图片打开后正常,但是文件名乱码了
在这里插入图片描述
解决办法如下,编写如下文件:

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

然后将resp.setHeader("content-disposition", "attachment;filename=目标.png");改为:

String header = req.getHeader("user-agent");
        String filename = DownLoadUtils.getFileName(header,"目标.png");
        resp.setHeader("content-disposition", "attachment;filename="+filename);

成功解决:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值