【SpringMVC(七)】使用ArgumentResolver 接受 json 参数

这里介绍下如何使用一个argumentResolver预处理httpServlet里的body,并且提取出json参数,传递给controller。

先定义一个标记注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface JsonParams {
}

再定义一个处理该标记的resolver:

import com.fasterxml.jackson.databind.ObjectMapper;
import com.liyao.annotation.JsonParams;
import org.apache.commons.io.IOUtils;
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.InputStream;
import java.util.Map;

public class JsonParamResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return parameter.hasParameterAnnotation(JsonParams.class);
    }

    @Override
    public Object resolveArgument(MethodParameter parameter,
                                  ModelAndViewContainer mavContainer,
                                  NativeWebRequest webRequest,
                                  WebDataBinderFactory binderFactory) throws Exception {
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        if ("application/json".equals(request.getContentType())) {
            InputStream inputStream = request.getInputStream();
            byte[] bytes = IOUtils.toByteArray(inputStream);
            String jsonStr = new String(bytes);
            ObjectMapper mapper = new ObjectMapper();
            Map data = mapper.readValue(jsonStr, Map.class);
            System.out.println(data);

            String paramName = parameter.getParameterName();
            return data.get(paramName);
        }
        return null;
    }
}

简单介绍下,解析逻辑在resolveArgument函数内部。

首先判定http请求body类型是否是json类的。

然后使用apache io库函数读取request中的body流。

再使用jackson解析json,转换为一个map。

最后根据参数名从map中取值。

整个处理过程比较简单,不是特别健壮。

 

看下spring配置:

    
        
            
        
    

最后是controller:

 @RequestMapping("/helloJson")
    public String s(@JsonParams long userId){
        System.out.println(userId);
        return "success";
    }

使用postman发一个json请求:

【SpringMVC(七)】使用ArgumentResolver 接受 json 参数_第1张图片

日志:

{userId=10086}
10086

说明解析成功。

 

注意:

HttpServletRequest的getInputStream方法可以返回请求的body:

    /**
     * Retrieves the body of the request as binary data using
     * a {@link ServletInputStream}.  Either this method or 
     * {@link #getReader} may be called to read the body, not both.
     *
     * @return			a {@link ServletInputStream} object containing
     * 				the body of the request
     *
     * @exception IllegalStateException  if the {@link #getReader} method
     * 					 has already been called for this request
     *
     * @exception IOException    	if an input or output exception occurred
     *
     */

    public ServletInputStream getInputStream() throws IOException; 

 

你可能感兴趣的:(java,spring)