java后台controller能否直接接收list<object>为入参?

修改下问题,最下方为我项目的详细代码,精简了一下,去除了state属性,代码顺序最开始,基础数据类型int,从单个int到int数组,到intarraylist,
单个stirng string数组, string list, arraylist,
单个Tag对象,Tag对象数组,list,arraylist

我网上找了很多例子,例子中的controller直接接收list都是接受的字符串类型,list<string>,并没有复杂对象类型的例子

目前我所知道的两种解决办法就是
1.新建一个vo类,里面有一个list<Tag>属性,controller接受这个类
2.接受字符串,将字符串转为list

但是如果我就是想直接接受list呢?

这是我的类:

public class Tag {

int id;

String name;

int state;

}

我前台传给后台的数据格式是这个样子的

[{"id":1,"name":"123","state":0},{"id":3,"name":"456","state":0}]

我后台能否直接在入参里面用list<Tag>接收呢?

我弄了半天也不行;

那么大家平常都是如何处理的呢,都是入参接收字符串,然后用jackson等框架再转成list吗

或者是我把入参改成什么样子后台就可以接受了呢,我记得之前遇到过一次这个问题,从前台遍历对象然后弄得,但是代码没了,也忘了,但是那样弄也挺麻烦的,最简单的方法是什么呢

分割线

pom文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example</groupId>
<artifactId>demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>

<name>demo</name>
<description>Demo project for Spring Boot</description>

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <java.version>1.8</java.version>
</properties>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-thymeleaf</artifactId>
    </dependency>
    <dependency>
        <groupId>net.sourceforge.nekohtml</groupId>
        <artifactId>nekohtml</artifactId>
        <version>1.9.22</version>
    </dependency>

    <!-- <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency> -->
    
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
    </plugins>
</build>

</project>

配置文件:

server:
port: 8088

spring:
thymeleaf:

mode: LEGACYHTML5

datasource:

url: jdbc:mysql://localhost:3306/ek
username: root
password: 1212
driver-class-name: com.mysql.jdbc.Driver

jpa:

database: MYSQL
show-sql: true
hibernate:
  ddl-auto: update
properties:
  hibernate:
    dialect: org.hibernate.dialect.MySQL5Dialect

Tag类

package com.example.demo.entity;

public class Tag {

int id;

String name;

public int getId() {
    return id;
}

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

public String getName() {
    return name;
}

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

@Override
public String toString() {
    return "Tag [id=" + id + ", name=" + name + "]";
}

}

前台和后台从简单到复杂一点一点来,各阶段代码:
version 1: 单个int类型,

前台代码:
<!DOCTYPE html>
<html>
<head>

<meta charset="UTF-8">
<title>index</title>
<!-- 引入样式 -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>

</head>
<body>
<button onclick="commit()">测试</button>
<script>
function commit(){

$.ajax({
    type:"post",
    url: 'add',
    data:{
        param:1
    },
    success:function(data){
        console.log(data);
    }
})

}
</script>
</body>

</html>

后台代码:

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HelloController {

@RequestMapping("")
public String Hello(ModelMap map) {
    return "index";
}

@ResponseBody
@RequestMapping(value = "add")
public String add(int param) {
    System.out.println("param:" + param);
    return "成功";
}

}

前端控制台数据格式:
param:1
后台控制台输出
param:1

version2:多个int类型;

将data:{

        param:1
    },

改为:
data:{

        param:[1,2,3]
    },

后台代码改为:
@ResponseBody

@RequestMapping(value = "add")
public String add(@RequestParam("param[]") int[] param) {
    System.out.println("param:" + param);
    System.out.println("param:" + Arrays.toString(param));
    return "成功";
}

后台入参改为:@RequestParam("param[]") int[] param
则可以正确接收,为param则不行

前台控制台数据格式:
param[]:1
param[]:2
param[]:3
后台控制台输出:
param:[I@55a3f9bb
param:[1, 2, 3]

version3:后台使用list接受
前台代码不变,
后台代码改为:
@ResponseBody

@RequestMapping(value = "add")
public String add(@RequestParam("param[]") List<Integer> param) {
    System.out.println("param:" + param);
    return "成功";
}

前台数据格式:
param[]:1
param[]:2
param[]:3
后台控制台输出:
param:[1, 2, 3]

version4:后台使用arraylist接收
前台代码不变,
后台代码改为:
@ResponseBody

@RequestMapping(value = "add")
public String add(@RequestParam("param[]") ArrayList<Integer> param) {
    System.out.println("param:" + param);
    return "成功";
}

前台数据格式:
param[]:1
param[]:2
param[]:3
后台控制台输出:
param:[1, 2, 3]

version 5:使用字符串测试,结果和int类型结果完全一致,就不贴代码了,

version 6:使用tag类测试,传递tag对象

index.html:

<!DOCTYPE html>
<html>
<head>

<meta charset="UTF-8">
<title>index</title>
<!-- 引入样式 -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>

</head>
<body>
<button onclick="commit()">测试</button>
<script>
function commit(){

$.ajax({
    type:"post",
    url: 'add',
    data:{
        id:1,
        name:"hello"
    },
    success:function(data){
        console.log(data);
    }
})

}
</script>
</body>

</html>

helloController:

package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.example.demo.entity.Tag;

@Controller
public class HelloController {

@RequestMapping("")
public String Hello(ModelMap map) {
    return "index";
}

@ResponseBody
@RequestMapping(value = "add")
public String add(Tag tag) {
    System.out.println(tag);
    return "成功";
}

}

version 6结果: 后台可以成功接收Tag类的对象,
控制台输出为:Tag [id=1, name=hello]

version 7:
修改前台数据格式:
data:{

        id:1,
        name:"hello"
    },

改为:
data:{tag:{id:1,name:'hello'}},
后台代码不变

version 7
结果:后台接受到的Tag类对象各属性为空
控制台输出为:Tag [id=0, name=null]
前台chrome控制台中记录的From data为:
tag[id]:1
tag[name]:hello

version 8 :使用tag类型的list接受数据
前台data修改为:
data:{
param:[{id:1,name:'hello'},{id:2,name:'hello'}]

    },

后台代码修改为:
@ResponseBody

@RequestMapping(value = "add")
public String add(@RequestParam("param[]") List<Tag> param) {
    System.out.println("param:" + param);
    return "成功";
}

version 8 结果:

前台chrome显示数据格式为:
param0:1
param0:hello
param1:2
param1:hello
请求失败,前台500错误,
后台代码报错:
错误信息为:
2018-01-29 13:22:06.313 WARN 3148 --- [nio-8088-exec-3] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.web.bind.MissingServletRequestParameterException: Required List parameter 'param[]' is not present

version 9:
ajax新增contentType,
data使用JSON.stringify格式胡
controller入参加入@requestBody注解

前台代码:
function commit(){

var param=[{id:1,name:'hello'},{id:2,name:'hello'}];
console.log(param);
console.log(JSON.stringify(param));
$.ajax({
    type:"post",
    url: 'add',
    contentType:"application/json; charset=utf-8",
    dataType:"json",
    data:{
        param:JSON.stringify(param)
    },
    success:function(data){
        console.log(data);
    }
})

}
后台代码:
@ResponseBody

@RequestMapping(value = "add")
public String add(@RequestBody List<Tag> param) {
    System.out.println("param:" + param);
    return "成功";
}

然后前台请求报400错误,
前台控制台输出位:
图片描述
数据格式为:
param=%5B%7B%22id%22%3A1%2C%22name%22%3A%22hello%22%7D%2C%7B%22id%22%3A2%2C%22name%22%3A%22hello%22%7D%5D

后台报错为:
2018-01-29 13:34:06.096 WARN 3148 --- [nio-8088-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Failed to read HTTP message: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'param': was expecting ('true', 'false' or 'null'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'param': was expecting ('true', 'false' or 'null')
at [Source: java.io.PushbackInputStream@14a71bea; line: 1, column: 7]
2018-01-29 13:34:06.096 WARN 3148 --- [nio-8088-exec-2] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved exception caused by Handler execution: org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Unrecognized token 'param': was expecting ('true', 'false' or 'null'); nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'param': was expecting ('true', 'false' or 'null')
at [Source: java.io.PushbackInputStream@14a71bea; line: 1, column: 7]

阅读 15.2k
2 个回答

楼主你可以把ajax的data:{ param:JSON.stringify(param) }改成data:JSON.stringify(param);希望能帮助到你!

可以 用@RequestBody注解

后端
clipboard.png

前台

clipboard.png
数据组装

clipboard.png

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题