HandlerMethodArgumentResolver(四):自定参数解析器处理特定场景需求,介绍PropertyNamingStrategy的使用【享学Spring MVC】(下)

简介: HandlerMethodArgumentResolver(四):自定参数解析器处理特定场景需求,介绍PropertyNamingStrategy的使用【享学Spring MVC】(下)
场景二:


在微服务场景中有个特别常见的现象:跟第三方服务做对接时(如python老系统),你不乏会遇到如下两个痛点:


  1. 对方系统是以下划线形式命名的(和Java命名规范相悖)
  2. 对方系统的参数json串层次较深,而对你有用的仅仅是深处的一小部分


例如这个参数串:


{
    "data": {
        "transport_data": {
            "demo_name": "fsx",
            "demo_age": 18
        },
        "secret_info": {
            "code": "fkldshjfkldshj"
        }
    },
    "code": "200",
    "msg": "this is a message"
}


对你真正有用的只有demo_name和demo_age两个值,怎么破???

我相信绝大部分小伙伴都这么做:按照此结构先定义一个DTO全部接收回来(字段命名也用下划线方式命名),然后再一个个处理。若这么做虽然简单,我觉得还是有如下两个不妥的地方:


Java属性名也必须用下划线命名,看起来影响了命名体系(其实就是看着不爽,哈哈)

按照参数这种复杂结构书写,使得我们关注点分散,不能聚焦到真真关心的那一块数据上

针对这些痛点,废话不多说,直接上我的处理方案:


1、定义一个模型(只写我自己关注的属性)

@Getter
@Setter
@ToString
public class TranUserVo {
    private String demoName;
    private Long demoAge;
}


定义的模型非常之简单,不仅只关心我要的数据,而且还是标准的java驼峰命名,没必要去迁就别的语言而丧失自己优雅性,否则容易把自己弄得四不像(万一又接python,又接.net呢?)~


2、自定义一个参数解析器并且注册上去


public class TranUserArgumentResolver implements HandlerMethodArgumentResolver {
    // 只处理这个类型,不需要注解
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        Class<?> parameterType = parameter.getParameterType();
        return TranUserVo.class.isAssignableFrom(parameterType);
    }
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        HttpMethod httpMethod = HttpMethod.valueOf(request.getMethod());
        // 本例为了简单,演示get的情况(这里使用key为:demoKey)
        if (httpMethod == HttpMethod.GET) {
            String value = request.getParameter("demoKey");
            JSONObject transportData = (JSONObject) ((JSONObject) JSON.parseObject(value).get("data")).get("transport_data");
            // 采用命名策略,转换TranUserVo实例对象再返回
            // 序列化配置对象
            ParserConfig config = new ParserConfig();
            config.propertyNamingStrategy = PropertyNamingStrategy.SnakeCase;
            TranUserVo tranUserVo = transportData.toJavaObject(TranUserVo.class, config, 0);
            return tranUserVo;
        } else { // 从body提里拿
            // ...
            return null;
        }
    }
}
// 注册此自定义的参数解析器
@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    argumentResolvers.add(new TranUserArgumentResolver());
}


对此部分我说明一点:对于json到对象的解析,理应还加上@Valid校验的能力的,此部分我就省略了,毕竟也不是本文所关心的重点


测试用例:


@ResponseBody
@GetMapping("/test/tranuser")
public Object testCurrUser(TranUserVo tranUser) {
    return tranUser;
}


请求:/test/tranuser?demoKey=上面那一大长串json串,得到的结果就是预期的结果喽:


image.png


完美~


说明:这种长传现在需要使用post/put传递,本文只是为了简化演示,所以使用了GET请求,毕竟解析Body体不是本文所需讨论的~


总结


我认为,自定义参数解析器HandlerMethodArgumentResolver最重要不是它本身的实现,而是它的指导思想:分离关注,业务解耦。当然本文我摘出来的两个使用场景案例只是冰山一角,各位需要举一反三,才能融会贯通。


既然我们可以自定义参数处理器HandlerMethodArgumentResolver,自然也就可以自定义返回值处理器HandlerMethodReturnValueHandler喽,作为课后作业,有兴趣者不妨一试,还是非常有作用的。特别在处理"老项目"的兼容性上非常好使,或许能让你大放异彩~

相关文章
|
22小时前
|
Java 开发者 Spring
深入解析 @Transactional:Spring 事务管理的艺术及实战应对策略
深入解析 @Transactional:Spring 事务管理的艺术及实战应对策略
6 2
|
23小时前
|
存储 缓存 Java
深入解析Spring框架中的ReflectionUtils
深入解析Spring框架中的ReflectionUtils
8 1
|
2天前
|
Java 数据库连接 Spring
Spring 整合 MyBatis 底层源码解析
Spring 整合 MyBatis 底层源码解析
|
2天前
|
消息中间件 Java Maven
深入理解Spring Boot Starter:概念、特点、场景、原理及自定义starter
深入理解Spring Boot Starter:概念、特点、场景、原理及自定义starter
|
1天前
|
JSON 缓存 Java
Spring Boot中的JSON解析优化
Spring Boot中的JSON解析优化
序-Servlet和SpringMVC的联系和区别-配置路径先想好使用的使用的方法,然后匹配的需要的技术
序-Servlet和SpringMVC的联系和区别-配置路径先想好使用的使用的方法,然后匹配的需要的技术
|
1天前
|
Java 容器 Spring
Spring5源码解析5-ConfigurationClassPostProcessor (上)
Spring5源码解析5-ConfigurationClassPostProcessor (上)
|
1天前
|
Java 测试技术 应用服务中间件
Spring 与 Spring Boot:深入解析
Spring 与 Spring Boot:深入解析
8 0
|
1天前
|
XML Java 开发者
“掌握Spring IoC和AOP:30道面试必备问题解析!“
“掌握Spring IoC和AOP:30道面试必备问题解析!“
9 0
|
1天前
|
JSON 前端开发 数据格式
SpringMVC的数据响应-直接回写json字符串
SpringMVC的数据响应-直接回写json字符串

推荐镜像

更多