Post提交JSON数据自动转为实体对象

1,396 阅读2分钟

介绍

在SpringBoot中,post提交的JSON数据时候,自动将参数信息转为实体对象,并且校验字段信息

实现

POM文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.silly.demo</groupId>
    <artifactId>spring-boot-demo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <description>spring boot 样例代码</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.2</version>
    </parent>


    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <!--打包或编译跳过单元测试-->
        <skipTests>true</skipTests>
    </properties>


    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>


        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.20</version>
        </dependency>

        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.75</version>
        </dependency>
        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>2.0.1.Final</version>
        </dependency>

        <dependency>
            <groupId>org.hibernate.validator</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>6.0.7.Final</version>
        </dependency>

    </dependencies>

</project>

JSONParam 注解

定义参数的key值

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author :silly
 * @description:JSON参数
 * @date :2021/7/15 16:23
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface JSONParam {
    /**
     * 表单提交的json字符串字段名
     */
    String value();
}

JSONMethodArgumentResolver 方法转换器

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.silly.demo.utils.ValidatorUtils;
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 java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author :silly
 * @description:json方法转换器
 * @date :2021/7/15 16:24
 */
public class JSONMethodArgumentResolver implements HandlerMethodArgumentResolver {


    /**
     * 判断是否支持
     *
     * @param parameter
     * @return
     */
    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(JSONParam.class);
    }

    /**
     * 参数转换
     *
     * @param parameter
     * @param container
     * @param request
     * @param factory
     * @return
     */
    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer container,
                                  NativeWebRequest request, WebDataBinderFactory factory) {
        //获取方法体上的的JSONParam注解
        JSONParam paramAnnotation = parameter.getParameterAnnotation(JSONParam.class);
        //获取注解上带的参数名
        String paramName = paramAnnotation.value();
        //获取提交的参数值
        String paramValue = request.getParameter(paramName);
        // 开始处理空格
        Map<String, Object> map = (Map<String, Object>) JSONObject.parse(paramValue);
        Set<Map.Entry<String, Object>> entrySet = map.entrySet();
        Map<String, Object> removeSpaceMap = new HashMap<>();
        for (Map.Entry<String, Object> entry : entrySet) {
            if (entry.getValue() instanceof String) {
                removeSpaceMap.put(entry.getKey(), ((String) entry.getValue()).trim());
            } else {
                removeSpaceMap.put(entry.getKey(), entry.getValue());
            }
        }
        //转换为实体对象
        Type type = parameter.getGenericParameterType();
        Object object = JSON.parseObject(JSON.toJSONString(removeSpaceMap), type);
        if (object != null) {
            //调用validator 校验参数
            ValidatorUtils.validate(object);
        }
        return object;
    }
}

ValidatorUtils参数校验工具类

import org.hibernate.validator.HibernateValidator;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import java.util.Set;


/**
 * @author :silly
 * @description:校验工具类
 * @date :2021/7/15 17:33
 */
public class ValidatorUtils {

    private ValidatorUtils() {
    }


    private static Validator validator;

    /**
     * 获取实例信息
     *
     * @return
     */
    public static Validator getInstance() {
        if (validator == null) {
            synchronized (ValidatorUtils.class) {
                if (validator == null) {
                    validator = Validation.byProvider(HibernateValidator.class).
                            configure().failFast(false).buildValidatorFactory().getValidator();
                }
            }
        }
        return validator;
    }

    /**
     * 校验
     */
    public static <T> void validate(T object) {
        StringBuilder sb = new StringBuilder();
        Set<ConstraintViolation<T>> constraintViolations = getInstance().validate(object);
        if (constraintViolations != null && constraintViolations.size() > 0) {
            for (ConstraintViolation<T> constraintViolation : constraintViolations) {
                sb.append(constraintViolation.getMessage());
            }
            throw new RuntimeException(sb.toString());
        }

    }

}

WebConfiguration 将解析器加入到框架中

import com.silly.demo.web.resolver.method.JSONMethodArgumentResolver;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

/**
 * @author :silly
 * @description:web 配置
 * @date :2021/4/14 11:08
 */
@Configuration
@AllArgsConstructor(onConstructor = @_(@Autowired))
public class WebConfiguration implements WebMvcConfigurer {


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new JSONMethodArgumentResolver());
    }
}

案例应用

User 用户实体

@Getter
@Setter
public class User {
    @NotEmpty(message = "用户名不能为空")
    private String userName;
    @NotEmpty(message = "密码不能为空")
    private String passWord;
    @NotNull(message = "爱好不能为空")
    private List<String> hobby;
}

UserController接口使用

@RestController
@RequestMapping(value = "/user")
public class UserController {
    
    /**
     * 用户信息
     *
     * @param user
     * @return
     */
    @RequestMapping(value = "/add")
    public RestResponse add(@JSONParam("user") User user) {
        return RestResponse.success("成功", user);
    }
}

结果展示

执行失败

  • 请求参数 在这里插入图片描述

  • 执行结果 在这里插入图片描述

执行成功

  • 请求参数 在这里插入图片描述

  • 执行结果

{
    "success": true,
    "message": "成功",
    "data": {
        "userName": "张三",
        "passWord": "111111",
        "hobby": [
            "乒乓球",
            "跳舞",
            "写代码"
        ]
    }
}

在这里插入图片描述