SpringBoot Controller 中使用多个@RequestBody

时间:2025-04-01 08:11:42
除spring的Jar包外涉及的主要Maven依赖:
<dependency>
            <groupId>commons-lang</groupId>
            <artifactId>commons-lang</artifactId>
            <version>2.4</version>
        </dependency>
 
        <dependency>
            <groupId></groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.35</version>
        </dependency>
 
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

其中fastjson用来解析json对象,commons-lang用来字符串判空(也可以自己手写),commons-io用来读取请求封装为字符串类型(也可以自己封装)。
1、重写方法参数解析器

import ;
import ;
import ;
import .;
import ;
import ;
import ;
import ;
import ;

import ;
import ;
import ;
import ;
import ;

/**
 * MultiRequestBody解析器
 * 解决的问题:
 * 1、单个字符串等包装类型都要写一个对象才可以用@RequestBody接收;
 * 2、多个对象需要封装到一个对象里才可以用@RequestBody接收。
 * 主要优势:
 * 1、支持通过注解的value指定JSON的key来解析对象。
 * 2、支持通过注解无value,直接根据参数名来解析对象
 * 3、支持基本类型的注入
 * 4、支持GET和其他请求方式注入
 * 5、支持通过注解无value且参数名不匹配JSON串key时,根据属性解析对象。
 * 6、支持多余属性(不解析、不报错)、支持参数“共用”(不指定value时,参数名不为JSON串的key)
 * 7、支持当value和属性名找不到匹配的key时,对象是否匹配所有属性。
 *
 * @date 2018/08/27
 */
public class MultiRequestBodyArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String JSONBODY_ATTRIBUTE = "JSON_REQUEST_BODY";

    /**
     * 设置支持的方法参数类型
     *
     * @param parameter 方法参数
     * @return 支持的类型
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        // 支持带@MultiRequestBody注解的参数
        return ();
    }

    /**
     * 参数解析,利用fastjson
     * 注意:非基本类型返回null会报空指针异常,要通过反射或者JSON工具类创建一个空对象
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        String jsonBody = getRequestBody(webRequest);

        JSONObject jsonObject = (jsonBody);
        // 根据@MultiRequestBody注解value作为json解析的key
        MultiRequestBody parameterAnnotation = ();
        //注解的value是JSON的key
        String key = ();
        Object value;
        // 如果@MultiRequestBody注解没有设置value,则取参数名FrameworkServlet作为json解析的key
        if ((key)) {
            value = (key);
            // 如果设置了value但是解析不到,报错
            if (value == null && ()) {
                throw new IllegalArgumentException(("required param %s is not present", key));
            }
        } else {
            // 注解为设置value则用参数名当做json的key
            key = ();
            value = (key);
        }

        // 获取的注解后的类型 Long
        Class<?> parameterType = ();
        // 通过注解的value或者参数名解析,能拿到value进行解析
        if (value != null) {
            //基本类型
            if (()) {
                return parsePrimitive((), value);
            }
            // 基本类型包装类
            if (isBasicDataTypes(parameterType)) {
                return parseBasicTypeWrapper(parameterType, value);
                // 字符串类型
            } else if (parameterType == ) {
                return ();
            }
            // 其他复杂对象
            return ((), parameterType);
        }

        // 解析不到则将整个json串解析为当前参数类型
        if (isBasicDataTypes(parameterType)) {
            if (()) {
                throw new IllegalArgumentException(("required param %s is not present", key));
            } else {
                return null;
            }
        }

        Object result = ();
        // 非基本类型,不允许解析所有字段,返回null
        if (!()) {
            // 如果是必传参数抛异常
            if (()) {
                throw new IllegalArgumentException(("required param %s is not present", key));
            }
            // 否则返回空对象
            return result;
        }
        // 非基本类型,允许解析,将外层属性解析
        result = ((), parameterType);
        // 如果非必要参数直接返回,否则如果没有一个属性有值则报错
        if (!()) {
            return result;
        } else {
            boolean haveValue = false;
            Field[] declaredFields = ();
            for (Field field : declaredFields) {
                (true);
                if ((result) != null) {
                    haveValue = true;
                    break;
                }
            }
            if (!haveValue) {
                throw new IllegalArgumentException(("required param %s is not present", key));
            }
            return result;
        }
    }

    /**
     * 基本类型解析
     */
    private Object parsePrimitive(String parameterTypeName, Object value) {
        final String booleanTypeName = "boolean";
        if ((parameterTypeName)) {
            return (());
        }
        final String intTypeName = "int";
        if ((parameterTypeName)) {
            return (());
        }
        final String charTypeName = "char";
        if ((parameterTypeName)) {
            return ().charAt(0);
        }
        final String shortTypeName = "short";
        if ((parameterTypeName)) {
            return (());
        }
        final String longTypeName = "long";
        if ((parameterTypeName)) {
            return (());
        }
        final String floatTypeName = "float";
        if ((parameterTypeName)) {
            return (());
        }
        final String doubleTypeName = "double";
        if ((parameterTypeName)) {
            return (());
        }
        final String byteTypeName = "byte";
        if ((parameterTypeName)) {
            return (());
        }
        return null;
    }

    /**
     * 基本类型包装类解析
     */
    private Object parseBasicTypeWrapper(Class<?> parameterType, Object value) {
        if ((parameterType)) {
            Number number = (Number) value;
            if (parameterType == ) {
                return ();
            } else if (parameterType == ) {
                return ();
            } else if (parameterType == ) {
                return ();
            } else if (parameterType == ) {
                return ();
            } else if (parameterType == ) {
                return ();
            } else if (parameterType == ) {
                return ();
            }
        } else if (parameterType == ) {
            return ();
        } else if (parameterType == ) {
            return ().charAt(0);
        }
        return null;
    }

    /**
     * 判断是否为基本数据类型包装类
     */
    private boolean isBasicDataTypes(Class clazz) {
        Set<Class> classSet = new HashSet<>();
        ();
        ();
        ();
        ();
        ();
        ();
        ();
        ();
        return (clazz);
    }

    /**
     * 获取请求体JSON字符串
     */
    private String getRequestBody(NativeWebRequest webRequest) {
        HttpServletRequest servletRequest = ();

        // 有就直接获取
        String jsonBody = (String) (JSONBODY_ATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
        // 没有就从请求中读取
        if (jsonBody == null) {
            try {
                jsonBody = (());
                (JSONBODY_ATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return jsonBody;
    }
}
2、编写解析的方法注解:

import ;
import ;
import ;
import ;

/**
 * Controller中方法接收多个JSON对象
 * @date 2018/08/27
 */
@Target()
@Retention()
public @interface MultiRequestBody {
    /**
     * 是否必须出现的参数
     */
    boolean required() default true;

    /**
     * 当value的值或者参数名不匹配时,是否允许解析最外层属性到该对象
     */
    boolean parseAllFields() default true;

    /**
     * 解析时用到的JSON的key
     */
    String value() default "";
}
3、在配置Bean中注入
特别注意: 如果加入本配置导致页面访问404 可以去掉 @EnableWebMvc注解


import ;
import ;
import ;
import ;
import ;
import ;

import ;
import ;

/**
 * Web Config Demo
 * @date 2018/08/27
 */
@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {
    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        // 添加MultiRequestBody参数解析器
        (new MultiRequestBodyArgumentResolver());
    }

    @Bean
    public HttpMessageConverter<String> responseBodyConverter() {
        // 解决中文乱码问题
        return new StringHttpMessageConverter(("UTF-8"));
    }

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        (converters);
        (responseBodyConverter());
    }
}
使用方法:

import ;
import ;
import ;
import ;
import ;
import ;

/**
 * Controller Demo
 * @date 2018/08/27
 */
@Controller
@RequestMapping("/xhr/test")
public class DemoController {



    @RequestMapping("/testStr")
    @ResponseBody
    public String multiRequestBodyDemo1(@MultiRequestBody String test1,@MultiRequestBody  String test2) {

        (test1 +"-->" + test2);
        return "";
    }

    @RequestMapping("/testChar")
    @ResponseBody
    public String multiRequestBodyDemo1(@MultiRequestBody char id) {

        (id);
        return "";
    }
    @RequestMapping("/demo")
    @ResponseBody
    public String multiRequestBodyDemo1(@MultiRequestBody Dog dog, @MultiRequestBody User user) {
        (() + ());
        return () + ";" + ();
    }


    @RequestMapping("/demo2")
    @ResponseBody
    public String multiRequestBodyDemo2(@MultiRequestBody("dog") Dog dog, @MultiRequestBody User user) {
        (() + ());
        return () + ";" + ();
    }

    @RequestMapping("/demo3")
    @ResponseBody
    public String multiRequestBodyDemo3(@MultiRequestBody("dog") Dog dog, @MultiRequestBody("user") User user) {
        (() + ());
        return () + ";" + ();
    }

    @RequestMapping("/demo4")
    @ResponseBody
    public String multiRequestBodyDemo4(@MultiRequestBody("dog") Dog dog, @MultiRequestBody Integer age) {
        (() + ());
        return () + ";age属性为:"+();
    }


    @RequestMapping("/demo5")
    @ResponseBody
    public String multiRequestBodyDemo5(@MultiRequestBody("color") String color, @MultiRequestBody("age") Integer age) {
        return "color="+color + "; age=" + age;
    }

    @RequestMapping("/demo6")
    @ResponseBody
    public String multiRequestBodyDemo6(@MultiRequestBody("dog") Dog dog, @MultiRequestBody Integer age) {
        (() + ());
        return () + ";age属性为:"+();
    }


    @RequestMapping("/demo7")
    @ResponseBody
    public String multiRequestBodyDemo7(@MultiRequestBody(required = false) Dog dog, @MultiRequestBody("age") Integer age) {
        return "dog="+dog + "; age=" + age;
    }


    @RequestMapping("/demo10")
    @ResponseBody
    public String multiRequestBodyDemo10( @MultiRequestBody(parseAllFields = false,required = false) Dog dog) {
        return ();
    }
    @RequestMapping("/demo99")
    @ResponseBody
    public String multiRequestBodyDemo99( @MultiRequestBody(parseAllFields = false,required = false) Character demo) {
        return ();
    }
}
两个实体:


/**
 * @date 2018/08/27
 */
public class Dog {

    private String name;

    private String color;


    public String getName() {
        return name;
    }

    public void setName(String name) {
         = name;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
         = color;
    }

    @Override
    public String toString() {
        return "Dog{" +
                "name='" + name + '\'' +
                ", color='" + color + '\'' +
                '}';
    }
}



/**
 * @date 2018/08/27
 */
public class User {

    private String name;

    private Integer age;

    public String getName() {
        return name;
    }

    public void setName(String name) {
         = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
         = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}


本文转载至:

/w605283073/article/details/82119284