Springmvc form-data body 解析为对象

1背景

本文只适用与Content-type 为form-data 媒体类型。

springmvc 是默认支持将form-data 传过来的表单数据的,但是有一个限制,那即是表单的key值要和对象的属性值是一样的,然而生产环境中,一般前端使用的参数都是下划线的,而我们对象里的key是驼峰的,这样就设置不到对应的值了。

这里有俩种方法:

  1. 一种为将对象里的key全部改为下划线(不推荐);
  2. 自定义参数解析。

这里我们使用第二种方法。 

2 实现

首先我们先定义一个class 工具类。

public class ClassUtil {

    private static Logger log = LoggerFactory.getLogger(ClassUtil.class);

    //将字符串转化为对应的类型,数组类型不支持
    public static Object getFieldValue(Field field, String origin) {
        Class<?> fileType = field.getType();
        if (fileType == String.class) {
            return origin;
        }

        if (fileType.isArray()) {
            throw new IllegalArgumentException("array type is not support");
        }
        if (fileType == int.class || fileType == Integer.class) {
            return Integer.parseInt(origin);
        }

        if (fileType == long.class || fileType == Long.class) {
            return Long.parseLong(origin);
        }

        if (fileType == byte.class || fileType == Byte.class) {
            return Byte.parseByte(origin);
        }

        if (fileType == short.class || fileType == Short.class) {
            return Short.parseShort(origin);
        }

        if (fileType == char.class || fileType == Character.class) {
            return origin.charAt(0);
        }

        if (fileType == float.class || fileType == Float.class) {
            return Float.parseFloat(origin);
        }

        if (fileType == double.class || fileType == Double.class) {
            return Double.parseDouble(origin);
        }

        if (fileType == boolean.class || fileType == Boolean.class) {
            return Boolean.parseBoolean(origin);
        }

        return JSONObject.parseObject(origin, fileType);
    }
    //为对应的属性设置,调用set方法
    public static void setFieldValue(Class clazz, Field field, Object instance, Object o) {
        if (clazz == null || field == null || o == null) {
            return;
        }
        String name = field.getName();
        Class<?> fieldType = field.getType();
        //获取set方法名称
        {
            String prefix = "set";
            name = prefix + name.substring(0, 1).toUpperCase() + name.substring(1);
        }

        try {
            Method setMethod = clazz.getDeclaredMethod(name, fieldType);
            setMethod.invoke(instance, o);
        } catch (NoSuchMethodException e) {
            log.error("no such method", e);
        } catch (IllegalAccessException e) {
            log.error("", e);
        } catch (InvocationTargetException e) {
            log.error("", e);
        }
}

然后我们创建一个注解,表明这个参数使用我们的自定义解析。

/**
 * 用于spring mvc 表单接受参数
 * 支持form data 转化对象, 使用fastjson 转化 , 目前只支持基本数据类型,属性类型为对象类型不支持
 */
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface FormDataJsonBody {
}

接下来我们实现自定义解析器,为了实现简单,我们其中使用了一些fastjson 的方法,所以需要依赖fastjson

public class FormDataJsonResolver implements HandlerMethodArgumentResolver {
    @Override
    public boolean supportsParameter(MethodParameter methodParameter) {
        FormDataJsonBody annotation = methodParameter.getParameterAnnotation(FormDataJsonBody.class);
        return annotation != null;
    }

    @Override
    public Object resolveArgument(MethodParameter methodParameter, ModelAndViewContainer modelAndViewContainer, NativeWebRequest request, WebDataBinderFactory webDataBinderFactory) throws Exception {
        Class<?> clazz = methodParameter.getParameterType();
        Object instance = clazz.newInstance();
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String keyName = "" ;
            {
                JSONField jsonAnnotation = field.getAnnotation(JSONField.class);
                if(jsonAnnotation == null){
                    keyName = field.getName() ;
                }else{
                    keyName = jsonAnnotation.name();
                }
            }
            String[] values = request.getParameterMap().get(keyName);
            //数组不进行处理
            if(values == null || values.length<1 || values.length>1){
                continue;
            }
            String dataStr = values[0];
            Object fieldValue = ClassUtil.getFieldValue(field, dataStr);
            ClassUtil.setFieldValue(clazz,field,instance,fieldValue);
        }
        return instance;
    }

然后我们需要将自定义解析起加入到Spring mvc 的解析器里,

@Configuration
@Slf4j
public class WebMvcConfigurer extends WebMvcConfigurationSupport {


    @Override
    protected void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
        argumentResolvers.add(new FormDataJsonResolver());
        super.addArgumentResolvers(argumentResolvers);
    }
}

3 测试

@PostMapping("/save_or_update")
public Map<String, Object> saveOrUpdate(@FormDataJsonBody DemoParam param) {
       
    return new HashMap();

}

public static class DemoParam{

    @JSONField(name = "start_time")
    private Long startTime;

    @JSONField(name = "type")
    private Integer sendType;

    @JSONField(name = "id")
    private Long id ;

    @JSONField(name = "details")
    private String details;
}
    

测试结果与我们预期的一样

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值