@RequestBody傳遞多個(gè)不同對(duì)象
如果使用spring mvc同客戶端通信,完全使用json數(shù)據(jù)格式,需要增加RequestBody注解,函數(shù)參數(shù)為自定義類
1
2
3
4
5
6
7
8
|
@Controller public class TestController{ @RequestMapping ( "\test" ) @ResponseBody public RetureResult test( @RequestBody User user){ return new ReturnResult(); } } |
這樣的話,可以將接收到的json格式的數(shù)據(jù)轉(zhuǎn)換為指定的數(shù)據(jù)對(duì)象user。比如{name:"test"},name為User類的屬性域。通過(guò)ResponseBody注解,可以返回json格式的數(shù)據(jù)。
有時(shí)接收json格式數(shù)據(jù)時(shí),我們可能需要將其轉(zhuǎn)換為多個(gè)對(duì)象。
以下方式是錯(cuò)誤的。原因是request的content-body是以流的形式進(jìn)行讀取的,讀取完一次后,便無(wú)法再次讀取了。
1
2
3
4
5
6
7
8
|
@Controller public class TestController{ @RequestMapping ( "\test" ) @ResponseBody public RetureResult test( @RequestBody User user, @RequestBody Address address){ return new ReturnResult(); } } |
解決方案1
增加一個(gè)包裝類,將所需要類寫入,增加get,set方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
@Controller public class TestController{ @RequestMapping ( "\test" ) @ResponseBody public RetureResult test( @RequestBody Param param){ User user=param.getUser(); Address address=param.getAddress(); return new ReturnResult(); } } class Param{ private User user; private Address address; public User getUser() { return user; } public void setUser(User user) { this .user = user; } public Address getAddress() { return address; } public void setAddress(Address address) { this .address = address; } } |
此時(shí)傳輸?shù)膉son數(shù)據(jù)格式變?yōu)閧user:{name:"test"},address:{location:"新華路"}}。
由于只是在TestController中增加一個(gè)包裝類,不會(huì)影響其他的類以及已經(jīng)定義好的model類,因此可以非常方便的達(dá)到接收多個(gè)對(duì)象參數(shù)的目的。
解決方案2
將接收參數(shù)定義為Map<String, Object>,然后使用map轉(zhuǎn)object工具,轉(zhuǎn)換成需要的對(duì)象。
此時(shí),即使自定義的Param類中的屬性即使比json數(shù)據(jù)中的屬性少了,也沒(méi)關(guān)系。
其中JSONUtils為自定義的工具類,可使用常見(jiàn)的fastjson等工具包包裝實(shí)現(xiàn)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
@Controller public class TestController{ @RequestMapping ( "\test" ) @ResponseBody public Object test( @RequestBody Map<String, Object> models){ User user=JsonXMLUtils.map2object((Map<String, Object>)models.get( "user" ),User. class ); Address address=JsonXMLUtils.map2object((Map<String, Object>)models.get( "address" ),Address. class ); return models; } } import com.alibaba.fastjson.JSON; public class JsonXMLUtils { public static String obj2json(Object obj) throws Exception { return JSON.toJSONString(obj); } public static <T> T json2obj(String jsonStr, Class<T> clazz) throws Exception { return JSON.parseObject(jsonStr, clazz); } public static <T> Map<String, Object> json2map(String jsonStr) throws Exception { return JSON.parseObject(jsonStr, Map. class ); } public static <T> T map2obj(Map<?, ?> map, Class<T> clazz) throws Exception { return JSON.parseObject(JSON.toJSONString(map), clazz); } } |
使用多個(gè)@RequestBody接收參數(shù)
原因
常規(guī)情況下,因?yàn)閞equest的body只能讀取一次,@RequestBody也只能解析一次,這就導(dǎo)致解析第二個(gè)的@RequestBody的時(shí)候stream已經(jīng)關(guān)閉了,無(wú)法再次讀取。
話不多說(shuō),上貨:
解決辦法:兩個(gè)類,直接copy即可
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
|
import javax.servlet.ReadListener; import javax.servlet.ServletInputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; import java.io.*; public class BodyReaderRequestWrapper extends HttpServletRequestWrapper { private final String body; /** * * @param request */ public BodyReaderRequestWrapper(HttpServletRequest request) throws IOException{ super (request); StringBuilder sb = new StringBuilder(); InputStream ins = request.getInputStream(); BufferedReader isr = null ; try { if (ins != null ){ isr = new BufferedReader( new InputStreamReader(ins)); char [] charBuffer = new char [ 128 ]; int readCount = 0 ; while ((readCount = isr.read(charBuffer)) != - 1 ){ sb.append(charBuffer, 0 ,readCount); } } else { sb.append( "" ); } } catch (IOException e){ throw e; } finally { if (isr != null ) { isr.close(); } } sb.toString(); body = sb.toString(); } @Override public BufferedReader getReader() throws IOException { return new BufferedReader( new InputStreamReader( this .getInputStream())); } @Override public ServletInputStream getInputStream() throws IOException { final ByteArrayInputStream byteArrayIns = new ByteArrayInputStream(body.getBytes()); ServletInputStream servletIns = new ServletInputStream() { @Override public boolean isFinished() { return false ; } @Override public boolean isReady() { return false ; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return byteArrayIns.read(); } }; return servletIns; } } |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
import org.springframework.stereotype.Component; import javax.servlet.*; import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component @WebFilter (filterName = "crownFilter" , urlPatterns = "/*" ) public class BodyReaderRequestFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest req, ServletResponse res, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)req; HttpServletResponse response = (HttpServletResponse)res; BodyReaderRequestWrapper requestWrapper = new BodyReaderRequestWrapper(request); if (requestWrapper == null ){ filterChain.doFilter(request,response); } else { filterChain.doFilter(requestWrapper,response); } } @Override public void destroy() { } } |
使用:自行測(cè)試。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/sunayn/article/details/106214391