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

32 篇文章 15 订阅

这里介绍下如何使用一个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; 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值