使用@RequestBody传递多个不同对象方式

网友投稿 1540 2022-11-29

使用@RequestBody传递多个不同对象方式

使用@RequestBody传递多个不同对象方式

目录@RequestBody传递多个不同对象解决方案1解决方案2使用多个@RequestBody接收参数原因解决办法:两个类,直接copy即可

@RequestBody传递多个不同对象

如果使用spring mvc同客户端通信,完全使用json数据格式,需要增加RequestBody注解,函数参数为自定义类

@Controller

public class TestController{

@RequestMapping("\test")

@ResponseBody

public RetureResult test(@RequestBody User user){

return new ReturnResult();

}

}

这样的话,可以将接收到的json格式的数据转换为指定的数据对象user。比如{name:"test"},name为User类的属性域。通过ResponseBody注解,可以返回json格式的数据。

有时接收json格式数据时,我们可能需要将其转换为多个对象。

以下方式是错误的。原因是request的content-body是以流的形式进行读取的,读取完一次后,便无法再次读取了。

@Controller

public class TestController{

@RequestMapping("\test")

@ResponseBody

public RetureResult test(@RequestBody User user,@RequestBody Address address){

return new ReturnResult();

}

}

解决方案1

增加一个包装类,将所需要类写入,增加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;

}

}

此时传输的json数据格式变为{user:{name:"test"},address:{location:"新华路"}}。

由于只是在TestController中增加一个包装类,不会影响其他的类以及已经定义好的model类,因此可以非常方便的达到接收多个对象参数的目的。

解决方案2

将接收参数定义为Map,然后使用map转object工具,转换成需要的对象。

此时,即使自定义的Param类中的属性即使比json数据中的属性少了,也没关系。

其中JSONUtils为自定义的工具类,可使用常见的fastjson等工具包包装实现。

@Controller

public class TestController{

@RequestMapping("\test")

@ResponseBody

public Object test(@RequestBody Map models){

   User user=JsonXMLUtils.map2object((Map)models.get("user"),User.class);

   Address address=JsonXMLUtils.map2object((Map)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 json2obj(String jsonStr, Class clazz) throws Exception {

return JSON.parseObject(jsonStr, clazz);

}

public static Map json2map(String jsonStr) throws Exception {

return JSON.parseObject(jsonStr, Map.class);

}

public static T map2objLfhsicS(Map, ?> map, Class clazz) throws Exception {

return JSON.parseObject(JSON.toJSONString(map), clazz);

}

}

使用多个@RequestBody接收参数

原因

常规情况下,因为request的body只能读取一次,@RequestBody也只能解析一次,这就导致解析第二个的@RequestBody的时候stream已经关闭了,无法再次读取。

话不多说,上货:

解决办法:两个类,直接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() {

}

}

使用:自行测试。

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Kubernetes Pod 资源共享实现机制
下一篇:Mysql proxy实现读写分离
相关文章

 发表评论

暂时没有评论,来抢沙发吧~