Servlet gets request data [HttpServletRequest]


When Tomcat reads the HTTP request (string) through the Socket API, and parses the string into an
HttpServletRequest object according to the format of the HTTP protocol

method to understand

Some methods:

method describe
String getProtocol() Returns the name and version of the requested protocol
String getMethod() Returns the name of the HTTP method of the request, for example, GET, POST, or PUT
String getRequestURI() From the protocol name up to the query string of the first line of an HTTP request, returns the portion of the request's URL
String getContextPath() Returns the part of the request URI that indicates the request context
String getQueryString() Returns the query string contained in the request URL after the path
String getParameter(Stringname) Returns the value of the request parameter as a string, or null if the parameter does not exist
String[] getParameterValues(Stringname) Returns an array of String objects containing the values ​​of all the given request parameters, or null if the parameter does not exist

Notice: The request object is the content received by the server and should not be modified; therefore, the above methods are only "read" methods, not "write" methods

Information about various aspects of a request can be obtained through the above methods

Example:

insert image description here

@WebServlet("/request")
public class RequestServletStudy extends HttpServlet {
    
    
    // 访问路径: request?username=hh&password=123
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 此处是后台打印
        System.out.println("请求协议名:" + req.getProtocol());
        System.out.println("请求方法名:" + req.getMethod());
        System.out.println("应用上下文路径/应用名:" + req.getContextPath());
        System.out.println("资源路径/ServletPath:" + req.getServletPath());
        System.out.println("请求头中键为Host的值:" + req.getHeader("Host"));

        //响应给客户端的内容
        resp.getWriter().println("请求信息已获取,在idea后端控制台查看");
    }
}

After running:

insert image description here
Click the link to jump, and 404 will pop up at this time, you need to add /request.html after the url

insert image description here
Click get to jump:

insert image description here

Introduction to key methods

1. getParamter method

1). Get the data in url QueryString

@WebServlet("/request")
public class RequestServletStudy extends HttpServlet {
    
    
    // 访问路径: request?username=hh&password=123
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // 此处是后台打印
        System.out.println("请求协议名:" + req.getProtocol());
        System.out.println("请求方法名:" + req.getMethod());
        System.out.println("应用上下文路径/应用名:" + req.getContextPath());
        System.out.println("资源路径/ServletPath:" + req.getServletPath());
        System.out.println("请求头中键为Host的值:" + req.getHeader("Host"));
       
        //重点
        //通过键获取值: 1.queryString;
        // 访问路径: request?username=hh&password=123
        System.out.println("username: " + req.getParameter("username"));
        System.out.println("password: " + req.getParameter("password"));

        //响应给客户端的内容
        resp.getWriter().println("请求信息已获取,在idea后端控制台查看");
        
    }
}

insert image description here
You can view the printed content in the backend:

insert image description here
View through fiddler packet capture:

insert image description here

Note: When making an http request, the url will be encoded, and to obtain the Chinese, spaces, and special characters in the queryString, it needs to be decoded

For example, the form form is submitted, the request method is not set, the default is GET, the control in the form will be set to the queryString with the name as the key and the content entered/selected by the user as the value

<body>
    <h3>get with query string</h3>
    <form action="request">
        <input type="text" name="username" placeholder="请输入用户名">
        </br>
        <input type="password" name="password" placeholder="请输入密码">
        </br>
        <input type="submit" value="提交">
    </form>  
</body>

Others are consistent with the above examples

Since the front-end code can take effect immediately, there is no need to restart, just refresh the page directly:

insert image description here
View the backend print content:

insert image description here

2). Get the form format in the body

Form format: the data in the body, the format is the same as queryString

Modify the front-end code:

<h3>表单提交</h3>
<form action="request" method="post">
    <input type="text" name="username" placeholder="请输入用户名">
    </br>
    <input type="password" name="password" placeholder="请输入密码">
    </br>
    <input type="submit" value="提交">
</form>  

Refresh the page and submit the form:

insert image description here
After submitting, you will find that the method is not allowed, and a 405 error occurs
. The back-end code is the GET method, and our front-end code is written in post

Thinking: How to make it support the post method at the same time without changing the doGet method? ?

// 既支持 get, 也支持 post
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
    doGet(req, resp);
}

Reboot, then enter username and password:

insert image description here

View backend output:

insert image description here
Observing the above picture, you will find that there are garbled characters.
Note: The content in the body also has an encoding format, which needs to be set to display normally:

req.setCharacterEncoding("utf-8"); //设置body解析的编码格式
System.out.println("username: " + req.getParameter("username"));
System.out.println("password: " + req.getParameter("password"));

Restart, refresh the page to view:

At this point, there is no more garbled characters:

insert image description here

3). Get data of simple data type in form-data

Modify the front-end code:

<h3>fomr-data格式</h3>
<form action="request" enctype="multipart/form-data" method="post">
    <input type="text" name="username" placeholder="请输入用户名">
    </br>
    <input type="password" name="password" placeholder="请输入密码">
    </br>
    <input type="submit" value="提交">
</form> 

refresh page:

insert image description here
View backend output:

insert image description here
View through packet capture:

insert image description here
Add backend code:

@WebServlet("/form-data")
@MultipartConfig //form-data 格式需要使用这个注解
public class FormDataServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // request.getParameter 也可以获取 form-data 中的简单类型数据
        req.setCharacterEncoding("utf-8"); // 设置body解析的编码格式
        System.out.println("username: " + req.getParameter("username"));
        System.out.println("password: " + req.getParameter("password"));
    }
}

Reboot, refresh the page:

insert image description here
insert image description here

Key points: http request data, storage location

  1. url queryString
  2. body (various types)

2. getPart method

Obtain the uploaded file in the form-data format If the uploaded
file is obtained directly using getParameter(), it cannot be obtained

Example:

<h3>fomr-data格式 上传文件</h3>
<form action="form-data" enctype="multipart/form-data" method="post">
    <input type="text" name="username" placeholder="请输入用户名">
    </br>
    <input type="password" name="password" placeholder="请输入密码">
    </br>
    选择头像: <input type="file" name="head" accept="image/*">
    <input type="submit" value="提交">
</form> 
@WebServlet("/form-data")
@MultipartConfig //form-data 格式需要使用这个注解
public class FormDataServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        // request.getParameter 也可以获取 form-data 中的简单类型数据
        req.setCharacterEncoding("utf-8"); // 设置body解析的编码格式
        System.out.println("username: " + req.getParameter("username"));
        System.out.println("password: " + req.getParameter("password"));
        System.out.println("head[文件无法通过getParameter获取]: " + req.getParameter("head"));
    }
}

insert image description here
Capture packets through fiddler:

insert image description here
The files uploaded in form-data must be obtained through getPart, and getParameter cannot be obtained
In fact, simple types of data can also be obtained using getPart, but it is also necessary to call the part object api to obtain the content, which is more complicated

  1. Get the binary data of the uploaded file, convert it to a string and print it
    (read through the input stream of the part object)
Part head = req.getPart("head");
// 获取上传文件的二进制数据,转换为字符串打印
InputStream is = head.getInputStream(); // 获取输入流(里边包含了数据)
// 输入流.available 返回包含的数据长度
byte[] bytes = new byte[is.available()];
// 从输入流中把数据读取到 byte[]中,字节数组对象就有了这些数据
is.read(bytes);
System.out.println(new String(bytes,"utf-8"));

The binary data printed in the background, some screenshots:

insert image description here

  1. Directly save the file uploaded by the client to the local server (do not read, save it directly)
    Note that the above code should be commented out, otherwise it cannot be used
// 直接把客户端上传的文件,保存在服务器本地
head.write("D://"+head.getSubmittedFileName());

Note: If this path already has this file, an error will be reported

Restart, refresh the page, enter the user name and password, select the picture, and submit it. After success, you will find the picture you just saved in the corresponding directory

insert image description here

3. getInputStream method

Get the data of the body of the request body (the data is included in the input stream), no matter what format, as long as it is in the body, you can get it; but the form format does not need to be obtained in this way (it is more troublesome, and you have to parse it yourself multiple sets of key-value pairs)
Commonly used scenarios: json format

Front-end code:

<body>
    <h3>ajax提交json格式</h3>
    <input type="text" id="ajax_username" placeholder="请输入用户名">
    </br>
    <input type="password" id="ajax_password" placeholder="请输入密码">
    </br>
    <button onclick="ajax_submit()">提交</button>
</body>

<script>
    function ajax_submit(){
    
    
        let username = document.querySelector("#ajax_username");
        let password = document.querySelector("#ajax_password");
        let json = {
    
    
            username: username.value, // 键为username,值为对象的value属性
            password: password.value,
        };
        ajax({
    
    
            url: "ajax-json-servlet",
            method: "post",
            //body上为 json格式的字符串
            contentType: "application/json",
            // JSON.stringify(json) 是将一个json对象序列化成一个字符串,格式是json格式
            body: JSON.stringify(json),
            callback: function(status,resp){
    
    
                alert("后端返回的内容: " + resp)
            }
        });
    }
    function ajax(args){
    
    //var ajax = function(){}
        let xhr = new XMLHttpRequest();
        // 设置回调函数
        xhr.onreadystatechange = function(){
    
    
            // 4: 客户端接收到响应后回调
            if(xhr.readyState == 4){
    
    
                // 回调函数可能需要使用响应的内容,作为传入参数
                args.callback(xhr.status, xhr.responseText);
            }
        }
        xhr.open(args.method, args.url);
        //如果args中,contentType属性有内容,就设置Content-Type请求头
        if(args.contentType){
    
    //js中,if判断,除了判断boolean值,还可以判断字符串,对象等,有值就为true
            xhr.setRequestHeader("Content-Type", args.contentType);
        }
        //如果args中,设置了body请求正文,调用send(body)
        if(args.body){
    
    
            xhr.send(args.body);
        }else{
    
    //如果没有设置,调用send()
            xhr.send();
        }
    }
</script>

Backend code:

@WebServlet("/ajax-json-servlet")
public class AjaxJsonServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req.setCharacterEncoding("utf-8"); //获取请求body数据,先设置编码
        // request.getInputStream 获取请求正文的数据 (不管Content-Type是什么类型,都可以获取)
        // 表单格式也可以使用此 API 获取,比较复杂
        // json是使用这个 api 比较典型的场景
        InputStream is = req.getInputStream();
        //先定义一个 byte 数组
        int len = req.getContentLength(); //也可以通过getHeader("Content-Length")获取,只是返回的是字符串相对麻烦一点
        byte[] bytes = new byte[len];
        is.read(bytes);
        System.out.println("获取的json数据:" + new String(bytes,"utf-8"));
    }
}

Reboot, refresh the page:

insert image description here
Enter username and password, submit:

insert image description here

Backend print content:

insert image description here

Packet capture can be checked:

insert image description here

In fact, it is not convenient to get the entire json string, such as: To judge whether the account password is correct or not
: so far, the JSON data obtained by the server is still a whole String type, if you want to get the username and password The specific value needs to be further parsed with the JSON library

Common way: use third-party library
You can convert a json string into a java object;
you can also convert a java object into a json string (useful when responding)

Introduce the Jackson library for JSON parsing

  1. Search for Jackson Databind in Central Repository

insert image description here

  1. Add the dependency configuration in the central warehouse to pom.xml
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.12.3</version>
</dependency>

insert image description here

Modify the backend code:

@WebServlet("/ajax-json-servlet")
public class AjaxJsonServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req.setCharacterEncoding("utf-8"); //获取请求body数据,先设置编码
        InputStream is = req.getInputStream();
        ObjectMapper mapper = new ObjectMapper();
        // 简单暴力 直接转换为 map对象
        Map json = mapper.readValue(is, Map.class);
        System.out.println("获取的json字符串转换的map:" + json);
    }
}

Restart, refresh the page, submit data, and view the print results:

insert image description here
Map is actually not very convenient to use. If you want to use the specified string key to get the value, then modify the back-end code:

@WebServlet("/ajax-json-servlet")
public class AjaxJsonServlet extends HttpServlet {
    
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
    
        req.setCharacterEncoding("utf-8"); //获取请求body数据,先设置编码
        InputStream is = req.getInputStream();
        ObjectMapper mapper = new ObjectMapper();
        User user = mapper.readValue(is,User.class);
        System.out.println("获取的json字符串转换的map:" + user);
    }
    // 把 json字符串转换为 java对象,需要某个键的名称和成员变量名一样(类型也是)
    static class User{
    
    
        private String username;
        private String password;
        
        @Override
        public String toString() {
    
    
            return "User{" +
                    "username='" + username + '\'' +
                    ", password='" + password + '\'' +
                    '}';
        }
        
        // 提供getter 和 setter方法
        public String getUsername() {
    
    
            return username;
        }
        public String getPassword() {
    
    
            return password;
        }
        public void setUsername(String username) {
    
    
            this.username = username;
        }
        public void setPassword(String password) {
    
    
            this.password = password;
        }
    }
}

Restart, refresh the page, submit data, and view the print results:

insert image description here
Generally convert json strings to custom types, but you need to pay attention:To convert a json string to a java object, the name of a key needs to be the same as the member variable name (and the type)

insert image description here

Guess you like

Origin blog.csdn.net/m0_47988201/article/details/123309223