spring-cloud-netflix icon indicating copy to clipboard operation
spring-cloud-netflix copied to clipboard

how to use feign multi pojo paramters?

Open HongKing opened this issue 6 years ago • 1 comments

I want use feign and springmvc controller like this:

@RequestMapping(value = "/save")
String saveUser(@RequestJson(value = "user") User user, @RequestJson(value = "group") Group group);

feign build this param to request body like this:

{
  'user':{'name':......},
  'group':{'name':.....}
}

in springmvc controller we can write a resolver class to parse this request body, but I don't known how to build this param to request body. I parse this request body code as follows:

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface RequestJson {
    
    /**
     * bind paramter name
     */
    String value() default "";
    
    boolean required() default true;
}
public class RequestJsonMethodProcessor implements HandlerMethodArgumentResolver {

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

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
            NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        
        HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
        JSONObject json = (JSONObject) request.getSession().getAttribute("TEMP_JSON_BODY");
        if (json == null) {
            json = getJsonFromBody(request);
            request.getSession().setAttribute("TEMP_JSON_BODY", json); // cache request body content to session
            // in global interceptor.preHandle() session.removeAttribute("TEMP_JSON_BODY")
        }
        mavContainer.setRequestHandled(true);
        
        parameter = parameter.nestedIfOptional();
        Type targetType = parameter.getNestedGenericParameterType();
        Class<?> targetClass = (targetType instanceof Class ? (Class<?>) targetType : null);
        RequestJson aa = parameter.getParameterAnnotation(RequestJson.class);
        JSONObject a = json.getJSONObject(aa.value());

        return JSONObject.toBean(a, targetClass);
    }
    
    private JSONObject getJsonFromBody(HttpServletRequest request) {
        StringBuffer sb = new StringBuffer();
        String line = null;
        try {
            BufferedReader reader = request.getReader();
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return JSONObject.fromObject(sb.toString());
    }
    
}
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
      @Override
      public void addArgumentResolvers(List<HandlerMethodArgumentResolver> argumentResolvers) {
          argumentResolvers.add(new RequestJsonMethodProcessor());
      }
}

HongKing avatar Jan 11 '18 06:01 HongKing

This isn't spring mvc, it's not currently possible.

spencergibb avatar Jan 17 '18 23:01 spencergibb