【问题标题】:java.lang.IllegalArgumentException: argument type mismatch while using Spring Custom Argument Resolverjava.lang.IllegalArgumentException:使用 Spring 自定义参数解析器时参数类型不匹配
【发布时间】:2021-11-20 08:57:28
【问题描述】:

我在使用带有 HandlerMethodArgumentResolver 的 Spring Argument 解析器时遇到 java.lang.IllegalArgumentException:参数类型不匹配。多次调试我的代码,但能够找到为什么会出现这个异常。如果有人可以帮助我,那就太好了。 这是我的代码。

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

配置类:

@Configuration
@EnableWebMvc
public class SpringWebMvcConfig implements WebMvcConfigurer {


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

}

CommonHeader 类:

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

扩展 CommonHeader 类的请求类:

@Getter
@Setter
public class GetDataRequest extends CommonHeader {

    private String name1;
    private String name2;
   
}

【问题讨论】:

  • 问题是什么?您的GetNotificationPrefrenceDataRequest 没有在该代码中使用,那么为什么要使用转换器?
  • 只是输入错误,如本示例代码。标头的某些字段对于我的项目的所有 API 都是通用的。所以我正在应用这个参数解析器代码来优化代码。
  • SpringArgumentResolver类中return语句后出现异常,return commonHeader;
  • 那么你认为CommonHeader 会自动变成GetDataRequest 吗?执行GetDataRequest req = (GetDataRequest) new CommonHeader();(即,将COmmonHeader 转换为GetDataRequest)也会在常规java 中导致ClassCastException。那么为什么会有所不同。需要从MethodParameter中判断类型,动态构造实例。
  • 但是 spring webflux 项目的相同逻辑正在使用少量更改。 github.com/martinnemec3/spring-argument-resolver-demo/blob/main/…

标签: java spring-boot spring-mvc illegalargumentexception


【解决方案1】:

您的SpringArgumentResolver 错误。 GetDataRequestCommonHeader,但 CommonHeader 不是 GetDataRequest。您的 SpringArgumentResolver always 返回一个 CommonDataHeader 不能转换/转换为 GetDataRequest 因此错误。

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

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

您应该在SpringArgumentResolver 中做的是动态确定类并实例化它,将其转换为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

【讨论】:

  • 此代码在执行 CommonHeader commonHeader = (CommonHeader) BeanUtils.instantiateClass(parameter.getParameterType());这是正确的方式吗?
  • 为什么不呢。你需要类型,你也可以使用BeanUtils.instantiateClass(parameter.getParameterType(), CommonHeader.class); 这样你就不需要演员了。
  • 好的。但没有强制转换,它给出:“不存在类型变量的实例,因此捕获 ? 符合 CommonHeader”
  • 那是由于使用了泛型。因此需要演员阵容或其他方法。我会更新答案。
猜你喜欢
  • 2017-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
相关资源
最近更新 更多