All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.starmcc.qmframework.body.JsonPathArgumentResolver Maven / Gradle / Ivy

package com.starmcc.qmframework.body;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.starmcc.qmframework.config.TransmitConfiguration;
import com.starmcc.qmframework.exception.QmParamErrorException;
import com.starmcc.qmframework.exception.QmParamNullException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
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;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @author starmcc
 * @version 2018年9月10日 V1.0
 * 自定义解析json数据
 */
public class JsonPathArgumentResolver implements HandlerMethodArgumentResolver {

    private static final String JSONBODY_ATTRIBUTE = "JSON_REQUEST_BODY";

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

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

        String jsonBody = this.getRequestBody(webRequest);
        JSONObject jsonObject = JSON.parseObject(jsonBody);
        if (jsonObject == null) {
            throw new QmParamNullException(TransmitConfiguration.getRequestKey());
        }
        // 根据@qmBody注解value作为json解析的key
        QmBody qmBody = parameter.getParameterAnnotation(QmBody.class);
        // 注解的value是JSON的key
        String key = qmBody.key();
        Object value = null;
        // 如果@qmBody注解没有设置value,则取参数名FrameworkServlet作为json解析的key
        if (StringUtils.isNotEmpty(key)) {
            value = jsonObject.get(key);
        } else {
            // 注解为设置value则用参数名当做json的key
            key = parameter.getParameterName();
            value = jsonObject.get(key);
        }
        // 如果required = true 则不允许value == null
        if (value == null && qmBody.required()) {
            throw new QmParamNullException(key);
        } else if (value == null && qmBody.required() == false) {
            return value;
        }
        Class parameterType = parameter.getParameterType();
        // 通过注解的value或者参数名解析,能拿到value进行解析
        //基本类型
        if (parameterType.isPrimitive()) {
            return parsePrimitive(parameterType.getName(), value);
        }
        // 基本类型包装类
        if (isPackDataTypes(parameterType)) {
            return parseBasicTypeWrapper(parameterType, value);
            // 字符串类型
        } else if (parameterType == String.class) {
            if (StringUtils.isEmpty(value.toString()) && qmBody.required()) {
                throw new QmParamNullException(key);
            }
            return value.toString();
        }
        // 解析Date时间
        if (parameterType == Date.class) {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
                    .parse(value.toString());
        }
        // 如果是list则解析list
        if (parameterType.isAssignableFrom(List.class)) {
            Type genericType = parameter.getGenericParameterType();
            if (genericType instanceof ParameterizedType) {
                try {
                    ParameterizedType pt = (ParameterizedType) genericType;
                    //得到泛型里的class类型对象
                    Class genericClazz = (Class) pt.getActualTypeArguments()[0];
                    return JSON.parseArray(value.toString(), genericClazz);
                } catch (Exception e) {
                    try {
                        return JSON.parseArray(value.toString());
                    } catch (Exception e1) {
                        if (qmBody.required()) {
                            throw new QmParamErrorException(key);
                        }
                        return null;
                    }
                }
            }
            return JSON.parseArray(value.toString());
        }
        return JSON.parseObject(value.toString(), parameterType);
    }


    /**
     * 基本类型解析
     *
     * @param String parameterTypeName
     * @param Object value
     * @return Object
     */
    private Object parsePrimitive(String parameterTypeName, Object value) {
        final String booleanTypeName = "boolean";
        if (booleanTypeName.equals(parameterTypeName)) {
            return Boolean.valueOf(value.toString());
        }
        final String intTypeName = "int";
        if (intTypeName.equals(parameterTypeName)) {
            return Integer.valueOf(value.toString());
        }
        final String charTypeName = "char";
        if (charTypeName.equals(parameterTypeName)) {
            return value.toString().charAt(0);
        }
        final String shortTypeName = "short";
        if (shortTypeName.equals(parameterTypeName)) {
            return Short.valueOf(value.toString());
        }
        final String longTypeName = "long";
        if (longTypeName.equals(parameterTypeName)) {
            return Long.valueOf(value.toString());
        }
        final String floatTypeName = "float";
        if (floatTypeName.equals(parameterTypeName)) {
            return Float.valueOf(value.toString());
        }
        final String doubleTypeName = "double";
        if (doubleTypeName.equals(parameterTypeName)) {
            return Double.valueOf(value.toString());
        }
        final String byteTypeName = "byte";
        if (byteTypeName.equals(parameterTypeName)) {
            return Byte.valueOf(value.toString());
        }
        return null;
    }

    /**
     * 基本类型包装类型解析
     *
     * @param parameterType Class
     * @param value         Object
     * @return Object
     */
    private Object parseBasicTypeWrapper(Class parameterType, Object value) {
        if (Number.class.isAssignableFrom(parameterType)) {
            Number number = (Number) value;
            if (parameterType == Integer.class) {
                return number.intValue();
            } else if (parameterType == Short.class) {
                return number.shortValue();
            } else if (parameterType == Long.class) {
                return number.longValue();
            } else if (parameterType == Float.class) {
                return number.floatValue();
            } else if (parameterType == Double.class) {
                return number.doubleValue();
            } else if (parameterType == Byte.class) {
                return number.byteValue();
            }
        } else if (parameterType == Boolean.class) {
            return Boolean.valueOf(value.toString());
        } else if (parameterType == Character.class) {
            return value.toString().charAt(0);
        }
        return null;
    }

    /**
     * 是否为包装数据类型
     *
     * @param clazz class
     * @return boolean
     */
    private boolean isPackDataTypes(Class clazz) {
        Set classSet = new HashSet<>();
        classSet.add(Integer.class);
        classSet.add(Long.class);
        classSet.add(Short.class);
        classSet.add(Float.class);
        classSet.add(Double.class);
        classSet.add(Boolean.class);
        classSet.add(Byte.class);
        classSet.add(Character.class);
        return classSet.contains(clazz);
    }


    /**
     * 获取请求体JSON字符串
     *
     * @param webRequest NativeWebRequest
     * @return String
     */
    private String getRequestBody(NativeWebRequest webRequest) {
        HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
        // 有就直接获取
        String jsonBody = (String) webRequest.getAttribute(JSONBODY_ATTRIBUTE, NativeWebRequest.SCOPE_REQUEST);
        // 没有就从请求中读取
        if (jsonBody == null) {
            try {
                jsonBody = IOUtils.toString(servletRequest.getReader());
                webRequest.setAttribute(JSONBODY_ATTRIBUTE, jsonBody, NativeWebRequest.SCOPE_REQUEST);
            } catch (IOException e) {
                throw new QmParamErrorException(e);
            }
        }
        return jsonBody;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy