好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

@RequestBody传递多个不同对象

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

?

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格式的数据转换为指定的数据对象user。比如{name:"test"},name为User类的属性域。通过ResponseBody注解,可以返回json格式的数据。

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

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

?

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

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

     }

}

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

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

解决方案2

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

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

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

?

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);

     }

}

使用多个@RequestBody接收参数

原因

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

话不多说,上货:

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

     }

}

使用:自行测试。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。

原文链接:https://blog.csdn.net/sunayn/article/details/106214391

查看更多关于使用@RequestBody传递多个不同对象方式的详细内容...

  阅读:14次