SpringMVC study notes -05 processor method return value

1. ModelAndView

    The most commonly used return value type, Model is used to store data, and is finally placed in the request scope; View represents the view, and the framework uses forward to jump to the view. If the result of request processing requires both data and view, it is more convenient to use ModelAndView. If you only need data and don't need page jumps (for example, Ajax asynchronous response to update partial data); or only need page jumps and don't need to pass data, it is not appropriate to use ModelAndView at this time, and there will always be some redundant.

    @RequestMapping(value = "/noLimit.do")
    public ModelAndView doNoLimit(){
        ModelAndView modelAndView = new ModelAndView();

        // 存放数据 框架会自动将数据放到request作用域
        modelAndView.addObject("msg","hello-nolimit");

        modelAndView.setViewName("show");

        return modelAndView;
    }

2. String

    When the view parser is configured in the framework, the returned String result will be regarded as the logical view name, and the address will be formed after the view parser is spliced; if the view parser is not configured, then the returned String will be regarded as the view path.

The view resolver is configured:

    <p>处理器方法返回String表示视图名称</p>
    <form action="test/returnString-view.do" method="post">
        姓名:<input type="text" name="name"><br>
        年龄:<input type="text" name="age"><br>
        <input type="submit" value="提交">
    </form>
    @RequestMapping(value = "/returnString.do")
    public String doReturnString(HttpServletRequest request, @RequestParam(value = "name") String name, @RequestParam(value = "age") Integer age){
        System.out.println("name = " + name + ", age = " + age);
        // 手动将数据添加到request对象中
        request.setAttribute("name",name);
        request.setAttribute("age",age);
        return "showProperty";
    }

At this point, if we return to the attempt path:

    @RequestMapping(value = "/returnString.do")
    public String doReturnString(HttpServletRequest request, @RequestParam(value = "name") String name, @RequestParam(value = "age") Integer age){
        System.out.println("name = " + name + ", age = " + age);
        // 手动将数据添加到request对象中
        request.setAttribute("name",name);
        request.setAttribute("age",age);
        return "/WEB-INF/view/showProperty.jsp";
    }

    

Obviously, the framework treats the String result we return as the logical view name, which is spliced ​​by the view parser.

Note: When we return the String type, if we need to forward data at the same time, we must manually add the object to the request object.

3.void

    Void is used when there is no need to jump to other views after the request is processed. For example, it can be used to respond to Ajax asynchronous requests: output data through HttpServletResponse and respond to Ajax requests.

1. Import the jquery library file

2. Ajax processing data uses json format, we also need to import the dependency package of json to wrap the string into json format

    <!--jackson-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>

3. Set the trigger event to initiate the Ajax request in the page

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>Title</title>
    <script type="text/javascript" src="js/jquery-3.5.1.js"></script>
    <script type="text/javascript">
        $(function () {
            $("button").click(function () {
                $.ajax({
                    url:"test/returnVoid_ajax.do", // 请求路径
                    data:{ // 请求的数据
                        name:"zzt",
                        age:21
                    },
                    type:"post", // 请求方式
                    dataType:"json", // 返回数据的解析方式 json为把json格式的字符串解析为对象
                    success:function (resp) { // resp结果数据解析后的结果
                        alert(resp);
                    }
                })
            })
        })
    </script>
</head>
<body>
    <button id="btn">发起Ajax请求</button>
</body>
</html>

4. In the processor method, use the response object to return data

    @RequestMapping(value = "/returnVoid_ajax.do")
    public void doReturnVoid(HttpServletResponse response,@RequestParam("name") String name, @RequestParam("age") Integer age) throws IOException {
        System.out.println("name = " + name + ", age = " + age);
        // 1.(假装)调用业务方法获取数据
        Student student = new Student(name, age);
        // 2.将结果转换成json格式的字符串
        String json = "";
        if(student != null){
            ObjectMapper objectMapper = new ObjectMapper();
            json = objectMapper.writeValueAsString(student);
            System.out.println("对象转换为json格式为 : " + json);
        }
        // 3.设置相应格式,响应请求
        response.setContentType("application/json;charset=utf-8");
        PrintWriter printWriter = response.getWriter();
        printWriter.println(json);
        printWriter.flush();
        printWriter.close();
        return;
    }

5. Execution results

Jquery parses the returned string into an object in json format and assigns it to the receiving parameter. Of course, we can also retrieve the value in the object.

        success:function (resp) { // resp结果数据解析后的结果
                alert("name = " + resp.name + " age = " + resp.age);
        }

It is worth noting that the dataType attribute, which is used to specify the desired result type, is declared in the request header:

But we have already specified in the code that the format of the data is a json string for the response header, and jquery will also try to parse it into a json object (using the JSON.parse method):

4.Object

        In the third method, for the response to the Ajax request, we need to permanently convert the object into a json string, and use the response object to return the data. This is a common redundant operation. Of course, we can also extract the common part through the tool class, but SpringMVC also provides another way, which is to use the object as the return value. If we use this method, even if the String type is returned, the framework will not treat it as a view name or a logical view name, but only as the passed data.

        @ResponseBody annotation will put the result data into the response body.

A. Pass ordinary object types

1. Add jackson dependency

Jaskson is the default json dependency of Spring MVC.

    <!--jackson-->
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-core</artifactId>
      <version>2.9.0</version>
    </dependency>
    <dependency>
      <groupId>com.fasterxml.jackson.core</groupId>
      <artifactId>jackson-databind</artifactId>
      <version>2.9.0</version>
    </dependency>

2. Configure annotation-driven <mvc:annotation-driven/>

    <!--配置注解驱动-->
    <mvc:annotation-driven/>

Note that there is also annotation-driven in Spring, here we are going to use the annotation-driven in SpringMVC, don't make a mistake.

<mvc:annotation-driven> After adding the configuration, the implementation class of the HttpMessageConverter (message converter) interface will be created automatically.

We commonly use StringHttpMessageConverter (created by default) and MappingJackson2HttpMessageConverter (created only after the annotation driver is configured).

HttpMessageConverter: The message converter interface defines the method for converting java objects into json, xml, binary stream and other data formats. It has many implementation classes, which are responsible for the conversion of java objects.

Conversion steps: 1. Call the canWrite method defined in the interface to determine whether the conversion can be performed

                  2. Call the write method defined in the interface to complete the data format conversion

This corresponds to the part we just implemented manually:

        String json = "";
        if(student != null){
            ObjectMapper objectMapper = new ObjectMapper();
            json = objectMapper.writeValueAsString(student);
            System.out.println("对象转换为json格式为 : " + json);
        }

3. Add @ResponseBody to the processor method

@ResponseBody is responsible for putting the output into the response body, in addition to the method annotated with @ResponseBody, the return value will not be used as the logical view name or view path (specifically String).

    @ResponseBody
    @RequestMapping(value = "/returnVoid_ajax.do")
    public Student doReturnVoid(HttpServletResponse response,@RequestParam("name") String name, @RequestParam("age") Integer age) throws IOException {
        System.out.println("name = " + name + ", age = " + age);

        Student student = new Student(name, age);
        return student;
    }

This corresponds to the part we just implemented manually:

        response.setContentType("application/json;charset=utf-8");//响应数据格式
        PrintWriter printWriter = response.getWriter();
        printWriter.println(json);
        printWriter.flush();
        printWriter.close();

4. Execution results

5. Detailed execution steps

1. The container will use a List to store all the message converters ArrayList<HttpMessageConverter> (After the annotation driver takes effect, the MappingJackson2HttpMessageConverter object will be created and put into the list)

2. For the returned Student object, the framework will traverse all message converters in the list and call their canWrite() method to determine which message converter implements the class object that can convert the Student object

3. After determining the message converter object, use its write() method to complete the conversion (Student is an object and needs to be converted to json format)

4. @ResponseBody annotation means that the returned result is placed in the response

B. Pass collection

    @ResponseBody
    @RequestMapping(value = "/returnVoid_ajaxList.do")
    public List<Student> doReturnVoidList(HttpServletResponse response, @RequestParam("name") String name, @RequestParam("age") Integer age) throws IOException {
        System.out.println("name = " + name + ", age = " + age);

        List<Student> students = new ArrayList<>();
        Student student = new Student(name, age);
        students.add(student);
        student = new Student("辅助",20);
        students.add(student);
        return students;
    }

What is returned at this time is an array of json strings, we can use the loop function that comes with jquery to traverse the value:

                $.ajax({
                    url:"test/returnVoid_ajaxList.do", // 请求路径
                    data:{ // 请求的数据
                        name:"zzt",
                        age:21
                    },
                    type:"post", // 请求方式
                    dataType:"json", // 要求返回的数据类型是json格式的字符串
                    success:function (resp) { // resp结果数据解析后的结果
                        //alert("name = " + resp.name + " age = " + resp.age);
                        $.each(resp,function (i,student) {
                            alert(student.name + "--" + student.age)
                        })
                    }
                })

C. The passed String is only used as ordinary text data

    @ResponseBody
    @RequestMapping(value = "/returnStringAjax.do")
    public String doReturnStringAjax(){
        return "返回的是字符串不是数据";
    }

We use ajax to submit the request:

                $.ajax({
                    url:"test/returnStringAjax.do", // 请求路径
                    data:{ // 请求的数据
                        name:"zzt",
                        age:21
                    },
                    type:"post", // 请求方式
                    dataType:"json", // 要求返回的数据类型是json格式的字符串
                    success:function (resp) { // resp结果数据解析后的结果
                        //alert("name = " + resp.name + " age = " + resp.age);
                        /*$.each(resp,function (i,student) {
                            alert(student.name + "--" + student.age)
                        })*/
                        alert("返回文本数据:" + resp);
                    }
                })

There is no pop-up window at this time, but the ajax request is indeed successfully sent and the response is received. The key is that because we set the requirement that the return type is json format, but we actually return String, which is not performed by the method provided by Jackson Converted, so a format mismatch occurred and execution was interrupted. The solution is to change the value of dataType to text, indicating that the result is text data.

Now we have encountered the second problem. There is no error in execution but the data cannot be parsed:

Observing the response header, it is found that the default encoding format in the response is ISO-8859-1. This encoding format cannot parse Chinese normally. We need to manually set the encoding format to utf-8: [Note] We have configured it before Filtered, but the data returned by the Ajax request will not pass the filter, so it needs to be set manually.

Use the produces attribute of @RequestMapping to set the encoding format ContentType:

    @ResponseBody
    @RequestMapping(value = "/returnStringAjax.do", produces = "text/plain;charset=utf-8")
    public String doReturnStringAjax(){
        return "返回的是字符串不是数据--SpringMVC";
    }

[Note]: The return value of String type is converted by StringHttpMessageConverter.

 

 

 

 

 

Guess you like

Origin blog.csdn.net/qq_39304630/article/details/112919407