使用@RequestBody傳遞多個(gè)不同對(duì)象方式
@RequestBody傳遞多個(gè)不同對(duì)象
如果使用spring mvc同客戶端通信,完全使用json數(shù)據(jù)格式,需要增加RequestBody注解,函數(shù)參數(shù)為自定義類
@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ú)法再次讀取了。
@Controller public class TestController{ @RequestMapping("\test") @ResponseBody public RetureResult test(@RequestBody User user,@RequestBody Address address){ return new ReturnResult(); } }
解決方案1
增加一個(gè)包裝類,將所需要類寫入,增加get,set方法
@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為自定義的工具類,可使用常見的fastjson等工具包包裝實(shí)現(xiàn)。
@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即可
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; } }
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è)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Mybatis-Plus接口BaseMapper與Services使用詳解
這篇文章主要為大家介紹了Mybatis-Plus接口BaseMapper與Services使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05mybatis返回map結(jié)果集@MapKey使用的場(chǎng)景分析
這篇文章主要介紹了mybatis返回map結(jié)果集@MapKey使用的場(chǎng)景分析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01Intellij idea遠(yuǎn)程debug連接tomcat實(shí)現(xiàn)單步調(diào)試
這篇文章主要介紹了Intellij idea遠(yuǎn)程debug連接tomcat實(shí)現(xiàn)單步調(diào)試,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-05-05spring基礎(chǔ)系列之JavaConfig配置詳解
本篇文章主要介紹了spring基礎(chǔ)系列之JavaConfig配置詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-07-07在 Spring Boot 項(xiàng)目中實(shí)現(xiàn)文件下載功能
這篇文章主要介紹了在 Spring Boot 項(xiàng)目中實(shí)現(xiàn)文件下載功能,本文給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09springboot HandlerIntercepter攔截器修改request body數(shù)據(jù)的操作
這篇文章主要介紹了springboot HandlerIntercepter攔截器修改request body數(shù)據(jù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。2021-06-06java關(guān)鍵字static學(xué)習(xí)心得
本篇文章給大家分享一篇關(guān)于java關(guān)鍵字static的學(xué)習(xí)心得,有這方面需要的朋友學(xué)習(xí)下吧。2018-01-01Java Swing實(shí)現(xiàn)的定制TextField功能示例
這篇文章主要介紹了Java Swing實(shí)現(xiàn)的定制TextField功能,結(jié)合實(shí)例形式分析了java swing組件TextField相關(guān)屬性功能與設(shè)置操作技巧,需要的朋友可以參考下2018-01-01