【问题标题】:Spring 4 Exception Handling : No suitable resolver for argumentSpring 4 异常处理:没有合适的参数解析器
【发布时间】:2019-05-16 07:45:03
【问题描述】:

问题陈述

Spring 3 迁移到Spring 4 会在异常处理流程中引发一些异常。 Exception 在org.springframework.web.method.support.InvocableHandlerMethod 类中显示No suitable resolver for argument

所以每当发生异常时Spring 试图找到它得到的异常处理程序 但是当它尝试填充方法参数或异常处理程序时,它会抛出以下异常

调用@ExceptionHandler方法失败:

  public org.springframework.web.servlet.ModelAndView  
       HelloController.handleCustomException(CustomGenericException, javax.servlet.http.HttpServletRequest, org.springframework.web.servlet.ModelAndView)

  java.lang.IllegalStateException: 
     No suitable resolver for argument [2] 
             [type=org.springframework.web.servlet.ModelAndView]

HandlerMethod详情:

Controller [HelloController]
Method [public org.springframework.web.servlet.ModelAndView  
        HelloController.handleCustomException(CustomGenericException,
            javax.servlet.http.HttpServletRequest,org.springframework.web.servlet.ModelAndView)]
        at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(
                     InvocableHandlerMethod.java:169)

它基本上是为@CRequestParam("p") String p变量而来的

代码

控制器

@RequestMapping(method = RequestMethod.GET, value="/exception2")
    public String getException1(ModelMap model, @CRequestParam("p") String p) {

        System.out.println("Exception 2 "+ p);
        throw new CustomGenericException("1","2");
    }

异常处理

@ExceptionHandler(CustomGenericException.class)
    public ModelAndView handleCustomException(CustomGenericException ex, 
            HttpServletRequest request, @CRequestParam("p") String p) {

            ModelAndView model = new ModelAndView("error/generic_error");
            model.addObject("exception", ex);
            System.out.println("CustomGenericException  ");
            return model;
    }

注释

@Target( { ElementType.PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface CRequestParam {
    String value() default "";
}

参数解析器

public class CRequestparamResolver implements HandlerMethodArgumentResolver {


    @Override
        public boolean supportsParameter(MethodParameter methodParameter) {
          CRequestParam requestParamAnnotation = 
          methodParameter.getParameterAnnotation(CRequestParam.class);
        if(requestParamAnnotation==null){
        return false;
        }
        return true;
        }

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

    CRequestParam requestParamAnnotation = methodParameter .getParameterAnnotation(CRequestParam.class);

    if (requestParamAnnotation != null) {
        String requestParamName = requestParamAnnotation.value();
        if (StringUtils.hasText(requestParamName)) {
        return webRequest.getParameter(requestParamName);
        }
    }
    return null;
  }

XML 配置

<bean
        class="com.mkyong.common.resolver.AnnotationMethodHandlerAdapterConfigurer"
        init-method="init">
        <property name="customArgumentResolvers">
            <list>
                <bean class="com.mkyong.common.resolver.CRequestparamResolver" />
            </list>
        </property>
    </bean>

    <bean 
 class="org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver">
        <property name="customArgumentResolvers">
            <list>
                <bean class="com.mkyong.common.resolver.CRequestparamResolver" />
            </list>
        </property>
    </bean>

源代码

https://github.com/santoshjoshi/SpringMVC4

【问题讨论】:

  • 我认为你的意思不是@CRequestParam,而是@RequestParam
  • @geo 及其自定义请求参数CRequestParam,我们有CRequestparamResolver 解析器。
  • @geo 并且整个源代码现已在https://github.com/santoshjoshi/SpringMVC4签入
  • 你能发布一个更完整的堆栈跟踪吗?
  • AFAIK RequestMappingHandlerAdapter 不处理异常,因此无法使用它的参数解析器。看看ExceptionHandlerExceptionResolver.setArgumentResolvers()。我自己从未使用过它,但它看起来很有希望。

标签: java spring spring-mvc spring-4


【解决方案1】:

通过在请求本身中传递自定义参数解决了问题。

代码如下:

控制器

@RequestMapping(method = RequestMethod.GET, value = "/exception2")
public String getException1(ModelMap model, @CRequestParam("p") String p, HttpServletRequest request) {

  System.out.println("Exception 2 " + p);
  request.setAttribute("p", p);
  throw new CustomGenericException("1", "2");
}

异常处理程序

@ExceptionHandler(CustomGenericException.class)
public ModelAndView handleCustomException(CustomGenericException ex, HttpServletRequest request) {

  ModelAndView model2 = new ModelAndView("error/generic_error");
  model2.addObject("exception", ex);
  System.out.println(request.getAttribute("p"));
  System.out.println("CustomGenericException  ");
  return model2;

}

完整的源代码可在git获得

【讨论】:

    【解决方案2】:

    通过提供WebApplicationInitializer的实现解决了这个问题

    public class SpringDispatcherConfig implements WebApplicationInitializer {
    
    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext Contianer =   new AnnotationConfigWebApplicationContext();
        Contianer.register(SpringConfig.class);
        Contianer.setServletContext(servletContext);
        DispatcherServlet dispatcherServlet = new DispatcherServlet(Contianer);
        dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
        Dynamic servlet = servletContext.addServlet("spring",dispatcherServlet);
        servlet.addMapping("/");
        servlet.setLoadOnStartup(1);
    
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-10-31
      • 1970-01-01
      • 1970-01-01
      • 2021-04-13
      • 1970-01-01
      • 1970-01-01
      • 2011-08-15
      相关资源
      最近更新 更多