【SpringMVC(七)】使用ArgumentResolver 接受 json 参数
原创
©著作权归作者所有:来自51CTO博客作者wx636dc453ed367的原创作品,请联系作者获取转载授权,否则将追究法律责任
这里介绍下如何使用一个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请求:
日志:
{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;