zoukankan      html  css  js  c++  java
  • spring 自定参数解析器(HandlerMethodArgumentResolver)

    由于之前用@RequestParam无法接收request payload 正文格式为json格式的字符串,只能使用@RequestBody整个接收,觉得麻烦,但是spring自带的参数解析器不具有这种功能,只能尝试着用自定义参数解析器去解决。

    自定义解析器需要实现HandlerMethodArgumentResolver接口,HandlerMethodArgumentResolver接口包含两个接口:这里写图片描述

    接口说明:
    supportsParameter:用于判定是否需要处理该参数分解,返回true为需要,并会去调用下面的方法resolveArgument。
    resolveArgument:真正用于处理参数分解的方法,返回的Object就是controller方法上的形参对象。

    1、自定义注解

    package com.manqian.crm.resolver;
    
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    
    @Target(ElementType.PARAMETER)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface JsonParam {
    
        String value();
    
        boolean required() default true;
    
        String defaultValue() default "";
    }
    
    

    若不想自定义注解,可以直接在实现HandlerMethodArgumentResolver的supportsParameter直接返回true

    2、自定义参数解析器,实现HandlerMethodArgumentResolver接口

    package com.manqian.crm.resolver;
    
    import com.jayway.jsonpath.JsonPath;
    import com.jayway.jsonpath.PathNotFoundException;
    import com.manqian.crm.api.exception.ParamCheckException;
    import org.apache.commons.io.IOUtils;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.MethodParameter;
    import org.springframework.web.bind.support.WebDataBinderFactory;
    import org.springframework.web.context.request.NativeWebRequest;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.method.support.ModelAndViewContainer;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    
    public class JsonPathArgumentResolver implements HandlerMethodArgumentResolver {
    
        private static final String JSON_REQUEST_BODY = "JSON_REQUEST_BODY";
    
        //判断是否支持要转换的参数类型
        @Override
        public boolean supportsParameter(MethodParameter parameter) {
            return parameter.hasParameterAnnotation(JsonParam.class);
        }
    
        //当支持后进行相应的转换
        @Override
        public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
            String body = getRequestBody(webRequest);
            Object val = null;
    
            try {
                val = JsonPath.read(body, parameter.getParameterAnnotation(JsonParam.class).value());
                if (parameter.getParameterAnnotation(JsonParam.class).required() && val == null) {
                    throw new ParamCheckException(parameter.getParameterAnnotation(JsonParam.class).value() + "不能为空");
                }
            } catch (PathNotFoundException exception) {
                System.out.println(exception.getStackTrace());
                if (parameter.getParameterAnnotation(JsonParam.class).required()) {
    //                throw new ParamCheckException(parameter.getParameterAnnotation(JsonParam.class).value() + "不能为空");
                    throw exception;
                }
            }
            return val;
        }
    
        private String getRequestBody(NativeWebRequest webRequest) {
            HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
            String jsonBody = (String) servletRequest.getAttribute(JSON_REQUEST_BODY);
            if (jsonBody == null) {
                try {
                    jsonBody = IOUtils.toString(servletRequest.getInputStream());
                    servletRequest.setAttribute(JSON_REQUEST_BODY, jsonBody);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
            return jsonBody;
    
        }
    
    }
    
    

    3、注册自定义参数解析器
    springboot方式:
    1、

    package com.demo;
    
    import java.util.List;
    
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
    
    import com.demo.mvc.component.MultiPersonArgumentResolver;
    import com.demo.mvc.component.PersonArgumentResolver;
    
    @SpringBootApplication
    public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    
        @Override
        protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    
            // 注册JsonPathArgumentResolver的参数分解器
            argumentResolvers.add(new JsonPathArgumentResolver());
        }
    }
    

    2、

    package com.manqian.crm.resolver;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.method.support.HandlerMethodArgumentResolver;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
    
    import java.util.List;
    
    @Configuration
    public class ClientResourcesConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
    //        super.addArgumentResolvers(argumentResolvers);
            argumentResolvers.add(new JsonPathArgumentResolver());
        }
    }
    
    

    传统XML格式:
    1、

    <mvc:annotation-driven>
          <mvc:argument-resolvers>
            <bean class="com.manqian.crm.resolver.JsonPathArgumentResolver"/>
          </mvc:argument-resolvers>
    </mvc:annotation-driven>
    

    2、

    <bean class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
        <property name="jsonPathArgumentResolver">
              <bean class="com.manqian.crm.resolver.JsonPathArgumentResolver"/>
        </property>
    </bean>
    

    使用:
    1、依赖:

    com.jayway.jsonpath
    json-path

    2、controller方法使用@JsonParam接收参数
    这里写图片描述

    参考:https://stackoverflow.com/questions/12893566/passing-multiple-variables-in-requestbody-to-a-spring-mvc-controller-using-ajax/12897632#12897632

    https://my.oschina.net/sugarZone/blog/704575

  • 相关阅读:
    能用HTML/CSS解决的问题,就不要用JS
    跨域
    从输入url到页面展示到底发生了什么
    hosts 文件
    了解Web及网络基础
    hybrid
    组件化和 React
    MVVM 和 VUE
    虚拟 DOM
    ES6模块化与常用功能
  • 原文地址:https://www.cnblogs.com/But-you/p/10670577.html
Copyright © 2011-2022 走看看