Response

HttpServletResponse

  我们在创建Servlet时会覆盖service()方法,或doGet()/doPost(),这些方法都有两个参数,一个为代表请求的request和代表响应response。
service方法中的response的类型是ServletResponse,而doGet/doPost方法的response的类型是HttpServletResponse,HttpServletResponse是ServletResponse的子接口,功能和方法更加强大

response设置响应行

  设置响应行的状态码
  setStatus(int sc)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.rexyan.response;

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

public class Response extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//通过修改状态码和头的方式实现跳转
response.setStatus(301);
response.setHeader("Location", "http://www.baidu.com");

//实际开发中使用这种方式
response.sendRedirect("http://www.baidu.com");
}

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

response设置响应头

  addHeader(String name, String value)
  addIntHeader(String name, int value)
  addDateHeader(String name, long date)
  setHeader(String name, String value) 【经常用】
  setDateHeader(String name, long date)
  setIntHeader(String name, int value)
  其中,add表示添加,而set表示设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.rexyan.response;

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

public class Response extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setHeader("name", "rex");
response.addHeader("name", "lisi");
}

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

通过response设置响应体

  PrintWriter getWriter()获得字符流 通过字符流的write(Strings)方法可以将字符串设置到response缓冲区中,随后Tomcat会将response缓冲区中的内容组装成Http响应返回给浏览器端。
关于设置中文的乱码问题,原因:response缓冲区的默认编码是iso8859-1,此码表中没有中文,可以通过response的setCharacterEncoding(String charset) 设置response的编码

  但我们发现客户端还是不能正常显示文字原因:我们将response缓冲区的编码设置成UTF-8,但浏览器的默认编码是本地系 统的编码,因为我们都是中文系统,所以客户端浏览器的默认编码是GBK,我们可以 手动修改浏览器的编码是UTF-8。

  我们还可以在代码中指定浏览器解析页面的编码方式,
通过response的setContentType(String type)方法指定页面解析时的编码是UTF-8
response.setContentType(“text/html;charset=UTF-8”);

  上面的代码不仅可以指定浏览器解析页面时的编码,同时也内含setCharacterEncoding的功能,所以在实际开发中只要编写response.setContentType(“text/html;charset=UTF-8”);就可以解决页面输出中文乱码问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package com.rexyan.response;

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

public class Response extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=utf-8");
response.getWriter().write("中国");
//在实际开发中其实只需要使用response.setContentType("text/html;charset=utf-8");设置即可
}

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

获取文件的绝对路径

1
String realPath = getServletContext().getRealPath("a.jpg");

响应头设置字节

  ServletOutputStream getOutputStream()
  获得字节流,通过该字节流的write(byte[] bytes)可以向response缓冲区中写入字节,在由Tomcat服务器将字节内容组成Http响应返回给浏览器。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.rexyan.response;

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

public class Response extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//传入相对路径通过ServerLetContext获取文件的绝对路径
String realPath = getServletContext().getRealPath("a.jpg");
//使用IO读取文件
FileInputStream fileInputStream = new FileInputStream(realPath);
//将文件写到response缓冲区
ServletOutputStream outputStream = response.getOutputStream();

int len = 0;
byte[] buffer = new byte[1024];
while ((len=fileInputStream.read(buffer))>0) {
outputStream.write(buffer, 0, len);
}
fileInputStream.close();
}

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

下载文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.rexyan.response;

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

public class Response extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//若要下载文件,需加上两个头文件
//通过getMimeType传入文件名获取文件的Mime类型
response.setContentType(getServletContext().getMimeType("a.jpg"));
//设置头文件,告诉浏览器以下载的方式打开文件
response.setHeader("Content-Disposition", "attachment;filename=a.jpg");

//------------------------------------------------------------------

//传入相对路径通过ServerLetContext获取文件的绝对路径
String realPath = getServletContext().getRealPath("a.jpg");
//使用IO读取文件
FileInputStream fileInputStream = new FileInputStream(realPath);
//将文件写到response缓冲区
ServletOutputStream outputStream = response.getOutputStream();

int len = 0;
byte[] buffer = new byte[1024];
while ((len=fileInputStream.read(buffer))>0) {
outputStream.write(buffer, 0, len);
}
fileInputStream.close();

}

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

文件下载出现乱码

  但是,如果下载中文文件,页面在下载时会出现中文乱码或不能显示文件名的情况, 原因是不同的浏览器默认对下载文件的编码方式不同,ie是UTF-8编码方式,而火狐 浏览器是Base64编码方式。所里这里需要解决浏览器兼容性问题,解决浏览器兼容 性问题的首要任务是要辨别访问者是ie还是火狐(其他),通过Http请求体中的User-Agent属性可以辨别

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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");
}

其中agent就是请求头User-Agent的值

  代码实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package com.rexyan.response;

import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import sun.misc.BASE64Encoder;

public class Response extends HttpServlet {

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String agent = request.getHeader("User-Agent");
String filename = "a.jpg";
String downname = filename;

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

//若要下载文件,需加上两个头文件
//通过getMimeType传入文件名获取文件的Mime类型
response.setContentType(getServletContext().getMimeType(filename));
//设置头文件,告诉浏览器以下载的方式打开文件
response.setHeader("Content-Disposition", "attachment;filename="+ downname);

//------------------------------------------------------------------

//传入相对路径通过ServerLetContext获取文件的绝对路径
String realPath = getServletContext().getRealPath(filename);
//使用IO读取文件
FileInputStream fileInputStream = new FileInputStream(realPath);
//将文件写到response缓冲区
ServletOutputStream outputStream = response.getOutputStream();

int len = 0;
byte[] buffer = new byte[1024];
while ((len=fileInputStream.read(buffer))>0) {
outputStream.write(buffer, 0, len);
}
fileInputStream.close();

}

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