1. 程式人生 > >springMVC Controller接收 多物件的json資料

springMVC Controller接收 多物件的json資料

第一種方法,用包裝類封裝物件

實體類物件

public class User {

    private int id;
    private String userName;
    private String realName;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getRealName() {
        return realName;
    }

    public void setRealName(String realName) {
        this.realName = realName;
    }

    @Override
    public String toString() {
        return "User{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", realName='" + realName + '\'' +
                '}';
    }
}


public class Info {

    private int id;
    private String address;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    @Override
    public String toString() {
        return "Info{" +
                "id=" + id +
                ", address='" + address + '\'' +
                '}';
    }
}

public class RequestParam {

    private User user;

    private Info info;

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public Info getInfo() {
        return info;
    }

    public void setInfo(Info info) {
        this.info = info;
    }
}

定義了三個實體 RequestParam裡面又封裝了User類和Info類

JAVA程式碼

    @RequestMapping(value = "/show",method = RequestMethod.POST)
    public String show(@RequestBody RequestParam param){

        User user = param.getUser();
        Info info = param.getInfo();

        return user.toString();
    }

前臺程式碼

                $("#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);                          
                       }
                   });
                });

可以成功接收到物件,但是顯得沒有那麼優雅,每次請求資料不同都要另外寫一個包裝類,顯得很麻煩。

第二種方法,用Map物件接收 更加簡單粗暴

JAVA程式碼

    @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";
    }

也不夠方便 每個物件還要再做一次轉換

第三種方法,使用自定義的HandlerMethodArgumentResolver

自定義註解 加在控制器的引數前作為標記

@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";
    }

前臺程式碼

                $("#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);                          
                       }
                   });
                });

第三種方式相對比較好 但我有幾點還是沒明白

public Object resolveArgument(MethodParameter methodParameter,
ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
WebDataBinderFactory webDataBinderFactory) 
這個方法中的 ModelAndViewContainer和webDataBinderFactory 這兩個物件的作用,怎樣寫能夠優雅,歡迎大家不吝賜教。