response and request objects
Tomcat receives the http request from the client and creates a request object representing the request and a response object representing the response for each request
Since the request object represents the http request, we can get the data submitted by the browser and find the request object. The response object represents the http response, so we can output data to the browser and find the response object.
What is an HttpServletResponse object?
http response consists of status line, entity content, message header and an empty line. The HttpServletResponse object encapsulates the information of the http response.
Application of HttpServletResponse
Call the getOutputStream() method to output data to the browser
Call the getOutputStream() method to output data to the browser. The getOutputStream() method can use print() or write(). What's the difference between them? Let's try. The code is as follows
//Get OutputStream stream ServletOutputStream servletOutputStream = response.getOutputStream(); //Output data to browser servletOutputStream.print("aaaa");
Successful output, there seems to be nothing wrong.
Let's try to output Chinese
//Get OutputStream stream ServletOutputStream servletOutputStream = response.getOutputStream(); //Output data to browser servletOutputStream.print("China!");
Something's wrong!!!
Why do exceptions occur? In io, we learned that outputStream outputs binary data. The print() method receives a string. The print() method changes "China" into binary data. Tomcat uses IOS 8859-1 coding to convert it. The "China" does not support ISO 8859-1 coding at all. So there was an exception
Let's take another look at the write() method. First, output English data to the browser
response.getOutputStream().write("aaa".getBytes());
no problem
Try outputting Chinese data again
response.getOutputStream().write("Hello, I'm China".getBytes());
There seems to be no problem.
Why can you normally output Chinese to the browser by using the write() method? "Hello, I'm China". When the code getBytes() is converted into byte [] array, the default code is gb2312, while "Hello, I'm China" supports gb2312, so it can be displayed normally.
However, to achieve universality, the program should use UTF-8 encoding. We specify UTF-8 encoding when converting a string into a byte array to see what happens.
response.getOutputStream().write("Hello, I'm China".getBytes("UTF-8"));
OK, I succeeded in making it garbled!!!
Why does it become garbled? The reason is this: the Chinese I output to the server is UTF-8 encoded, while the browser uses GBK. GBK wants to display the Chinese data of UTF-8. It's strange not to mess the code!
In that case, I'll try changing the browser's encoding to UTF-8.
The garbled code problem has been solved again. However, do you have to change the coding format on the web page every time you write UTF-8 programs? This is obviously impossible.
Since the HTTP response has a header that tells the browser what type of returned data is, the HttpServletResponse object should have a corresponding method to tell the browser what the returned data encoding format is
So I looked up the Servlet API and found the method to set the message header
//Set the header information and tell the browser that the data code I sent back is utf-8 response.setHeader("Content-Type", "text/html;charset=UTF-8"); response.getOutputStream().write("Hello, I'm China".getBytes("UTF-8"));
When the browser displays data, it automatically replaces the coding format of the page with UTF-8, and the problem of garbled code is also solved
In addition, in addition to using the HttpServletResponse object to set the message header, I can use the html tag to simulate an http message header
Here is the code:
//Get servletOutputStream object ServletOutputStream servletOutputStream = response.getOutputStream(); //Use the meta tag to simulate the http message header and tell the browser the encoding and format of the returned data servletOutputStream.write("<meta http-equiv='content-type' content='text/html;charset=UTF-8'>".getBytes()); servletOutputStream.write("I am China".getBytes("UTF-8"));
The garbled code problem can also be solved
Call the getWriter() method to output data to the browser
For the getWriter() method, it is a subclass of Writer, so it can only output character data to the browser, not binary data
Use the getWriter() method to output Chinese data. The code is as follows:
//Get printWriter object PrintWriter printWriter = response.getWriter(); printWriter.write("Like after reading the blog!");
I'm glad to hear that something visible has appeared again, and I've been garbled again.
Why is there a garbled code? Because Tomcat is written by foreigners, the default code of Tomcat is ISO 8859-1. When we output Chinese data, Tomcat will encode our data according to the ISO 8859-1 code table. Chinese does not support this code table, so there is chaos
In that case, let me set the code. The code is as follows:
//It was originally ISO 8859-1, but I set it to UTF-8 response.setCharacterEncoding("UTF-8"); //Get printWriter object PrintWriter printWriter = response.getWriter(); printWriter.write("Like after reading the blog!");
I visited again, my God! It looks more chaotic!
Why has the problem of garbled code not been solved? Careful friends will find that I only set the code table to UTF-8 during Chinese conversion, but the browser may not use the UTF-8 code table to display data
OK, let's take a look at the encoding format of the browser. Sure enough, the browser uses GB2312 to display UTF-8 data. It's strange that it doesn't mess up
There are two methods to solve this problem [simulate message headers with tags and set message headers]. Servlet also provides a method for us
//Set the browser to display data in UTF-8 encoding response.setContentType("text/html;charset=UTF-8");
OK, let's visit again
Since servlets have so many methods to solve the problem of garbled code, is there one of the easiest? you 're right! The following method is the simplest. It not only sets the browser to display data in UTF-8, but also internally sets the code table of Chinese transcoding to UTF-8, that is, response.setContentType("text/html;charset=UTF-8"); Do the response.setCharacterEncoding("UTF-8")!
Using getWriter() to display Chinese data only needs one method!
//Set the browser to display data in UTF-8 encoding, response.setContentType("text/html;charset=UTF-8"); //Get printWriter object PrintWriter printWriter = response.getWriter(); printWriter.write("Like after reading the blog!");
Realize file download
Download resources are also commonly used in our daily life. How does it do it? To be able to download to others, the server should have this resource
Now there is a picture under my web site!
Since the browser sends all requests to find a Servlet, I will write a Servlet. When others visit my Servlet, they can download my picture!
java files are uploaded and downloaded through io streams. Since you want to download pictures, you must first be able to read them
//Gets the path to the resource String path = this.getServletContext().getRealPath("/download/1.png"); //Read resources FileInputStream fileInputStream = new FileInputStream(path); //Get the file name and save the path on the computer in the form of \. String fileName = path.substring(path.lastIndexOf("\\") + 1);
Tell the browser that I want to download this file
//Set the message header and tell the browser that I want to download the picture 1.png response.setHeader("Content-Disposition", "attachment; filename="+fileName);
Send the read content back to the browser
//Write the read resources to the browser int len = 0; byte[] bytes = new byte[1024]; ServletOutputStream servletOutputStream = response.getOutputStream(); while ((len = fileInputStream.read(bytes)) > 0) { servletOutputStream.write(bytes, 0, len); } //close resource servletOutputStream.close(); fileInputStream.close();
When I visit, the browser prompts me to download.
It can also be opened successfully!
Now the question arises again. What if the name of my file is Chinese?
We visited again and found that the name was garbled (how could it be all garbled)
In order to solve the problem of garbled file names, we need to encode URL s as follows:
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
When accessing again, the file name garbled problem is solved!
Automatic refresh
Refresh the page and update resources at the specified time
Let the browser refresh automatically, it must be modifying the message header again.
//Automatically refresh the web page every 3 seconds response.setHeader("Refresh", "3");
In order to better see the effect, we add the time value
response.getWriter().write("time is :" + System.currentTimeMillis());
The value changes every three seconds
After learning the above, it seems useless. Who can see such things when they surf the Internet. Automatic refresh, which can realize page Jump]
When we log in to the website, we often see [log in successfully and jump automatically after 3 seconds...]. In fact, this is done with Refresh.
response.setContentType("text/html;charset=UTF-8"); response.getWriter().write("3 Jump to page in seconds....."); //After three seconds, jump to the index.jsp page. I set the mapping path of the web application to /, and the url does not write the application name response.setHeader("Refresh", "3;url='/index.jsp'");
Look at the effect
Set cache
The browser itself has a caching mechanism
When I first visited index.jsp, the browser sent two requests to the server [one is a web page and the other is a picture]
When I visited index.jsp for the second time, the browser cached the pictures! The picture is not reloaded, it is taken from the cache.
For example, stock type web pages can't get cached data, and the data should be updated constantly. Next, I will disable the caching function
//The browser has three message headers to set the cache for compatibility! Set all three headers response.setDateHeader("Expires", -1); response.setHeader("Cache-Control","no-cache"); response.setHeader("Pragma", "no-cache"); //Here to see the effect PrintWriter printWriter = response.getWriter(); printWriter.print("How do you do" + new Date().toString());
Of course, if some data on the page is not updated for a long time, you can set it as a cache, which can improve the performance of the server
Realize data compression
The amount of information on the web page is very large. If the data is not compressed and sent back to the browser, it will consume a lot of traffic
Now I have an article to output to the browser
response.setContentType("text/html;charset=UTF-8"); String ss = "fsdfhsdfhuisdhfusdhfuids" + "fsdfdsfsdfsdfdsfdafdsfhsdjfhsdjkfhkjds" + "fdsfjdslkfjsldkfjsdlkfjsdkfsdjkff" + "fsjdfjdsklfjdsklfjkldsfjlksdjflksdjflkds" + "dsjfklsdjflsdjfkldsfkjsdkfjsldkfjsdlfk" + "fdsjlkfjdslkfjsdlkfjlkasjflk"; response.getWriter().write("The original length is:"+ss.getBytes().length+"</br>"); //Output to browser response.getWriter().write(ss);
You can see that the original length is 201
What is the principle of compression? We know that getOutputStream() and getWriter() both output data directly to the browser. Now what I have to do is not to output the data directly to the browser. Let me compress it first, and then output it to the browser. java provides GZIP compression class to us
Let's use the GZIP class to compress the data
//The construction method of GZIP requires an OutputStream subclass object. Which object is suitable? Let's take a look at the write() method GZIPOutputStream gzipOutputStream = new GZIPOutputStream(); //After checking the API, write() receives byte [] type. gzipOutputStream.write();
So I passed it a ByteArrayOutputStream on the constructor
//Since it is of byte [] type, I will give it a ByteArrayOutputStream GZIPOutputStream gzipOutputStream = new GZIPOutputStream(new ByteArrayOutputStream());
When writing data with GZIPOutputStream, the data is written to ByteArrayOutputStream. Later, the data will be taken out and written to the browser. Therefore, GZIPOutputStream cannot be given by anonymous internal classes. ByteArrayOutputStream must be defined,
//Create a GZIPOutputStream object and give it ByteArrayOutputStream ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); GZIPOutputStream gzipOutputStream = new GZIPOutputStream(byteArrayOutputStream); //GZIP compresses the data. The data written by GZIP is saved on byteArrayOutputStream gzipOutputStream.write(ss.getBytes()); //gzipOutputStream has a buffer. Clear the buffer and close the stream gzipOutputStream.close();
Take out the compressed data and write it to the browser
//Take out the compressed data byte[] bytes = byteArrayOutputStream.toByteArray(); //Write compressed data to the browser response.getOutputStream().write(bytes);
Let's compare the size before compression with the size after compression
The data is indeed compressed. However, why is it garbled again? Very simply, since you have compressed the data and you write it to the browser, the browser does not know that this is the compressed data. It opens the data in a normal way. Of course, it causes garbled code!, Now I want to tell the browser that this is compressed data
//Tell the browser that this is gzip compressed data response.setHeader("Content-Encoding","gzip"); //Then write the compressed data to the browser response.getOutputStream().write(bytes);
Visit again
Generate random pictures
It is very common to generate random pictures. When we log in, we often write verification codes, and those verification codes are a picture, which is written to the browser through HttpServletResponse.
To generate an image, java provides the BufferedImage class for us to use
//Generate a picture in memory, 80 wide, 20 high, and the type is RGB BufferedImage bufferedImage = new BufferedImage(80, 20, BufferedImage.TYPE_INT_RGB); //Get this picture Graphics graphics = bufferedImage.getGraphics(); //Set colors and fonts to pictures graphics.setColor(Color.BLUE); graphics.setFont(new Font(null, Font.BOLD, 20)); //Write data on the picture, first write 12345, the abscissa is 0 and the ordinate is 20 [height] graphics.drawString("12345", 0, 20);
OK, now we create a picture in memory and write 12345. Next, we're going to write the picture to the browser. Write the picture to the browser, and java provides the picture stream [ImageIO] for us to use
//To write a picture to the browser, tell the browser that the type of echo is a picture response.setHeader("ContentType", "jpeg"); //java provides a picture stream for us to use. This is a tool class //Send the picture in. The type is jpg and write it to the browser ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
Let's visit and see what the picture looks like
It's too ugly. Let's change the background to white
//Fill the whole picture with white graphics.setColor(Color.white); graphics.fillRect(0, 0, 80, 20);
Look at the effect. It's obviously much better
OK, our picture numbers can't be written manually. The numbers should be generated randomly! This is simple. Now I want to generate 7-bit random numbers. The method of generating random numbers is as follows
private String makeNum() { Random random = new Random(); //This will generate a random number of 0-7 bits. Now the problem comes again. What if the random number is less than 7 bits? If there are not enough 7 digits, we can add them to 7 digits int anInt = random.nextInt(9999999); //Convert a number to a string String num = String.valueOf(anInt); //Judge the number of digits, and add if it is not enough StringBuffer stringBuffer = new StringBuffer(); for (int i = 0; i < 7 - num.length(); i++) { stringBuffer.append("0"); } return stringBuffer.append(num).toString(); }
If you want to generate Chinese, just find the Chinese mapping table.
Redirect jump
What is a redirect jump? Clicking a hyperlink to notify the browser to jump to another page is called redirect jump. Is to tell the browser to jump, which is very important. There are two ways to jump between pages: redirection and forwarding. As for when to use redirection and what to use forwarding, I will explain it in detail when I finish talking about the HttpServletRequest object.
Let's use the following HttpServletResponse object redirection
//Redirect to the index.jsp page response.sendRedirect("/zhongfucheng/index.jsp");
Access Servlet222 in the browser's address bar
Jump to the index.jsp page and the address bar changes
Let's look at what happened to the http protocol
From the figure, we can see two status codes, one is 302. One is 200. 302 status code represents temporary redirection in http protocol. For example, I went to the Disciplinary Committee and said: give me a leave form and I'm going home. The disciplinary committee told me: I don't have a leave form here. Go to the counselor. When I visited Sevlet222 again, I looked for servlet222. Servlet222 told the browser: I don't have the resources you want. The resources you want are in the index.jsp page. Find them yourself.
It is easy to see that redirection is achieved through 302 status code and jump address. Therefore, we can redirect and jump by setting the http header
//The setting status code is 302 response.setStatus(302); //HttpServletResponse encapsulates common status codes into static constants, so we can use SC_MOVED_TEMPORARILY stands for 302 response.setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY); //The jump address is the index.jsp page response.setHeader("Location", "/zhongfucheng/index.jsp");
In fact, the sendRedirect() method encapsulates setStatus() and setHeader(). The principle is setStatus() and setHeader()
getWriter and getOutputStream details
- getWriter() and getOutputStream() cannot be called at the same time. If called at the same time, an exception will occur
- The data written by the Servlet program to the ServletOutputStream or PrintWriter object will be obtained by the Servlet engine from the response. The Servlet engine takes these data as the body of the response message, and then combines them with the response status line and each response header to output to the client.
- After the service () method of the Servlet is completed (that is, after doPost() or doGet()), the Servlet engine will check whether the output stream object returned by the getWriter or getOutputStream method has called the close method. If not, the Servlet engine will call the close method to close the output stream object