Servlet Part 3 [introduction to request and response, common applications of response]

Keywords: servlet request response

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

  1. getWriter() and getOutputStream() cannot be called at the same time. If called at the same time, an exception will occur
  2. 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.
  3. 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

Posted by alco19357 on Fri, 22 Oct 2021 08:16:34 -0700