SpringMVC - @RequestJson之HandlerMethodArgumentResolver 从入门到青铜(六)

简介: SpringMVC - @RequestJson之HandlerMethodArgumentResolver 从入门到青铜(六)

解决方案

1、第一种方案

在服务启动时,动态替换掉MapMethodProcessor#supportsParameter的字节码。

@Override
public boolean supportsParameter(MethodParameter parameter) {
  if(parameter.hasParameterAnnotation(RequestJson.class))
  {
    return false;
  }
  return Map.class.isAssignableFrom(parameter.getParameterType());
}

使用javassist可以实现这一点,但是这样去做,代码复杂性较高。“任何一个功能的实现,都要想办法降低代码复杂性”。


第二种方案


首先删除WebConfig,让spring不再自动的将自定义解析器加到RequestMappingHandlerAdapter的解析器容器中;然后我们通过下面的方式手动的将RequestJsonHandlerMethodArgumentResolver加载到RequestMappingHandlerAdapter的解析容器中。(通过这样的方式,我们可以任意的指定解析器的顺序)。


@Configuration
public class MethodArgumentResolver {
    @Autowired
    private RequestMappingHandlerAdapter adapter;
    @PostConstruct
    public void injectSelfMethodArgumentResolver() {
        List<HandlerMethodArgumentResolver> argumentResolvers = new ArrayList<>();
        argumentResolvers.add(new RequestJsonHandlerMethodArgumentResolver());
        argumentResolvers.addAll(adapter.getArgumentResolvers());
        adapter.setArgumentResolvers(argumentResolvers);
    }
}

Ps:XML配置的话,思路类似,但是会出现一个问题,极有可能会影响其它参数解析原本并不冲突的解析器,导致这个功能OK了,另一个功能又崩了的局面,所以还有最后一种方案(推荐)。


第三种方案


此处我们封装一个类似JSONObject的实体类MapWrapper来替代Map原型解决,可以通过MapWrapper.getMapWrapper()拿到我们需要的Map

package com.luxsuen.requestjson.util;
import com.alibaba.fastjson.JSONObject;
public class MapWrapper {
    private JSONObject jsonObject;
    public MapWrapper(JSONObject jsonObject) {
        this.jsonObject = jsonObject;
    }
    public JSONObject getMapWrapper() {
        return jsonObject;
    }
}

五、测试项目

package com.luxsuen.requestjson.entity;
import java.util.Date;
public class User {
    private Integer userId;
    private String userAccount;
    private String userPassword;
    private String userRemark;
    private Byte userDel;
    private Date userCreatetime;
    private Date userUpdatetime;
    public User(Integer userId, String userAccount, String userPassword, String userRemark, Byte userDel, Date userCreatetime, Date userUpdatetime) {
        this.userId = userId;
        this.userAccount = userAccount;
        this.userPassword = userPassword;
        this.userRemark = userRemark;
        this.userDel = userDel;
        this.userCreatetime = userCreatetime;
        this.userUpdatetime = userUpdatetime;
    }
    public User() {
        super();
    }
    public Integer getUserId() {
        return userId;
    }
    public void setUserId(Integer userId) {
        this.userId = userId;
    }
    public String getUserAccount() {
        return userAccount;
    }
    public void setUserAccount(String userAccount) {
        this.userAccount = userAccount == null ? null : userAccount.trim();
    }
    public String getUserPassword() {
        return userPassword;
    }
    public void setUserPassword(String userPassword) {
        this.userPassword = userPassword == null ? null : userPassword.trim();
    }
    public String getUserRemark() {
        return userRemark;
    }
    public void setUserRemark(String userRemark) {
        this.userRemark = userRemark == null ? null : userRemark.trim();
    }
    public Byte getUserDel() {
        return userDel;
    }
    public void setUserDel(Byte userDel) {
        this.userDel = userDel;
    }
    public Date getUserCreatetime() {
        return userCreatetime;
    }
    public void setUserCreatetime(Date userCreatetime) {
        this.userCreatetime = userCreatetime;
    }
    public Date getUserUpdatetime() {
        return userUpdatetime;
    }
    public void setUserUpdatetime(Date userUpdatetime) {
        this.userUpdatetime = userUpdatetime;
    }
}
package com.luxsuen.requestjson.web;
import com.luxsuen.jsonutil.util.JsonUtil;
import com.luxsuen.requestjson.entity.User;
import com.luxsuen.requestjson.annotation.RequestJson;
import com.luxsuen.requestjson.util.MapWrapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
@Controller
@RequestMapping("/user/")
public class UserController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    /**
     * @Author Lux Sun
     * @Description: 测试(以大括号开始) @PathVariable & @RequestJson + 一步获取分参后的value
     * @Param: [userId, userDel, userAccount, scoreArray, money, user1, user2, user3, userList, mapWrapper1, mapWrapper2]
     * @Return: java.lang.Object
     */
    @RequestMapping(value = "info/{userId}", method = RequestMethod.POST)
    @ResponseBody
    public Object checkRequestJsonByBeginBigBrace(
                                                @PathVariable(value = "userId") Integer userId,
                                                @RequestJson(value = "userDel") Boolean userDel,
                                                @RequestJson(value = "userAccount") String userAccount,
                                                @RequestJson(value = "scoreArray") Double[] scoreArray,
                                                @RequestJson(value = "money") BigDecimal money,
                                                @RequestJson(value = "user1") User user1,
                                                @RequestJson(value = "user2") User user2,
                                                @RequestJson(value = "user3") User user3,
                                                @RequestJson(value = "userList") List<User> userList,
                                                @RequestJson(value = "mapWrapper1") MapWrapper mapWrapper1,
                                                @RequestJson(value = "mapWrapper2") MapWrapper mapWrapper2)
    {
        // 获取实体类 & 实体类数组
        Object user = JsonUtil.getJsonEntityByKeyArray(mapWrapper1.getMapWrapper(), User.class, "k8");
        Object userlist = JsonUtil.getJsonEntityListByKeyArray(mapWrapper1.getMapWrapper(), User.class, "k9");
        // 获取普通类型 & 集合
        Object integer = JsonUtil.getJsonValueByKeyArray(mapWrapper1.getMapWrapper(), Integer.class, "k9", "0", "userId");
        Object string = JsonUtil.getJsonValueByKeyArray(mapWrapper1.getMapWrapper(), String.class, "k2");
        Object bool = JsonUtil.getJsonValueByKeyArray(mapWrapper1.getMapWrapper(), Boolean.class, "k3");
        Object array1 = JsonUtil.getJsonValueByKeyArray(mapWrapper1.getMapWrapper(), List.class, "k4");
        Object map1 = JsonUtil.getJsonValueByKeyArray(mapWrapper1.getMapWrapper(), Map.class, "k5");
        Object map2 = JsonUtil.getJsonValueByKeyArray(mapWrapper1.getMapWrapper(), Map.class, "k6");
        Object array2 = JsonUtil.getJsonValueByKeyArray(mapWrapper1.getMapWrapper(), List.class, "k7");
        return null;
    }
    /**
     * @Author Lux Sun
     * @Description: 测试(以中括号开始)
     * @Param: [mapWrapper3]
     * @Return: java.lang.Object
     */
    @RequestMapping(value = "info", method = RequestMethod.POST)
    @ResponseBody
    public Object checkRequestJsonByBeginMidBrace(@RequestJson(value = "mapWrapper3") MapWrapper mapWrapper3)
    {
        return null;
    }
    /**
     * @Author Lux Sun
     * @Description: 测试(只有大括号)
     * @Param: [arr]
     * @Return: java.lang.Object
     */
    @RequestMapping(value = "onlyBigBrace", method = RequestMethod.POST)
    @ResponseBody
    public Object checkRequestJsonByOnlyBigBrace(@RequestJson(value = "name") String name)
    {
        return null;
    }
    /**
     * @Author Lux Sun
     * @Description: 测试(只有中括号)
     * @Param: [arr]
     * @Return: java.lang.Object
     */
    @RequestMapping(value = "onlyMidBrace", method = RequestMethod.POST)
    @ResponseBody
    public Object checkRequestJsonByOnlyMidBrace(@RequestJson(value = "arr") Integer[] arr)
    {
        return null;
    }
}

测试案例

// 以大括号开始嵌套
{
  "userId": 1,
  "userDel": false,
  "userAccount": "Admin",
  "scoreArray": [
    98.5,
    89,
    120
  ],
  "money": 123.45678987654321,
  "user1": {
    "userId": 1,
    "userAccount": "Bob1",
    "userPassword": "abc123456",
    "userRemark": "",
    "userDel": 0,
    "userCreatetime": "2019-03-07 16:52:46",
    "userUpdatetime": "2019-03-07 16:52:46"
  },
  "user2": {
    "userId": 2,
    "userAccount": "Bob2",
    "userPassword": "abc123456",
    "userRemark": "",
    "userDel": 0,
    "userCreatetime": "2019-03-07 16:52:46",
    "userUpdatetime": "2019-03-07 16:52:46",
    "more": "!@#$%^&*"
  },
  "user3": {
    "userId": 3,
    "userAccount": "Bob3",
    "userPassword": "abc123456",
    "userRemark": "用户",
    "userCreatetime": "2019-03-07 16:52:46",
    "userUpdatetime": "2019-03-07 16:52:46"
  },
  "userList": [
    {
      "userId": 2,
      "userAccount": "Alice",
      "userPassword": "abc789",
      "userRemark": "大学生",
      "userDel": 1,
      "userCreatetime": "2019-03-08 16:52:46",
      "userUpdatetime": "2019-03-08 16:52:46"
    },
    {
      "userId": 3,
      "userAccount": "Tom",
      "userPassword": "[{}]147@#",
      "userRemark": "学生",
      "userDel": 0,
      "userCreatetime": "2007-03-08 16:52:46",
      "userUpdatetime": "2007-03-08 16:52:46"
    }
  ],
  "mapWrapper1": {
    "k1": 123,
    "k2": "abc",
    "k3": true,
    "k4": [
      1,
      2,
      3
    ],
    "k5": {
      "k5-1": "qwer",
      "k5-2": 90.6
    },
    "k6": {"k6-1": [
      "qaz",
      "wsx"
    ]},
    "k7": [
      {"k7-1": 456},
      {"k7-2": "asdf"}
    ],
    "k8": {
      "userId": 3,
      "userAccount": "Bob3",
      "userPassword": "abc123456",
      "userRemark": "用户",
      "userCreatetime": "2019-03-07 16:52:46",
      "userUpdatetime": "2019-03-07 16:52:46"
    },
    "k9": [
      {
        "userId": 2,
        "userAccount": "Alice",
        "userPassword": "abc789",
        "userRemark": "大学生",
        "userDel": 1,
        "userCreatetime": "2019-03-08 16:52:46",
        "userUpdatetime": "2019-03-08 16:52:46"
      },
      {
        "userId": 3,
        "userAccount": "Tom",
        "userPassword": "[{}]147@#",
        "userRemark": "学生",
        "userDel": 0,
        "userCreatetime": "2007-03-08 16:52:46",
        "userUpdatetime": "2007-03-08 16:52:46"
      }
    ]
  },
  "mapWrapper2": [
    1,
    "2",
    {
      "k1": 123,
      "k2": "abc",
      "k3": true,
      "k4": [
        1,
        2,
        3
      ],
      "k5": {
        "k5-1": "qwer",
        "k5-2": 90.6
      },
      "k6": {"k6-1": [
        "qaz",
        "wsx"
      ]},
      "k7": [
        {"k7-1": 456},
        {"k7-2": "asdf"}
      ]
    },
    {
      "k8": 456,
      "k9": "def",
      "k10": false,
      "k11": [
        4,
        5,
        6
      ],
      "k12": {
        "k12-1": "qwer",
        "k12-2": 90.6
      },
      "k13": {"k13-1": [
        "qaz",
        "wsx"
      ]},
      "k14": [
        {"k14-1": 456},
        {"k14-2": "asdf"}
      ]
    }
  ]
}
// 以中括号开始嵌套
[
  1,
  "2",
  {
    "k1": 123,
    "k2": "abc",
    "k3": true,
    "k4": [
      1,
      2,
      3
    ],
    "k5": {
      "k5-1": "qwer",
      "k5-2": 90.6
    },
    "k6": {"k6-1": [
      "qaz",
      "wsx"
    ]},
    "k7": [
      {"k7-1": 456},
      {"k7-2": "asdf"}
    ]
  },
  {
    "k8": 456,
    "k9": "def",
    "k10": false,
    "k11": [
      4,
      5,
      6
    ],
    "k12": {
      "k12-1": "qwer",
      "k12-2": 90.6
    },
    "k13": {"k13-1": [
      "qaz",
      "wsx"
    ]},
    "k14": [
      {"k14-1": 456},
      {"k14-2": "asdf"}
    ]
  }
]
// 只有大括号
{
  "name": "Admin"
}
// 只有中括号
[
  1, 2, 3
]
// required
{
}

Ps:如果在JsonPath执行报错时,当找不到“key”引起的话,这是正常现象,并不是程序的BUG噢~

目录
相关文章
|
3月前
|
XML 前端开发 Java
SpringMVC入门到实战------2、SpringMVC创建实例Hello SpringMVC(maven+tomcat)
这篇文章是SpringMVC框架的入门教程,详细指导了如何在IDEA中使用Maven和Tomcat创建SpringMVC工程,包括添加依赖、配置web.xml、编写控制器、创建配置文件、配置Tomcat服务器以及进行基本的测试,展示了一个简单的Hello SpringMVC示例。
SpringMVC入门到实战------2、SpringMVC创建实例Hello SpringMVC(maven+tomcat)
SpringMVC入门到实战------5、域对象共享数据 Request、Session、Application、Model、ModelAndView、Map、ModelMap的详细使用及代码实例
这篇文章详细解释了在IntelliJ IDEA中如何使用Mute Breakpoints功能来快速跳过程序中的后续断点,并展示了如何一键清空所有设置的断点。
SpringMVC入门到实战------5、域对象共享数据 Request、Session、Application、Model、ModelAndView、Map、ModelMap的详细使用及代码实例
|
3月前
|
存储 前端开发 Java
SpringMVC入门到实战------1、SpringMVC简介
这篇文章是SpringMVC框架的入门介绍,阐述了MVC架构的概念和分层,解释了SpringMVC作为Spring家族的一部分在Web应用开发中的作用和重要性,并概述了SpringMVC的关键特点,包括与Spring IOC容器的无缝集成、基于Servlet的DispatcherServlet、全面的解决方案、代码简洁性、高内聚低耦合的组件化设计以及卓越的性能表现。
SpringMVC入门到实战------ 十一 拦截器的使用
这篇文章介绍了SpringMVC中拦截器的使用,包括拦截器的配置、拦截器的三个抽象方法`preHandle`、`postHandle`和`afterCompletion`的作用,以及多个拦截器的执行顺序和规则。
SpringMVC入门到实战------ 十一 拦截器的使用
|
3月前
|
JSON 前端开发 JavaScript
SpringMVC入门到实战------九 HttpMessageConverter @RequestBody 、@ResponseBody 、RequestEntity、ResponseEntity
这篇文章详细介绍了SpringMVC中的`HttpMessageConverter`接口及其相关的`@RequestBody`、`@ResponseBody`、`RequestEntity`和`ResponseEntity`注解和类型的使用,包括如何将请求体转换为Java对象、如何将Java对象转换为响应体、以及如何处理JSON和AJAX请求。
SpringMVC入门到实战------九 HttpMessageConverter @RequestBody 、@ResponseBody 、RequestEntity、ResponseEntity
|
3月前
|
Java 数据库连接 Spring
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
文章是关于Spring、SpringMVC、Mybatis三个后端框架的超详细入门教程,包括基础知识讲解、代码案例及SSM框架整合的实战应用,旨在帮助读者全面理解并掌握这些框架的使用。
后端框架入门超详细 三部曲 Spring 、SpringMVC、Mybatis、SSM框架整合案例 【爆肝整理五万字】
|
3月前
|
缓存 Java 应用服务中间件
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
这篇文章详细介绍了在SpringMVC中创建JSP页面的全过程,包括项目的创建、配置、Tomcat的设置,以及如何实现页面跳转和配置模板解析器,最后还对比了JSP和HTML模板解析的差异。
SpringMVC入门到实战------七、SpringMVC创建JSP页面的详细过程+配置模板+实现页面跳转+配置Tomcat。JSP和HTML配置模板的差异对比(二)
|
3月前
|
XML JSON 数据库
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
这篇文章详细介绍了RESTful的概念、实现方式,以及如何在SpringMVC中使用HiddenHttpMethodFilter来处理PUT和DELETE请求,并通过具体代码案例分析了RESTful的使用。
SpringMVC入门到实战------七、RESTful的详细介绍和使用 具体代码案例分析(一)
|
3月前
|
前端开发
SpringMVC入门到实战------六、SpringMVC的视图。ThymeleafView、转发视图、重定向视图、视图控制器的使用详解
这篇文章详细介绍了SpringMVC中的视图类型,包括ThymeleafView、转发视图、重定向视图和视图控制器的使用,以及如何通过源码查看确定使用的视图渲染器类型。
SpringMVC入门到实战------六、SpringMVC的视图。ThymeleafView、转发视图、重定向视图、视图控制器的使用详解
SpringMVC入门到实战------十二、异常处理器
这篇文章介绍了SpringMVC中拦截器的使用,包括拦截器的配置、拦截器的三个抽象方法`preHandle`、`postHandle`和`afterCompletion`的作用,以及多个拦截器的执行顺序和规则。