这里介绍下如何使用一个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<String, Object> 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配置:

<mvc:annotation-driven>
<mvc:argument-resolvers>
<bean class="com.liyao.pre.JsonParamResolver"/>
</mvc:argument-resolvers>
</mvc:annotation-driven>

最后是controller:

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

使用postman发一个json请求:

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

日志:

{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;