SpringMVC系列--獲取參數--實例

創建項目

gitee地址:https://gitee.com/shapeless/demo/tree/master/demo_springboot_mvc

創建SpringBoot項目,引入spring-boot-starter-web

實體類

User.java

package com.example.demo.entity;

import java.util.List;

public class User {
    private String name;
    private Integer age;
    private String[] password;
    private List<Integer> scoreArray;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String[] getPassword() {
        return password;
    }

    public void setPassword(String[] password) {
        this.password = password;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public List<Integer> getScoreArray() {
        return scoreArray;
    }

    public void setScoreArray(List<Integer> scoreArray) {
        this.scoreArray = scoreArray;
    }
}

Account.java

package com.example.demo.entity;

import java.io.Serializable;

public class Account implements Serializable {
    private String phoneNum;
    private String[] emails;

    public String getPhoneNum() {
        return phoneNum;
    }

    public void setPhoneNum(String phoneNum) {
        this.phoneNum = phoneNum;
    }

    public String[] getEmails() {
        return emails;
    }

    public void setEmails(String[] emails) {
        this.emails = emails;
    }
}

x-www-form-urlencoded請求

Controller

BasicController.java

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.List;

// localhost:8080/basic/no_annotation/string1
@RequestMapping("/basic")
@Controller
public class BasicController {
    @RequestMapping("/1")
    @ResponseBody
    public String test1(int intVal, Long longVal, String myStr){
        System.out.println("intVal  : " + intVal);
        System.out.println("longVal : " + longVal);
        System.out.println("myStr   : " + myStr);
        return "Hello world";
    }

    @RequestMapping("/2")
    @ResponseBody
    public User test2(@RequestParam Integer intVal,
                                         @RequestParam(value = "my_str", required = false) String[] myStr,
                                         @RequestParam String[] password,
                                         @RequestParam List<Integer> scoreArray,
                                         @RequestParam Integer age,
                                         User user){
        System.out.println("intVal     : " + intVal);
        System.out.println("age        : " + age);
        System.out.println("myStr      : " + Arrays.asList(myStr));
        System.out.println("password   : " + Arrays.asList(password));
        System.out.println("scoreArray : " + scoreArray);

        return user;
    }

    @RequestMapping("/3")
    @ResponseBody
    public User test3(@RequestBody User user){
        return user;
    }
}

測試

測試1:基本類型爲空導致錯誤

http://localhost:8080/basic/1

後端打印

java.lang.IllegalStateException: Optional int parameter 'intVal' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.

前端結果

測試2正常操作

其實也不正常,最好不要用基本類型接收。

http://localhost:8080/basic/1?intVal=2&myStr=hehe

後端

intVal  : 2
longVal : null
myStr   : hehe

前端

測試3正常操作

http://localhost:8080/basic/2?intVal=2&my_str=Tony,Stark&name=Jarvis&age=21&password=ab,cd&scoreArray=99,98&phoneNum=12

後端

intVal     : 2
age        : 21
myStr      : [Tony, Stark]
password   : [ab, cd]
scoreArray : [99, 98]

 前端

結論

  • 如果一個參數,實體類與接口參數都有,則都會賦值。
  • 若實體類中有數組/List 成員,也會對它直接賦值。
  • 若實體類含有實體類,無法賦值。因爲參數中沒有與實體類相同名字的key,此時就要用form-data或者json了。(或者x-www-urlencoded也有寫類參數的方法,目前不知道)

測試4@RequestParam缺少參數訪問(失敗)

http://localhost:8080/basic/2?intVal=2&my_str=Tony,Stark&name=Jarvis&age=21&password=ab,cd&phoneNum=12

後端

2020-07-04 18:00:37.222  WARN 15844 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.bind.MissingServletRequestParameterException: Required List parameter 'scoreArray' is not present]

前端

測試5用@RequestBody接收(失敗)

http://localhost:8080/basic/3?intVal=2&my_str=Tony,Stark&name=Jarvis&age=21&password=ab,cd&scoreArray=99,98&phoneNum=12

後端

2020-07-04 14:02:55.954  WARN 15844 --- [nio-8080-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: Required request body is missing: public com.example.demo.entity.User com.example.demo.controller.BasicController.test3(com.example.demo.entity.User)]

前端

form-data請求

其他網址

使用FormData格式在前後端傳遞數據 - wenr - 博客園

Controller

FormDataController.java

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

// localhost:8080/basic/no_annotation/string1
@RequestMapping("/formdata")
@Controller
public class FormDataController {
    @RequestMapping("/1")
    @ResponseBody
    public String test1(int intVal, Long longVal, String myStr){
        System.out.println("intVal  : " + intVal);
        System.out.println("longVal : " + longVal);
        System.out.println("myStr   : " + myStr);
        return "Hello world";
    }

    @RequestMapping("/2")
    @ResponseBody
    public User test2(@RequestParam Integer intVal,
                     @RequestParam(value = "my_str", required = false) String[] myStr,
                     @RequestParam String[] password,
                     @RequestParam List<Integer> scoreArray,
                     @RequestParam Integer age,
                     User user){
        System.out.println("intVal     : " + intVal);
        System.out.println("age        : " + age);
        System.out.println("myStr      : " + Arrays.asList(myStr));
        System.out.println("password   : " + Arrays.asList(password));
        System.out.println("scoreArray : " + scoreArray);

        return user;
    }

    @RequestMapping("/3")
    @ResponseBody
    public User test3(User user){
        System.out.println("name            : " + user.getName());
        System.out.println("password        : " + Arrays.asList(user.getPassword()));
        System.out.println("scoreArray      : " + user.getScoreArray());
        System.out.println("acount.phoneNum : " + user.getAccount().getPhoneNum());
        System.out.println("account.emails  : " + Arrays.asList(user.getAccount().getEmails()));
        return user;
    }
}

測試

測試1:基本類型爲空導致錯誤

postman(http://localhost:8080/formdata/1

後端

java.lang.IllegalStateException: Optional int parameter 'intVal' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type.

測試2基本類型不爲空(成功)

最好不要用基本類型接收。

postman:訪問http://localhost:8080/formdata/1/

後端

intVal  : 2
longVal : null
myStr   : hehe

測試3正常操作:沒有@RequestBody的接收單個實體類接收

postman的body數據

後端

name            : Jarvis
password        : [ab, cd]
scoreArray      : [99, 98]
acount.phoneNum : null
account.emails  : [[email protected], [email protected]]

測試4有@RequestBody的接收單個實體類接收(失敗)

postman訪問:http://localhost:8080/formdata/4/

postman數據:

後端打印

2020-07-06 09:18:19.637  WARN 16088 --- [nio-8080-exec-1] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'multipart/form-data;boundary=--------------------------428878162965035610803450;charset=UTF-8' not supported]

JSON請求(單個對象)

Controller

JsonController.java

package com.example.demo.controller;

import com.example.demo.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.Arrays;
import java.util.List;

@RequestMapping("/json")
@Controller
public class JsonController {
    @RequestMapping("/1")
    @ResponseBody
    public User setUserNoAnnotation(User user, List<String> password, Integer[] scoreArray) {
        printUser(user);
        return user;
    }

    @RequestMapping("/2")
    @ResponseBody
    public User setUserAnnotation(@RequestBody User user) {
        printUser(user);
        return user;
    }

    @RequestMapping("/3")
    @ResponseBody
    public User setUserAnnotation1(@RequestBody User user, @RequestParam List<String> password, Integer[] scoreArray) {
        System.out.println(password);
        if (scoreArray != null) {
            System.out.println(Arrays.asList(scoreArray));
        } else {
            System.out.println("scoreArray = null");
        }
        System.out.println();
        printUser(user);

        return user;
    }

    @RequestMapping("/4")
    @ResponseBody
    public User setUserAnnotation2(@RequestBody User user, @RequestBody List<String> password, @RequestBody Integer[] scoreArray) {
        if (password != null) {
            System.out.println(password);
        } else {
            System.out.println("password = null");
        }

        if (scoreArray != null) {
            System.out.println(Arrays.asList(scoreArray));
        } else {
            System.out.println("scoreArray = null");
        }
        System.out.println();
        printUser(user);
        return user;
    }

    private void printUser(User user){
        System.out.println("name            : " + user.getName());
        System.out.println("password        : " + Arrays.asList(user.getPassword()));
        System.out.println("scoreArray      : " + user.getScoreArray());
        System.out.println("acount.phoneNum : " + user.getAccount().getPhoneNum());
        System.out.println("account.emails  : " + Arrays.asList(user.getAccount().getEmails()));
    }
}

測試

測試前提

json的body

{
    "name": "Jarvis",
    "password": [
        "ab",
        "cd"
    ],
    "scoreArray": [
        99,
        98
    ],
    "account": {
        "phoneNum": "123",
        "emails": [
            "[email protected]",
            "[email protected]"
        ]
    }
}

測試1:正常操作

使用postman,url:http://localhost:8080/json/2

後端

name            : Jarvis
password        : [ab, cd]
scoreArray      : [99, 98]
acount.phoneNum : 123
account.emails  : [[email protected], [email protected]]

postman

{
    "name": "Jarvis",
    "age": null,
    "password": [
        "ab",
        "cd"
    ],
    "scoreArray": [
        99,
        98
    ],
    "account": {
        "phoneNum": "123",
        "emails": [
            "[email protected]",
            "[email protected]"
        ]
    }
}

測試2:(不使用@RequestBody接收)

使用postman,url:http://localhost:8080/json/1

後端

2020-07-03 23:27:18.504 ERROR 12568 --- [nio-8080-exec-3] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.IllegalStateException: No primary or default constructor found for interface java.util.List] with root cause

java.lang.NoSuchMethodException: java.util.List.<init>()
	at java.lang.Class.getConstructor0(Class.java:3082) ~[na:1.8.0_51]
	at java.lang.Class.getDeclaredConstructor(Class.java:2178) ~[na:1.8.0_51]
	at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:216) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:85) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:139) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:134) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:879) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:660) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:741) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.7.RELEASE.jar:5.2.7.RELEASE]
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:373) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1590) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_51]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_51]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.36.jar:9.0.36]
	at java.lang.Thread.run(Thread.java:745) [na:1.8.0_51]

postman

{
    "timestamp": "2020-07-03T15:44:10.224+00:00",
    "status": 500,
    "error": "Internal Server Error",
    "message": "",
    "path": "/json/1"
}

測試3:(一個有@RequestBody+多個無)

postman訪問:http://localhost:8080/json/3?password=ef,gh

後端

[ef, gh]
scoreArray = null

name            : Jarvis
password        : [ab, cd]
scoreArray      : [99, 98]
acount.phoneNum : 123
account.emails  : [[email protected], [email protected]]

postman

{
    "name": "Jarvis",
    "age": null,
    "password": [
        "ab",
        "cd"
    ],
    "scoreArray": [
        99,
        98
    ],
    "account": {
        "phoneNum": "123",
        "emails": [
            "[email protected]",
            "[email protected]"
        ]
    }
}

測試4:多個@RequestBody

postman訪問:http://localhost:8080/json/4?password=ef,gh

後端

2020-07-03 23:48:06.907  WARN 2644 --- [nio-8080-exec-5] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.http.converter.HttpMessageNotReadableException: I/O error while reading input message; nested exception is java.io.IOException: Stream closed]

postman

{
    "timestamp": "2020-07-03T15:47:45.924+00:00",
    "status": 400,
    "error": "Bad Request",
    "message": "",
    "path": "/json/4"
}

錯誤原因

其他網址:https://www.e-learn.cn/topic/3352427

每個方法只能有一個@RequestBody。使用@RequestBody把請求轉化爲特定的Object(在最後會關閉相應的流),所以在同一個方法中第二次使用@RequestBody是沒用的,因爲流已經關閉。

You cannot use it this way as only one @RequestBody per method is allowed. Using @RequestBody Spring converts incoming request body into the specified object (what closes the stream representing body at the end) so attempting to use @RequestBody second time in the same method makes no sense as stream has been already closed.

JSON請求(多個對象)

其他網址

SpringMVC接收多個對象參數_木子葉的奔跑-CSDN博客_spring接收2個對象的參數

方案1:Map對象接收

前端

$("#ok2").click(function(){
   var json = {"user":{"id":9527,"userName":"zcy","realName":"鋼鐵俠"},"info":{"id":998,"address":"紐約"}};
   $.ajax({
       url:"http://localhost:8080/more/show",
       type:"post",
       cache:false,
       contentType:"application/json",
       data:JSON.stringify(json),
       success:function(data){
           alert(data);                          
       }
   });
});

後端

@RequestMapping(value = "/show")
public String test(@RequestBody  Map<String,Object> map){

    // 拿到Object之後 再做轉換爲實體即可 可以用FastJson
    Object user = map.get("user");
    Object info = map.get("info");

    return "success";
}

方案2:自定義處理方法

前端

$("#ok2").click(function(){
   var json = {"user":{"id":9527,"userName":"zcy","realName":"鋼鐵俠"},"info":{"id":998,"address":"紐約"}};
   $.ajax({
       url:"http://localhost:8080/more/custom",
       type:"post",
       cache:false,
       // 直接傳josn對象 這裏與上文不同
       data:json,
       success:function(data){
           alert(data);                          
       }
   });
});

後端

自定義註解 (加在控制器的參數前作爲標記)

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface JsonObject {
}

自定義處理類(實現HandlerMethodArgumentResolver接口)

public class JsonObjectArgResolverHandler implements HandlerMethodArgumentResolver {
 
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        return methodParameter.hasParameterAnnotation(JsonObject.class);
    }
 
    @Override
    public Object resolveArgument(MethodParameter methodParameter,
                                  ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
                                  WebDataBinderFactory webDataBinderFactory) throws Exception {
 
        // 獲取Controller中的參數名
        String name = methodParameter.getParameterName();
        // 獲取Controller中參數的類型
        Class clazz = methodParameter.getParameterType();
        Object arg = null;
        // 獲取該參數實體的所用屬性
        Field[] fields = clazz.getDeclaredFields();
        // 實例化
        Object target = clazz.newInstance();
 
        // 創建WebDataBinder對象 反射 遍歷fields給屬性賦值
        WebDataBinder binder = webDataBinderFactory.createBinder(nativeWebRequest,null,name);
        for (Field field:fields){
            field.setAccessible(true);
            String fieldName = field.getName();
            Class<?> fieldType = field.getType();
            // 在request中 多對象json數據的key被解析爲 user[id] user[realName] info[address] 的這種形式
            String value = nativeWebRequest.getParameter(name + "[" + fieldName + "]");
            arg = binder.convertIfNecessary(value,fieldType,methodParameter);
            field.set(target,arg);
        }
 
        return target;
    }
}

註冊自己寫的處理類

@Component
public class MyWebAppConfig implements WebMvcConfigurer {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        // 配置自定義接收參數
        WebMvcConfigurer.super.addArgumentResolvers(resolvers);
        resolvers.add(new JsonObjectArgResolverHandler());
    }
}

Controller

@RequestMapping(value = "/custom")
public String custom(@JsonObject User user, @JsonObject Info info){
    System.out.println(user.toString());
    System.out.println(info.toString());

    return "success";
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章