java.lang.IllegalArgumentException:使用 Spring 自定义参数解析器时参数类型不匹配

java.lang.IllegalArgumentException: argument type mismatch while using Spring Custom Argument Resolver

我得到 java.lang.IllegalArgumentException:使用 Spring 参数解析器和 HandlerMethodArgumentResolver 时参数类型不匹配。多次调试我的代码,但能够找到出现此异常的原因。如果有人可以帮助我,那就太好了。 这是我的代码。

public final class SpringArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return CommonHeader.class.isAssignableFrom(parameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        CommonHeader commonHeader = new CommonHeader();

        String user_id = webRequest.getHeader("UserID");
       
        commonHeader.setUser_id(user_id);

            return commonHeader;
    }

配置class:

@Configuration
@EnableWebMvc
public class SpringWebMvcConfig implements WebMvcConfigurer {


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new SpringArgumentResolver());
    }

}

CommonHeader class:

public class CommonHeader {

    private String user_id;
    private String ip_address;
    private String request_id;

    public CommonHeader(String user_id) {
            this.user_id = user_id;
    }
    public CommonHeader(){}
 
    public String getUser_id() {
        return user_id;
    }

    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }
}

控制器:

@GetMapping("user_data")
public DeferredResult<ResponseEntity<JsonNode>> getUserPreferenceData(GetDataRequest getDataRequest) {
            DeferredResult<ResponseEntity<JsonNode>> deferredResult = new DeferredResult<>();
         // some logic 
        //  some logic
       return deferredResult;
    }

请求 class 扩展 CommonHeader class:

@Getter
@Setter
public class GetDataRequest extends CommonHeader {

    private String name1;
    private String name2;
   
}

你的SpringArgumentResolver是错误的。 GetDataRequestCommonHeader,但 CommonHeader 不是 GetDataRequest。你的 SpringArgumentResolver always return 是一个 CommonDataHeader 不能 cast/turned 变成 GetDataRequest 因此错误。

CommonHeader header = new CommonHeader();
GetDataRequest request = (GetDataRequest) header;

基本上就是您所期望的自动发生的情况。现在这在常规 java 中不起作用(导致 ClassCastException),为什么它在 Spring 中起作用? Spring 检查生成的对象是否可以分配给该方法参数,在这种情况下不能,因为 GetDataRequest.isAssignableFrom(CommonHeader.class); 将 return false (尽管相反是正确的!).

您应该在 SpringArgumentResolver 中做的是动态确定 class 并实例化它,将其转换为 CommonHeader 并设置字段。

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

    CommonHeader commonHeader = BeanUtils.instantiateClass(parameter.getParameterType(), CommonHeader.class);
    String user_id = webRequest.getHeader("UserID");
    commonHeader.setUser_id(user_id);
    return commonHeader;
}

这将使用方法参数的实际类型来创建实例,从而消除 ClassCastException,对于 Spring,IllegalArgumentException