20. Introduction to Servlet - introduction and use of response
Response overview
In the previous chapters, we have already known the relevant functions of the resquest request, so let's continue to understand the response response.
Overview of HttpServletResponse
In the Servlet API, a HttpServletResponse interface (parameters of doGet, doPost methods) is defined, which inherits from the ServletResponse interface and is specially used to encapsulate HTTP response messages. Since the HTTP response message is divided into three parts: response line, response header, and response body, the methods for sending response status code, response header, and response body to the client are defined in the HttpServletResponse interface
effect
-
The three parts of the operation response (response line, response header, response body)
summary
-
Response represents the response object. The prototype is HttpServletResponse, created by the server, and there are doGet()/doPost() methods in the form of formal parameters
-
The role of Response
-
The three parts of the operation response (line, header, body)
Response sets the response status code (operation response line)
When the Servlet returns the response information to the browser, you can set the response status code returned to the browser.
For example:
HTTP/1.1 200
You can use the setStatus(int sc) method to set the response status code:
The commonly used status codes are:
200: success
302: Redirect
304: access cache
404: Client Error
500: Server Error
Let's write a Demo to demonstrate it.
1. Create a demo Servlet program and set the response status code 403
@WebServlet("/ResponseDemo1")
public class ResponseDemo1 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("访问 ResponseDemo1 ....");
//设置响应状态码: 403 forbidden
response.setStatus(403);
}
}
2. Test access on the browser
3. Summary
-
Set API: response.setStatus(int code);
-
Generally, no setting is required, maybe 302 redirection needs to be set
-
Common Response Status Codes
-
200 successful
-
302 redirect
-
304 read cache
-
404 client error
-
500 server error
Response sets the refresh response header to perform timing jump (operation response header)
We have learned how to use Response to set the response status code above, so let's operate the response header.
1. API introduction for manipulating response headers
Response header: is the server instructs the browser what to do
A key corresponds to a value
One key corresponds to multiple values
The method of concern: setHeader(String name,String value);
Common response headers
Refresh: timing jump (eg: the server tells the browser to jump to Baidu after 5s)
Location: redirection address (eg: the server tells the browser to jump to xxx)
Content-Disposition: Tell the browser to download
Content-Type: Set the MIME type of the response content (the server tells the browser the type of content)
Let's demonstrate how Refresh performs timing jumps.
2. Create a demo Servlet program and set the response header to jump regularly
@WebServlet("/ResponseDemo2")
public class ResponseDemo2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//目标: 让浏览器在访问ResponseDemo2后三秒,跳转到百度首页
System.out.println("ResponseDemo2收到了请求。。。");
//通过"Refresh"响应头
response.setHeader("Refresh","3;url=https://www.baidu.com");
}
}
3. Test access on the browser
After waiting for 3 seconds, it will automatically jump to Baidu, as follows:
Response initiates a redirect (operation response header)
Above we have realized the timing jump by setting the response header, so let's look at the redirection next.
1. Response sets the Location response header for redirection (immediate jump)
First create a Servlet program to demonstrate redirection, as follows:
@WebServlet("/ResponseDemo3")
public class ResponseDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ResponseDemo3收到了一个请求...");
//目标1:浏览器访问ResponseDemo3,会跳转到百度首页
//重定向跳转的步骤:1. 设置响应状态码为302 2. 设置响应头Location的值为要跳转到的地址
response.setStatus(302);
response.setHeader("Location","https://www.baidu.com");
}
}
2. Browser test access, found that the browser is successful and immediately jumps to Baidu
Visit http://localhost:8080/ResponseDemo3
In this test, we can make sure that redirects can be forwarded to resources outside the project. So let's forward it to the resources in the project to see.
3. Set redirection to resources in the project
3.1 Create an index.html under WEB-INF
3.2 Set redirection to the index.html in the Servlet, as follows:
@WebServlet("/ResponseDemo3")
public class ResponseDemo3 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("ResponseDemo3收到了一个请求...");
//目标1:浏览器访问ResponseDemo3,会跳转到百度首页
//重定向跳转的步骤:1. 设置响应状态码为302 2. 设置响应头Location的值为要跳转到的地址
// response.setStatus(302);
// response.setHeader("Location","https://www.baidu.com");
//目标2:浏览器访问ResponseDemo3,会跳转到本项目的index.html页面
response.setStatus(302);
response.setHeader("Location","/index.html"); // 路径设置: /项目部署路径/文件在webapp下的路径
}
}
Use a browser to access http://localhost:8080/ResponseDemo3 as follows:
So can I access the resources in WEB-INF?
3.3 Attempt to redirect to resources in WEB-INF
It can be seen that the browser cannot access the resources under WEB-INF, so it cannot be redirected to.
3.4 Shorthand redirection using sendRedirect
In the above, since we redirect to set the response code or set the request header, is there a shorthand method? Of course there is, see below.
// 重定向的简写方法
response.sendRedirect("/index.html");
Test it in a browser, as follows:
It can be seen that the effect of redirection can be achieved, so we just need to remember this way of writing.
4. Summary
-
Redirects cause the browser to make two requests
-
The redirected address bar path changes
-
Write the absolute path for the redirected path (with domain name/ip address, if it is in the same project, the domain name/ip address can be omitted)
-
The redirected path can be inside the project or outside the project (eg: Baidu)
-
Redirects cannot redirect to resources under WEB-INF
-
Store the data in the request, redirection is not available
//方式一: 重定向
//1.设置状态码
//response.setStatus(302);
//2.设置重定向的路径(绝对路径,带域名/ip地址的,如果是同一个项目里面的,域名/ip地址可以省略)
//response.setHeader("Location","https://www.baidu.com");
//response.setHeader("Location","/index.html");
//方式二: 直接调用sendRedirect方法, 内部封装了上面两行
response.sendRedirect("/index.html");
-
redirect
response.sendRedirect("重定向的路径");
Comparison of redirection and request forwarding
1. Features of redirection:
-
The redirection jump is initiated by the browser, and the browser will initiate two requests during this process
-
Redirection jumps can jump to resources of any server, but cannot jump to resources in WEB-INF
-
Redirect jumps cannot be used with request domain objects
-
The address in the browser's address bar will become the redirected path
2. Features of request forwarding:
1. 请求转发的跳转是由服务器发起的,在这个过程中浏览器只会发起一次请求
2. 请求转发只能跳转到本项目的资源,但是可以跳转到WEB-INF中的资源
3. 请求转发可以和request域对象一起使用
Use the character output stream of Response to output the text content of the response body to the browser (operation response body)
1. API for manipulating the response body
Page output can only be achieved using one of the streams, and the two streams are mutually exclusive.
General usage:
-
If you are outputting text content to the browser, then you need to output characters to the browser, use
getWriter()
-
If it is to download resources such as pictures, then you need to output the byte stream to the browser, use
getOutputStream()
Let's first demonstrate the situation of outputting text content.
2. Use getWriter() to output text content to the browser
2.1 The response.getWriter().writer() method can only output strings. If it outputs int, float, etc., there will be problems
@WebServlet("/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//要向浏览器输出响应体的信息,需要通过流来进行操作
//第一种:字符串,输出文本内容
PrintWriter writer = response.getWriter();
//使用字符流往浏览器输出文本
//1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
writer.write("hello world");
}
}
If the int and float types are output, an error will be reported as follows:
It can be seen that the numbers cannot be displayed normally, so what is the need to display the numbers? At this time, it is generally output as a string, as follows:
But if you don't want to do this, what can you do if you want to directly output int, float, etc.? writer.print()
method can be used .
2.2 The response.getWriter().print() method can output numbers and strings
//2. print()方法,可以输出数字、字符串
writer.print(123456);
It can be seen that using print()
the method can indeed output numbers, but we generally only need to remember to use writer()
the method to output strings.
2.3 Output Chinese character strings, garbled characters appear
It is possible to output English strings and numbers above, but when we try to output Chinese content, there will be garbled characters, as follows:
So why there are garbled characters, of course, it is caused by inconsistent encoding formats. So let's take a look at how to solve the garbled problem.
3. Solve the problem of Chinese response garbled characters
The problem of Chinese garbled characters is caused by the inconsistency between the encoding format of the server and the encoding format of the browser. Then we only need to set the encoding format of the server to UTF8, and then inform the browser to also set the encoding format to UTF8.
So what if the browser is notified to set the UTF8 encoding format? It can be set as follows when responding:
-
Solve the problem of character stream output Chinese garbled characters
response.setContentType("text/html;charset=utf-8");
/*
* 这句代码底层做了什么?
* 1. 设置服务器响应的字符集为UTF-8
* 2. 设置Content-Type响应头的信息为 "text/html;charset=UTF-8"
* 让浏览器知道了服务器的响应字符集UTF-8,那么浏览器也会使用UTF-8解码
*/
3.1 Demonstration of solving the problem of outputting Chinese garbled characters
@WebServlet("/ResponseDemo4")
public class ResponseDemo4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//解决响应中文乱码
response.setContentType("text/html;charset=utf-8");
//要向浏览器输出响应体的信息,需要通过流来进行操作
//第一种:字符串,输出文本内容
PrintWriter writer = response.getWriter();
//使用字符流往浏览器输出文本
//1. writer()方法,只能输出字符串,如果输出int、float等等类型的话,则会有问题
writer.write("你好,世界...");
//2. print()方法,可以输出数字、字符串
// writer.print(123456);
}
}
3.2 Shortcuts for setting the response encoding format
Although it is only one line of code to solve the Chinese garbled characters in the response, it is quite troublesome to remember every time. So we can set it as a shortcut to enter.
File | Settings | Editor | Live Templates
//解决响应中文乱码
response.setContentType("text/html;charset=utf-8");
The test results are as follows:
Use Response's byte stream getOutputStream() to output image content to the browser (operation response body)
Above we have implemented the output of the string content to the browser, so of course we also need to consider how to output the image content to the browser.
First, let's take a look at how the default DefaultServlet handles static resources.
DefaultServlet handles static resources
1. Copy a picture to the webapp directory
2. Start the tomcat service and use the project path to access image resources
So if you write a Servlet program yourself, how to realize this function?
Write your own Servlet and use getOutputStream() to output image resources to the browser
@WebServlet("/ResponseDemo5")
public class ResponseDemo5 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1. 读取b.jpg图片,将其转换成字节输入流,使用ServletContext
ServletContext servletContext = getServletContext();
InputStream is = servletContext.getResourceAsStream("1.jpeg");
//2. 使用字节输出流,将is中的字节都输出到浏览器
//2.1 获取响应字节流
ServletOutputStream os = response.getOutputStream();
//2.2 读取文件输入流 拷贝到 响应输出字节流
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
//3.关闭流
os.close();
is.close();
}
}
In the above code, we have achieved the effect of outputting the image resource to the browser, but we can find it.
Every time we operate a byte stream, we have to write a string of byte stream buffers to copy to another output stream, which is cumbersome:
//2.2 读取文件输入流 拷贝到 响应输出字节流
byte[] buffer = new byte[1024];
int len = 0;
while ((len = is.read(buffer)) != -1){
os.write(buffer,0,len);
}
Is there an easier way? Of course there is, that is, it can be encapsulated as a public method, and this public method has been provided by a third party, and we can use it directly.
The use of IO stream tools: Simplify the copy operation of byte streams
-
Introduce the jar package of commons-io
-
Use commons-io to simplify the copy operation of byte stream
1. Use Maven to import the jar package dependencies of commons-io
1.1 Visit the Maven warehouse and search for the dependencies of commons-io
Visit https://mvnrepository.com and search for commons-io as follows:
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
1.2 Import commons-io coordinate dependencies in the pom.xml of the project
<!-- 导入 commons-io -->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
2. Use the IOUtils.copy(is,os); method in commons-io to copy the stream
import org.apache.commons.io.IOUtils;
//2.2 使用 commons-io 中的 IOUtils.copy(is,os); 方法来拷贝流
IOUtils.copy(is, os);
3. View the source code of IOUtils.copy(is, os)
It can be seen that, in fact, this copy method also copies the byte stream, but the package is better, which is convenient for all of us to use.
Summary of responses
-
Set the response status code: setStatus()
-
Set the response header: setHeader(name,value)
-
The refresh response header is used to jump to a certain page after a few seconds
-
location response header, used to redirect to a certain page
-
-
Redirection writing: sendRedirect(address)
-
Set the content of the response body
-
response.getOutputStream() gets the byte output stream
-
response.getWriter() gets the character output stream
-
writer.write()/print() output string
-
Solve the Chinese garbled characters of the response data: response.setContentType("text/html;charset=UTF-8")
-
Output text content using a character output stream
-
output file using byte output stream
-
-
Use the framework of IO stream to read and write