Spring MVC Practical Tutorial Series (3)--Response Mode

     The previous section described the way that spring mvc receives client parameters and solved the "in" problem. This section will describe how the server generates a response to the client, that is, the "out" problem.

 

     (1) Directly returns a string specifying the view name.

This is the method that has been encountered in the example before. For example, this method returns "index", which means that there is a view file containing the string, and then add the view name to the view name through the view parser in the spring mvc configuration file. Add the prefix and suffix to get the path and name of the view in the server. That is, after the controller is executed, it will turn to execute /WEB-INF/jsp/index.jsp under the web application and send the generated HTML as a response to the client for reception.

@RequestMapping("/queryString")
    public String test1(String userName,String userPass,Integer age){
        System.out.println("User name: "+userName+", password: "+userPass+" Age: "+ age);
        return "index";
    }

<!--View resolver-->

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
            id="internalResourceViewResolver">
        <!-- 前缀 -->
        <property name="prefix" value="/WEB-INF/jsp/" />
        <!-- 后缀 -->
        <property name="suffix" value=".jsp" />
    </bean>

   In practical applications, it is usually meaningless to jump directly to a view. Since it is MVC, it is usually necessary to carry data (ie, model) to the view, so how to put the required data objects in the response? You can add a Map type parameter to the method to save the part of our model, whose key is String type and value is Object type. Recall that when we jump to the view in the servlet, we use four scope objects to pass data to the view. These four scope objects are essentially a Map object with String as key and Object as value, so spring mvc design It is completely reasonable to become a Map, and the default scope is request. The sample code is as follows:

@RequestMapping("/test1")
    public String test1(Map<String, Object> resultMap){
        User user = new User();
        user.setUserName("张三");
        user.setAge(12);
       

      // save the model data in the result set
        resultMap.put("user", user);
        return "index";
    }

Note that here we manually create a User object and assign a value to it. In practical applications, the data object should come from the business logic component. Then in index.jsp, you can use EL to display the content of the user object ${user}, of course, you can also use the embedded java expression <%=request.getAttribute("user")%> to print, of course, it must be repeated Write down the toString method of the User class, otherwise the address will be printed. If you observe the browser address bar and find that the URL has not changed, it means that spring mvc uses the server-side jump method by default instead of responding to redirection.

 

  (2) Return the ModelAndView object

    Spring mvc provides the ModelAndView object to encapsulate the view logic name with the model data part, so that the method can directly return an encapsulated ModelAndView without providing Map parameters. An example is as follows:

@RequestMapping("/test2")
    public ModelAndView test2(){
        ModelAndView mav = new ModelAndView();
        // set view logical name
        mav.setViewName("index");
        // build model data
        User user = new User();
        user.setUserName("Li Si");
        user.setAge(21);
        // Add the model to the ModelAndView instance
        mav.getModel().put("user", user);
        return mav;
    }

As you can see, the model part is still a Map of <String, Object>. Of course, in addition to calling its member methods to set the view and model separately, you can also use the ModelAndView constructor to bind the view and model at one time when the object is created. For example, the above code can be changed to this:

@RequestMapping("/test2")
    public ModelAndView test2() {
        // 构建模型数据
        User user = new User();
        user.setUserName("wang5");
        user.setAge(24);
        ModelAndView mav = new ModelAndView("index", "user", user);

        return mav;
    }

The effect is the same.

 

(3) For Ajax requests, return ordinary strings

   If it is an Ajax request, you cannot return a view component, but return a part of the data separately, for example, the simplest is a string, please see the sample code:    @RequestMapping("/test3")
   @ResponseBody
    public String test3(String name ) {
        System.out.println("Parameter: "+name);
        return "Your name is: " + name;
    }

It can be seen that this method is almost the same as the previous method structure of the direct jump view, the difference is that an annotation called @ResponseBody is added to the method, which indicates that the return value (string) of the method is no longer a The view name is directly returned to the client as the response body, and there is no need to use HttpServletResponse. APIs such as PrintWriter only need to add an annotation to complete an Ajax response. The client code is as follows:

<script src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
<script type="text/javascript">
    $(function(){
        //按钮单击时执行
        $("#testBtn").click(function(){
            
            $.post("${pageContext.request.contextPath}/jumpToView/test3", {name:"张三" },
                function (data){
       
                    $("#result").html(data);

                });
            });
    });
</script>
</head>
<body>
    <input type="button" id="testBtn" value="ajax请求" />
    <span id="result"></span>
</body>

 

(4) Return JSON data

   For a simple ajax request, it is acceptable to return a simple String directly, but in most cases, complex data such as an object or a collection of objects needs to be returned. In this case, a Json string is often used as the response. In addition, in today's popular mobile Internet, Json is usually used in the interaction between the server and various APPs. In this section, let's take a brief look at how to convert objects or object collections into json strings in spring mvc. Here we use the jackson framework to assist the conversion process.

   1. Add the jackson library dependency to the pom:

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

 

   2. Convert a single object into json, the sample code is as follows:

   /**
     * Use jackson to convert a single object to a json string return
     * @param name
     * @return
     */
    @RequestMapping("/test4")
    @ResponseBody
   public String test4(String name,Integer age) {
        System.out.println( "parameter 1: "+name+", parameter 2: "+age); ObjectMapper om = new ObjectMapper();         User user = new User();         user.setUserName(name);         user.setAge(age);         // object Transfer out json string         String jsonResult = "";         try { jsonResult = om.writeValueAsString(user);             System.out.println("The converted Json string is: "+jsonResult);         } catch (JsonProcessingException e) {
       



       



           


            // TODO Auto-generated catch block
            e.printStackTrace();
        }        return jsonResult;    }
       
       

It can be seen that it is very simple to use jackson to directly convert objects and json strings. You only need to use the writeValueAsString method of an ObjectMapper. Please observe the results by yourself.

 Note: still don't forget the @ResponseBody annotation, otherwise spring mvc will look for the jsp named after your json string

 

3. Convert the object collection to json string, there is no difference, also use the writeValueAsString method of ObjectMapper:

/**
     * 使用jackson将对象集合转换为json 串返回
     * @param name
     * @return
     * @throws JsonProcessingException
     */
    @RequestMapping("/test5")
    @ResponseBody
    public String test5() {
        String jsonResult = "";
        List<User> userList = new ArrayList<User>();
        User u1 = new User();
        User u2 = new User();
        User u3 = new User();
       
        u1.setUserName("张三");
        u2.setUserName("李四");
        u3.setUserName("王五");
       
        userList.add(u1);
        userList.add(u2);
        userList.add(u3);
       
        ObjectMapper om = new ObjectMapper();
        try {
            jsonResult = om.writeValueAsString(userList);
        } catch (JsonProcessingException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
       
        return jsonResult ;
    }

 Observing the results, you can see that it is encapsulated in the form of json values:

[{"userName":"张三","userPass":null,"age":null},{"userName":"李四","userPass":null,"age":null},{"userName":"王五","userPass":null,"age":null}]

 

(5) Jump between controllers

   Similar to servlet, in addition to jumping to a page, you can also jump from one controller method to another controller method. Of course, there are server-side jumps (foward) and client-side jumps (redirect).

1. Forward jump, that is, jump within the same application, the client only requests once, use the forward: URI keyword of the jump component in the return statement , the sample code:

/**
     * Call forward from one controller to another controller
     * and pass client parameters and server parameters
     * @param name
     * @return
     */
    @RequestMapping("/test6")
    public String test6(String name,HttpServletRequest req){
        req.setAttribute("key1", new String("Data from the previous controller"));
        return "forward:/jumpToView/test7";
    }

 

/**
     * Component to jump to
     * @param name
     * @param req
     * @return
     */

@RequestMapping("/test7")
    @ResponseBody
    public String test7(String name,HttpServletRequest req){
        System.out.println(name+","+req.getAttribute("key1"));
        return "测试controller之间跳转";
    }

The first controller method (test6) is not responsible for the response, and hands the controller to the jumped controller method. After the jump, the second controller method (test7) can not only receive the request parameters from the client, but also accept To the property value defined in the request scope in the first controller method, it means that both components are in the same request scope. Looking at the network packets, it is true that there is only one request and one response.



 

 

2. redirect jump, the first controller method of the request will respond to the client request with a 302 status code, notify the client to re-request another component, and put the URL of the other component in the location field of the response header and send it back to the client end. Use the redirect: URI keyword of the jump component in the return statement. The sample code is as follows:

/**
     * Jump to another controller method by redirect
     * @param name
     * @param req
     * @return
     */
    @RequestMapping("/test8")
    public String test8(String name,HttpServletRequest req){
        req.setAttribute( "key2", new String("Data from the previous controller"));
        return "redirect:/jumpToView/test7";
    }

The observation results show that the jump is successful, but the second component (test7) cannot receive the parameters passed by the client to the first component (test8), nor can it receive the internal properties of test8 itself encapsulated in the request, observe HTTP message, it is found that two requests and two responses are indeed generated, so the two components are not actually in the same request scope (request).



 

 

(6) Two additional questions:

  1. Problems with static resource mapping:

    After using spring mvc according to the previous configuration, it is found that dynamic resources (such as jsp, controller, etc.) can be requested normally, but static resources such as html cannot be requested. The reason is that the core controller of spring mvc covers the default mapping of static resources by the web server, and a Handler configuration needs to be added to the corresponding configuration file of spring mvc:

<mvc:default-servlet-handler />

This configuration indicates that the processing of static resources will be returned to the web server, in our case tomcat.

 

  2. Chinese garbled problem when returning string response

    Whether it is ordinary String or Json, as long as the response contains Chinese, it cannot be rendered normally. This is because the converter mechanism of spring mvc uses ISO-8859-1 encoding by default for the text type in the response. It is also very simple to solve this problem. Add a converter to the spring mvc configuration file and specify the encoding method of the response. For UTF-8 you can:

<mvc:annotation-driven>
        <mvc:message-converters>
            <bean class="org.springframework.http.converter.StringHttpMessageConverter">
                <property name="supportedMediaTypes">
                    <list>
                        <!-- <value>application/json;charset=UTF-8</value> -->
                        <value>text/html;charset=UTF-8</value>
                    </list>
                </property>
            </bean>
        </mvc:message-converters>
    </mvc:annotation-driven>

 

 We will introduce the mechanism of the converter later.

 

(7) Summary

   This section introduces several common ways for spring mvc to generate responses. In the next section, we will introduce the way to use the features of servlet3.x to implement 0 configuration and load the spring mvc container.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326486536&siteId=291194637