第一种方法,用包装类封装对象

实体类对象


   
  1. public class User {
  2. private int id;
  3. private String userName;
  4. private String realName;
  5. public int getId() {
  6. return id;
  7. }
  8. public void setId(int id) {
  9. this.id = id;
  10. }
  11. public String getUserName() {
  12. return userName;
  13. }
  14. public void setUserName(String userName) {
  15. this.userName = userName;
  16. }
  17. public String getRealName() {
  18. return realName;
  19. }
  20. public void setRealName(String realName) {
  21. this.realName = realName;
  22. }
  23. @Override
  24. public String toString() {
  25. return "User{" +
  26. "id=" + id +
  27. ", userName='" + userName + '\'' +
  28. ", realName='" + realName + '\'' +
  29. '}';
  30. }
  31. }
  32. public class Info {
  33. private int id;
  34. private String address;
  35. public int getId() {
  36. return id;
  37. }
  38. public void setId(int id) {
  39. this.id = id;
  40. }
  41. public String getAddress() {
  42. return address;
  43. }
  44. public void setAddress(String address) {
  45. this.address = address;
  46. }
  47. @Override
  48. public String toString() {
  49. return "Info{" +
  50. "id=" + id +
  51. ", address='" + address + '\'' +
  52. '}';
  53. }
  54. }
  55. public class RequestParam {
  56. private User user;
  57. private Info info;
  58. public User getUser() {
  59. return user;
  60. }
  61. public void setUser(User user) {
  62. this.user = user;
  63. }
  64. public Info getInfo() {
  65. return info;
  66. }
  67. public void setInfo(Info info) {
  68. this.info = info;
  69. }
  70. }

定义了三个实体 RequestParam里面又封装了User类和Info类

JAVA代码


   
  1. @RequestMapping(value = "/show",method = RequestMethod.POST)
  2. public String show(@RequestBody RequestParam param){
  3. User user = param.getUser();
  4. Info info = param.getInfo();
  5. return user.toString();
  6. }

前台代码


   
  1. $("#ok2").click(function(){
  2. var json = {"user":{"id":9527,"userName":"zcy","realName":"钢铁侠"},"info":{"id":998,"address":"纽约"}};
  3. $.ajax({
  4. url:"http://localhost:8080/more/show",
  5. type:"post",
  6. cache:false,
  7. contentType:"application/json",
  8. data:JSON.stringify(json),
  9. success:function(data){
  10. alert(data);
  11. }
  12. });
  13. });

可以成功接收到对象,但是显得没有那么优雅,每次请求数据不同都要另外写一个包装类,显得很麻烦。


第二种方法,用Map对象接收 更加简单粗暴

JAVA代码


   
  1. @RequestMapping(value = "/show")
  2. public String test(@RequestBody Map<String,Object> map){
  3. // 拿到Object之后 再做转换为实体即可 可以用FastJson
  4. Object user = map.get( "user");
  5. Object info = map.get( "info");
  6. return "success";
  7. }

也不够方便 每个对象还要再做一次转换

第三种方法,使用自定义的HandlerMethodArgumentResolver

自定义注解 加在控制器的参数前作为标记


   
  1. @Target(ElementType.PARAMETER)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface JsonObject {
  5. }

自定义处理类 实现HandlerMethodArgumentResolver接口


   
  1. public class JsonObjectArgResolverHandler implements HandlerMethodArgumentResolver {
  2. @Override
  3. public boolean supportsParameter(MethodParameter methodParameter) {
  4. return methodParameter.hasParameterAnnotation(JsonObject.class);
  5. }
  6. @Override
  7. public Object resolveArgument(MethodParameter methodParameter,
  8. ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
  9. WebDataBinderFactory webDataBinderFactory) throws Exception {
  10. // 获取Controller中的参数名
  11. String name = methodParameter.getParameterName();
  12. // 获取Controller中参数的类型
  13. Class clazz = methodParameter.getParameterType();
  14. Object arg = null;
  15. // 获取该参数实体的所用属性
  16. Field[] fields = clazz.getDeclaredFields();
  17. // 实例化
  18. Object target = clazz.newInstance();
  19. // 创建WebDataBinder对象 反射 遍历fields给属性赋值
  20. WebDataBinder binder = webDataBinderFactory.createBinder(nativeWebRequest, null,name);
  21. for (Field field:fields){
  22. field.setAccessible( true);
  23. String fieldName = field.getName();
  24. Class<?> fieldType = field.getType();
  25. // 在request中 多对象json数据的key被解析为 user[id] user[realName] info[address] 的这种形式
  26. String value = nativeWebRequest.getParameter(name + "[" + fieldName + "]");
  27. arg = binder.convertIfNecessary(value,fieldType,methodParameter);
  28. field.set(target,arg);
  29. }
  30. return target;
  31. }
  32. }

注册自己写的处理类


   
  1. @Component
  2. public class MyWebAppConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
  5. // 配置自定义接收参数
  6. WebMvcConfigurer. super.addArgumentResolvers(resolvers);
  7. resolvers.add( new JsonObjectArgResolverHandler());
  8. }
  9. }

Controller


   
  1. @RequestMapping(value = "/custom")
  2. public String custom(@JsonObject User user, @JsonObject Info info){
  3. System.out.println(user.toString());
  4. System.out.println(info.toString());
  5. return "success";
  6. }

前台代码


   
  1. $("#ok2").click(function(){
  2. var json = {"user":{"id":9527,"userName":"zcy","realName":"钢铁侠"},"info":{"id":998,"address":"纽约"}};
  3. $.ajax({
  4. url:"http://localhost:8080/more/custom",
  5. type:"post",
  6. cache:false,
  7. // 直接传josn对象 这里与上文不同
  8. data:json,
  9. success:function(data){
  10. alert(data);
  11. }
  12. });
  13. });

第三种方式相对比较好 但我有几点还是没明白

public Object resolveArgument(MethodParameter methodParameter,
                              ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
                              WebDataBinderFactory webDataBinderFactory) 
这个方法中的 ModelAndViewContainer和webDataBinderFactory 这两个对象的作用,怎样写能够优雅,欢迎大家不吝赐教。



  •                     <li class="tool-item tool-active is-like "><a href='javascript:void(0)'>

第一种方法,用包装类封装对象

实体类对象


   
  1. public class User {
  2. private int id;
  3. private String userName;
  4. private String realName;
  5. public int getId() {
  6. return id;
  7. }
  8. public void setId(int id) {
  9. this.id = id;
  10. }
  11. public String getUserName() {
  12. return userName;
  13. }
  14. public void setUserName(String userName) {
  15. this.userName = userName;
  16. }
  17. public String getRealName() {
  18. return realName;
  19. }
  20. public void setRealName(String realName) {
  21. this.realName = realName;
  22. }
  23. @Override
  24. public String toString() {
  25. return "User{" +
  26. "id=" + id +
  27. ", userName='" + userName + '\'' +
  28. ", realName='" + realName + '\'' +
  29. '}';
  30. }
  31. }
  32. public class Info {
  33. private int id;
  34. private String address;
  35. public int getId() {
  36. return id;
  37. }
  38. public void setId(int id) {
  39. this.id = id;
  40. }
  41. public String getAddress() {
  42. return address;
  43. }
  44. public void setAddress(String address) {
  45. this.address = address;
  46. }
  47. @Override
  48. public String toString() {
  49. return "Info{" +
  50. "id=" + id +
  51. ", address='" + address + '\'' +
  52. '}';
  53. }
  54. }
  55. public class RequestParam {
  56. private User user;
  57. private Info info;
  58. public User getUser() {
  59. return user;
  60. }
  61. public void setUser(User user) {
  62. this.user = user;
  63. }
  64. public Info getInfo() {
  65. return info;
  66. }
  67. public void setInfo(Info info) {
  68. this.info = info;
  69. }
  70. }

定义了三个实体 RequestParam里面又封装了User类和Info类

JAVA代码


   
  1. @RequestMapping(value = "/show",method = RequestMethod.POST)
  2. public String show(@RequestBody RequestParam param){
  3. User user = param.getUser();
  4. Info info = param.getInfo();
  5. return user.toString();
  6. }

前台代码


   
  1. $("#ok2").click(function(){
  2. var json = {"user":{"id":9527,"userName":"zcy","realName":"钢铁侠"},"info":{"id":998,"address":"纽约"}};
  3. $.ajax({
  4. url:"http://localhost:8080/more/show",
  5. type:"post",
  6. cache:false,
  7. contentType:"application/json",
  8. data:JSON.stringify(json),
  9. success:function(data){
  10. alert(data);
  11. }
  12. });
  13. });

可以成功接收到对象,但是显得没有那么优雅,每次请求数据不同都要另外写一个包装类,显得很麻烦。


第二种方法,用Map对象接收 更加简单粗暴

JAVA代码


   
  1. @RequestMapping(value = "/show")
  2. public String test(@RequestBody Map<String,Object> map){
  3. // 拿到Object之后 再做转换为实体即可 可以用FastJson
  4. Object user = map.get( "user");
  5. Object info = map.get( "info");
  6. return "success";
  7. }

也不够方便 每个对象还要再做一次转换

第三种方法,使用自定义的HandlerMethodArgumentResolver

自定义注解 加在控制器的参数前作为标记


   
  1. @Target(ElementType.PARAMETER)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. @Documented
  4. public @interface JsonObject {
  5. }

自定义处理类 实现HandlerMethodArgumentResolver接口


   
  1. public class JsonObjectArgResolverHandler implements HandlerMethodArgumentResolver {
  2. @Override
  3. public boolean supportsParameter(MethodParameter methodParameter) {
  4. return methodParameter.hasParameterAnnotation(JsonObject.class);
  5. }
  6. @Override
  7. public Object resolveArgument(MethodParameter methodParameter,
  8. ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
  9. WebDataBinderFactory webDataBinderFactory) throws Exception {
  10. // 获取Controller中的参数名
  11. String name = methodParameter.getParameterName();
  12. // 获取Controller中参数的类型
  13. Class clazz = methodParameter.getParameterType();
  14. Object arg = null;
  15. // 获取该参数实体的所用属性
  16. Field[] fields = clazz.getDeclaredFields();
  17. // 实例化
  18. Object target = clazz.newInstance();
  19. // 创建WebDataBinder对象 反射 遍历fields给属性赋值
  20. WebDataBinder binder = webDataBinderFactory.createBinder(nativeWebRequest, null,name);
  21. for (Field field:fields){
  22. field.setAccessible( true);
  23. String fieldName = field.getName();
  24. Class<?> fieldType = field.getType();
  25. // 在request中 多对象json数据的key被解析为 user[id] user[realName] info[address] 的这种形式
  26. String value = nativeWebRequest.getParameter(name + "[" + fieldName + "]");
  27. arg = binder.convertIfNecessary(value,fieldType,methodParameter);
  28. field.set(target,arg);
  29. }
  30. return target;
  31. }
  32. }

注册自己写的处理类


   
  1. @Component
  2. public class MyWebAppConfig implements WebMvcConfigurer {
  3. @Override
  4. public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
  5. // 配置自定义接收参数
  6. WebMvcConfigurer. super.addArgumentResolvers(resolvers);
  7. resolvers.add( new JsonObjectArgResolverHandler());
  8. }
  9. }

Controller


   
  1. @RequestMapping(value = "/custom")
  2. public String custom(@JsonObject User user, @JsonObject Info info){
  3. System.out.println(user.toString());
  4. System.out.println(info.toString());
  5. return "success";
  6. }

前台代码


   
  1. $("#ok2").click(function(){
  2. var json = {"user":{"id":9527,"userName":"zcy","realName":"钢铁侠"},"info":{"id":998,"address":"纽约"}};
  3. $.ajax({
  4. url:"http://localhost:8080/more/custom",
  5. type:"post",
  6. cache:false,
  7. // 直接传josn对象 这里与上文不同
  8. data:json,
  9. success:function(data){
  10. alert(data);
  11. }
  12. });
  13. });

第三种方式相对比较好 但我有几点还是没明白

public Object resolveArgument(MethodParameter methodParameter,
                              ModelAndViewContainer modelAndViewContainer, NativeWebRequest nativeWebRequest,
                              WebDataBinderFactory webDataBinderFactory) 
这个方法中的 ModelAndViewContainer和webDataBinderFactory 这两个对象的作用,怎样写能够优雅,欢迎大家不吝赐教。



  •                     <li class="tool-item tool-active is-like "><a href='javascript:void(0)'>