A detailed discussion of Request and Response in JavaWeb

Insert image description here

1. Overview of Request and Response

==Request is the request object, and Response is the response object. ==These two objects are seen when we use Servlet:Insert image description here

At this point, we need to think about a question: What are the functions of the two parameters request and response?

Insert image description here
Insert image description here

  • request:ObtainRequest data
    • The browser will send HTTP requests to the backend server [Tomcat]
    • HTTP requests will contain a lot of request data [request line + request header + request body]
    • The backend server [Tomcat] will parse the data in the HTTP request and store the parsing results in an object.
    • The stored object is the request object, so we can get the relevant parameters of the request from the request object.
    • After obtaining the data, you can continue the subsequent business. For example, obtaining the user name and password can realize the related business of login operation.
  • response:set upresponse data
    • After the business is processed, the backend needs to return the result of the business processing, that is, the response data, to the front end.
    • Encapsulate response data into response object
    • The background server [Tomcat] will parse the response object and splice the result in the format of [response line + response header + response body]
    • The browser finally parses the results and displays the content in the browser for the user to browse.

We can use a case to initially experience the use of request and response objects.

@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //使用request对象 获取请求数据
        String name = request.getParameter("name");//url?name=zhangsan

        //使用response对象 设置响应数据
        response.setHeader("content-type","text/html;charset=utf-8");
        response.getWriter().write("<h1>"+name+",欢迎您!</h1>");
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println("Post...");
    }
}

After successful startup, it can be accessed through the browser, and different content can be displayed on the page according to the different parameters passed in:

Insert image description here

Summarize
Insert image description here

  • The request object is an object used to encapsulate request data.
  • The response object is an object used to encapsulate response data.

At present, we only know what these two objects are used for, so how they are implemented requires us to continue to study in depth.

2. Request object

2.1 Request inheritance system

Let’s think about a question first

  • When our Servlet class implements the Servlet interface, the parameters in the service method are ServletRequest and ServletResponse
  • When our Servlet class inherits the HttpServlet class, the parameters in the doGet and doPost methods become HttpServletRequest and HttpServletReponse

So,

  • What is the relationship between ServletRequest and HttpServletRequest?
  • Who creates the request object?
  • What APIs are provided by request? Where can I check these APIs?

First, let’s take a look at the inheritance system of Request:

Insert image description here

As can be seen from the above figure, ServletRequest and HttpServletRequest are both provided by Java, so we can open the API document provided by JavaEE. After opening, we can see:

Insert image description here

Therefore, ServletRequest and HttpServletRequest are inheritance relationships, and both are interfaces. Interfaces cannot create objects. At this time, the following problem arises:

Insert image description here

At this time, we need to use the Request inheritance systemRequestFacade:

  • This class implements the HttpServletRequest interface and also indirectly implements the ServletRequest interface.
  • The service method, doGet method or doPost method in the Servlet class are ultimately called by the Web server [Tomcat], so Tomcat provides a specific implementation class of the method parameter interface and completes the creation of the object.
  • To understand what methods are provided in RequestFacade, we can directly view the interface documents about ServletRequest and HttpServletRequest in the JavaEE API document. Because RequestFacade implements its interface, it needs to rewrite the methods in the interface.

For the above conclusion, if you want to verify it, you can write a Servlet and print the request object in the method. You can see whether the final object is RequestFacade. The code is as follows:

@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        System.out.println(request);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
    }
}

Start the server, run the accesshttp://localhost:8080/request-demo/demo2, and get the running results:

Insert image description here
Insert image description here

Summarize

  • The inheritance system of Request is ServletRequest–>HttpServletRequest–>RequestFacade
  • Tomcat needs to parse the request data, encapsulate it as a request object, and create the request object and pass it to the service method
  • Using the request object, you can check the method description in the HttpServletRequest interface of the JavaEE API document.

2.2 Request to obtain request data

HTTP request data is divided into three parts, namelyRequest line, request header, request body, how to obtain the data of these three parts respectively. First, let us first learn how to obtain the request row data?
Insert image description here

2.2.1 Get request row data

The request line contains three pieces of content, namely 请求方式, 请求资源路径, HTTP协议及版本

Insert image description here

For these three parts of content, the request object provides corresponding API methods to obtain them, as follows:

  • Get request method:GET
String getMethod()
  • Get the virtual directory (project access path):/request-demo
String getContextPath()
  • Get URL (Uniform Resource Locator):http://localhost:8080/request-demo/req1
StringBuffer getRequestURL()
  • Get URI (Uniform Resource Identifier):/request-demo/req1
String getRequestURI()
  • Get request parameters (GET method):username=zhangsan&password=123
String getQueryString()

After introducing the above methods, let’s use all the above methods through code:

/**
 * request 获取请求数据
 */
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // String getMethod():获取请求方式: GET
        String method = req.getMethod();
        System.out.println(method);//GET
        // String getContextPath():获取虚拟目录(项目访问路径):/request-demo
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        // StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
        StringBuffer url = req.getRequestURL();
        System.out.println(url.toString());
        // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
        String uri = req.getRequestURI();
        System.out.println(uri);
        // String getQueryString():获取请求参数(GET方式): username=zhangsan
        String queryString = req.getQueryString();
        System.out.println(queryString);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    }
}

Start the server and accesshttp://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123. The results obtained are as follows:

Insert image description here

2.2.2 Obtain request header data

For the request header data, the format iskey: valueas follows:

Insert image description here
So the method to get the corresponding value based on the request header name is:

String getHeader(String name)

Next, if you want to get the version information of the client browser in the code, you can use

/**
 * request 获取请求数据
 */
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        //获取请求头: user-agent: 浏览器的版本信息
        String agent = req.getHeader("user-agent");
		System.out.println(agent);
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    }
}

After restarting the server,http://localhost:8080/request-demo/req1?username=zhangsan&passwrod=123, the results obtained are as follows:

Insert image description here

2.2.3 Obtain request body data

The browser does not have a request body when sending a GET request, so the request method needs to be changed to POST. The data format in the request body is as follows:

Insert image description here

For the data in the request body, the Request object provides the following two ways to obtain the data, namely:

  • Get the byte input stream. If the front end sends byte data, such as file data, use this method.
ServletInputStream getInputStream()
该方法可以获取字节
  • Get the character input stream. If the front end sends plain text data, use this method
BufferedReader getReader()
/**
 * request 获取请求数据
 */
@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
         //获取post 请求体:请求参数
        //1. 获取字符输入流
        BufferedReader br = req.getReader();
        //2. 读取数据
        String line = br.readLine();
        System.out.println(line);
    }
}

Notice

The BufferedReader stream is obtained through the request object. When the request is completed, the request object will be destroyed. After the request object is destroyed, the BufferedReader stream will be automatically closed, so there is no need to manually close the stream here.

Summarize
Insert image description here

HTTP request data includes 请求行, 请求头 and 请求体. For these three parts, the Request object Corresponding API methods are provided to obtain the corresponding values:

  • request line
    • getMethod() gets the request method
    • getContextPath() gets the project access path
    • getRequestURL() gets the request URL
    • getRequestURI() gets the request URI
    • getQueryString() obtains the request parameters of the GET request method
  • Request header
    • getHeader(String name) obtains the corresponding value based on the request header name
  • Request body
    • Notice:Only POST requests sent by the browser have a request body.
    • If it is plain text data: getReader()
    • If it is byte data such as file data: getInputStream()
2.2.4 General method of obtaining request parameters
  • GET method:
String getQueryString()
  • POST method:
BufferedReader getReader();

(1) Send a GET request and carry the user name, receive it in the background and print it to the console

(2) Send a POST request and carry the user name, and print it to the console after receiving it in the background

What everyone needs to pay attention to here is that GET requests and POST requests receive parameters in different ways. The specific implementation code is as follows:

@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    

        String result = req.getQueryString();
        System.out.println(result);

    }
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        BufferedReader br = req.getReader();
        String result = br.readLine();
        System.out.println(result);
    }
}

The request object has encapsulated the above method of obtaining request parameters. What operations are implemented in the request method?

(1) Obtain request parameters according to different request methods. The obtained content is as follows:

Insert image description here

(2) Divide the obtained content into pieces as follows:

Insert image description here

(3) Store the split back-end data into a Map collection:

Insert image description here

Note: Because the value of the parameter may be one or multiple, the value type of the Map is a String array.

Based on the above theory, the request object provides us with the following methods:

  • Get all parameter Map collection
Map<String,String[]> getParameterMap()
  • Get parameter value by name (array)
String[] getParameterValues(String name)
  • Get parameter value by name (single value)
String getParameter(String name)

2.4 The problem of Chinese garbled request parameters

2.4.1 POST request solution
  • Analyze the reasons for Chinese garbled characters:
    • The request parameter of POST is to obtain the data in the stream through getReader() of request.
    • The encoding used by TOMCAT when obtaining the stream is ISO-8859-1
    • ISO-8859-1 encoding does not support Chinese, so garbled characters will appear.
  • solution:
    • The encoding format of the page settings is UTF-8
    • Set the encoding of TOMCAT before obtaining the stream data to UTF-8
    • Set the encoding through request.setCharacterEncoding("UTF-8"), UTF-8 can also be written in lowercase

The modified code is:

/**
 * 中文乱码问题解决方案
 */
@WebServlet("/req4")
public class RequestDemo4 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        //1. 解决乱码: POST getReader()
        //设置字符输入流的编码,设置的字符集要和页面保持一致
        request.setCharacterEncoding("UTF-8");
       //2. 获取username
       String username = request.getParameter("username");
       System.out.println(username);
    }

    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}
2.4.2 GET request solution
  • The way the GET request obtains the request parameters isrequest.getQueryString()
  • The way to obtain request parameters for POST request isrequest.getReader()
  • request.setCharacterEncoding("utf-8") is to set the encoding of the request processing stream
  • The getQueryString method does not obtain data through the stream

Therefore, the GET request cannot solve the Chinese garbled code problem by setting the encoding. Then the problem comes again, how to solve the Chinese garbled code in the GET request?

  1. First we need to analyze the reasons why GET requests appear garbled:

Insert image description here

(1) The browser sends requests and data to the backend server (Tomcat) through the HTTP protocol

(2) During the process of sending HTTP, the browser will perform a URL for the Chinese data.coding

(3) When encoding the URL, the UTF-8 method specified by the page <meta> tag will be used for encoding. 张三 The encoded result for%E5%BC%A0%E4%B8%89

(4) After receiving %E5%BC%A0%E4%B8%89, the background server (Tomcat) will perform the URL according to ISO-8859-1 by defaultdecoding

(5) Since the formats used for encoding and decoding are different, the data obtained in the background will be garbled.

What is URL encoding and what is URL decoding?

coding:

java.net.URLEncoder.encode("需要被编码的内容","字符集(UTF-8)")

decoding:

java.net.URLDecoder.decode("需要被解码的内容","字符集(UTF-8)")

Next let’s encode and decode张三

public class URLDemo {

  public static void main(String[] args) throws UnsupportedEncodingException {
        String username = "张三";
        //1. URL编码
        String encode = URLEncoder.encode(username, "utf-8");
        System.out.println(encode); //打印:%E5%BC%A0%E4%B8%89

       //2. URL解码
       //String decode = URLDecoder.decode(encode, "utf-8");//打印:张三
       String decode = URLDecoder.decode(encode, "ISO-8859-1");//打印:`å¼ ä¸ `
       System.out.println(decode);
    }
}

At this point, we can analyze the reason why the Chinese parameters of the GET request are garbled.

  • The browser encodes the Chinese parameters in the URL according toUTF-8
  • Tomcat decoded the URL of the obtained contentISO-8859-1
  • There will be garbled characters on the classå¼ ä¸‰ in the console, and the last digit is a space

The specific implementation steps are:

1. Obtain the byte array corresponding to garbled code according to ISO-8859-1 encodingå¼ ä¸‰

2. Obtain the string corresponding to the byte array according to UTF-8 encoding

The implementation code is as follows:

public class URLDemo {

  public static void main(String[] args) throws UnsupportedEncodingException {
        String username = "张三";
        //1. URL编码
        String encode = URLEncoder.encode(username, "utf-8");
        System.out.println(encode);
        //2. URL解码
        String decode = URLDecoder.decode(encode, "ISO-8859-1");

        System.out.println(decode); //此处打印的是对应的乱码数据

        //3. 转换为字节数据,编码
        byte[] bytes = decode.getBytes("ISO-8859-1");
        for (byte b : bytes) {
            System.out.print(b + " ");
        }
		//此处打印的是:-27 -68 -96 -28 -72 -119
        //4. 将字节数组转为字符串,解码
        String s = new String(bytes, "utf-8");
        System.out.println(s); //此处打印的是张三
    }
}

Another thing that needs to be explained is thatAfter Tomcat8.0, the problem of garbled GET requests has been solved, and the default decoding method is set to UTF-8.

Summarize
Insert image description here

  1. Solution to Chinese garbled characters
  • If there are Chinese characters in the parameters of POST requests and GET requests, Chinese garbled characters will appear when receiving data in the background.

    GET requests will not appear in Tomcat 8.0 and later versions.

  • The POST request solution is: Set the encoding of the input stream

    request.setCharacterEncoding("UTF-8");
    注意:设置的字符集要和页面保持一致
    
  1. URL encoding implementation:
  • coding:

    URLEncoder.encode(str,"UTF-8");
    
  • decoding:

    URLDecoder.decode(s,"ISO-8859-1");
    

2.5 Request request forwarding

  1. Request forwarding (forward): a resource jumping method within the server.

Insert image description here

(1) The browser sends a request to the server, and the corresponding resource A in the server receives the request.

(2) After resource A processes the request, it sends the request to resource B.

(3) After resource B is processed, the result will be responded to the browser.

(4) The process of requesting from resource A to resource B is calledRequest forwarding

  1. How to implement request forwarding:
req.getRequestDispatcher("资源B路径").forward(req,resp);

3. Response object

After explaining the Request object earlier, let’s go back to the picture at the beginning:

Insert image description here

  • Request: Use the request object toObtainRequest data
  • Response: Use the response object toset upresponse data

The inheritance system of Response is also very similar to that of Request:

Insert image description here

3.1 Introduction to Response setting response data function

HTTP response data is divided into three parts, namelyResponse line, response header, response body, for these three parts of data, what methods does the response object provide to set it?

  1. response line

Insert image description here

For response headers, it is more commonly used to set the response status code:

void setStatus(int sc);
  1. response header

Insert image description here

Set response header key-value pairs:

void setHeader(String name,String value);
  1. response body

Insert image description here

For the response body, it is written to the browser through character and byte output streams.

Get the character output stream:

PrintWriter getWriter();

Get byte output stream

ServletOutputStream getOutputStream();

After introducing these methods, we will use these methods through cases later. First, we will complete the development of the redirection function.

3.2 Respones request redirection

  1. Response redirection (redirect): a resource jumping method.

Insert image description here

(1) The browser sends a request to the server, and the corresponding resource A in the server receives the request.

(2) Resource A cannot handle the request now, and will respond to the browser with a 302 status code + a path to access resource B.

(3) When the browser receives the response status code 302, it will resend the request to the access address corresponding to the location to access resource B.

(4) Resource B processes the request after receiving it and finally responds to the browser. This whole process is calledRedirect

  1. How to implement redirection:
resp.setStatus(302);
resp.setHeader("location","资源B的访问路径");
  1. Redirect Features
  • Browser address bar path sending changes

    When redirecting access, the address will change because there are two requests sent by the browser.

    Insert image description here

  • Can be redirected to resources in any location (service content, external)

    Because the first response result contains the path to which the browser will jump next, this path can be a resource at any location.

  • Two requests, cannot use request to share data on multiple resources

    Because the browser sent two requests, which are two different request objects, data cannot be shared through the request object.

End of introductionrequest redirectandRequest forwardingIn the future, we need to put these two together and compare them:

Insert image description here

Which one to use in the future still needs to be decided based on the specific business.

3.3 Response response character data

To write character data back to the browser, we need two steps:

  • Get the character output stream through the Response object: PrintWriter writer = resp.getWriter();

  • Write data through the character output stream: writer.write("aaa");

Next, we implement the actual application of response character data through some cases:

Returns a simple stringaaa

/**
 * 响应字符数据:设置字符数据的响应体
 */
@WebServlet("/resp3")
public class ResponseDemo3 extends HttpServlet {
    
    
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        response.setContentType("text/html;charset=utf-8");
        //1. 获取字符输出流
        PrintWriter writer = response.getWriter();
		 writer.write("aaa");
    }
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
    
    
        this.doGet(request, response);
    }
}

One final word

Thank you all for reading. The article is compiled through online resources and my own learning process. I hope it can help everyone.

With little talent and little knowledge, it is inevitable that there will be mistakes. If you find any mistakes, you can point them out and I will correct them.

Insert image description here

Guess you like

Origin blog.csdn.net/m0_69383623/article/details/128494273