2018-11-23 · Develop

SpringBoot 数据绑定-复杂对象

接上篇 SpringBoot 数据绑定 没有讲完的部分继续。

List/Set/Map

首先我们看看如何直接接受这种集合类型的数据

@GetMapping("/list")
@ApiOperation("List对象类型")
public List<String> hello(@RequestParam List<String> list) {
    return list;
}

@GetMapping("/set")
@ApiOperation("Set对象类型")
public Set<String> hello(@RequestParam Set<String> set) {
    return set;
}

@GetMapping("/map")
@ApiOperation("Map对象类型")
public Map<String, String> hello(@RequestBody Map<String, String> map) {
    return map;
}

对于前端如何传参,可以看下面的验证方式

curl -X GET "http://localhost:8080/list?list=a&list=b"
["a","b"]

curl -X GET "http://localhost:8080/set?set=a&set=b"
["a","b"]

curl -X GET -H "Content-Type: application/json"  -d "{\"a\":\"A\",\"b\":\"B\"}" "http://localhost:8080/map"
{"a":"A","b":"B"}

下面我们讲下集合类型作为复杂对象的一个字段进行绑定的情况。

@Getter
@Setter
@ToString
public class CollectionForm {

    private List<String> list;

    private Set<String> set;

    private Map<String, String> map;
}

像上面这样再去进行数据绑定的时候就遇到几个比较坑的地方需要注意:

curl -X GET "http://localhost:8080/collection?list=a&set=A&map%5B%27A%27%5D=a"
# 上面的 url = encodeURI("http://localhost:8080/collection?list=a&set=A&map['A']=a")
{"list":["a"],"set":["A"],"map":{"A":"a"}}

curl -X GET "http://localhost:8080/collection?list=a&list=b&set=A&set=B&map%5B%27A%27%5D=a"
# 上面的 url = encodeURI("http://localhost:8080/collection?list=a&list=b&set=A&set=B&map['A']=a")
{"list":["a","b"],"set":["A","B"],"map":{"A":"a"}}

curl -X GET "http://localhost:8080/collection?list%5B3%5D=a&set=A&map%5B%27A%27%5D=a"
# 上面的 url = encodeURI("http://localhost:8080/collection?list[3]=a&set=A&map['A']=a")
{"list":[null,null,null,"a"],"set":["A"],"map":{"A":"a"}}

curl -X GET "http://localhost:8080/collection?list%5B1%5D=a&set%5B1%5D=A&map%5B%27A%27%5D=a"
# 上面的 url = encodeURI("http://localhost:8080/collection?list[1]=a&set[1]=A&map['A']=a")
{"timestamp":"2018-11-24T15:08:12.651+0000","status":500,"error":"Internal Server Error","message":"Invalid property 'set[0]' of bean class [com.example.swagger.entity.CollectionForm]: Property referenced in indexed property path 'set[1]' is neither an array nor a List nor a Map; returned value was [[]]","path":"/collection"}
java.lang.IllegalArgumentException: Invalid character found in the request target. The valid characters are defined in RFC 7230 and RFC 3986
	at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:479) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:684) ~[tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:806) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1498) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_161]
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_161]
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.34.jar:8.5.34]
	at java.lang.Thread.run(Thread.java:748) [na:1.8.0_161]

Json

对于 Json 的数据绑定上面测试 Map 的时候就已使用过了,需要注意的以下几点

@PostMapping("/json")
@ApiOperation("Json对象类型")
public User hello(@RequestBody User user) {
    return user;
}
curl -X POST -H "Content-Type: application/json"  -d "{\"name\":\"A\",\"age\":12}" "http://localhost:8080/json"
{"name":"A","age":12,"contactInfo":null}

XML

对于 xml 的方式和 json 的方式差不多,只是说请求头变成了 Content-Type: application/xml

@PostMapping("/xml")
@ApiOperation("Xml对象类型")
public Admin hello(@RequestBody Admin admin) {
    return admin;
}

对于接受数据的对象,需要进行重构,使其知道如何转换 xml 数据,主要是通过 javax.xml.bind.annotation 包下面的注解。

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;

import javax.xml.bind.annotation.XmlRootElement;

@Getter
@Setter
@ToString
@XmlRootElement(name = "admin")
public class Admin {

    private String name;
    private Integer age;
}

测试代码如下

curl -X POST -H "Content-Type: application/xml"  -d "<?xml version=\"1.0\" encoding=\"UTF-8\" ?><admin><name>a</name>
<age>12</age></admin>" "http://localhost:8080/xml"
{"name":"a","age":12}