• SpringMVC处理跨域请求时的一个注意事项


        由于公司对SpingMVC框架里面的东西进行了扩展,在配置SpringMVC时没有使用<mvc:annotation-driven>这个标签。而且是自己手动来配置HandlerMappingHandlerAdapter。在处理跨域请求时,就抛No adapter for handler 异常了。记录下该异常的解决过程,方便后续查询。

    一、异常信息

        具体的异常信息如下:
    threw exception [No adapter for handler [org.springframework.web.servlet.handler.AbstractHandlerMapping$PreFlightHandler@edcb4b4]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler] with root cause
    javax.servlet.ServletException: No adapter for handler [org.springframework.web.servlet.handler.AbstractHandlerMapping$PreFlightHandler@edcb4b4]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
    	at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1202)
    	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:947)
    	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    	at org.springframework.web.servlet.FrameworkServlet.doOptions(FrameworkServlet.java:908)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:657)
    	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    	at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    x
     
    1
    threw exception [No adapter for handler [org.springframework.web.servlet.handler.AbstractHandlerMapping$PreFlightHandler@edcb4b4]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler] with root cause
    2
    javax.servlet.ServletException: No adapter for handler [org.springframework.web.servlet.handler.AbstractHandlerMapping$PreFlightHandler@edcb4b4]: The DispatcherServlet configuration needs to include a HandlerAdapter that supports this handler
    3
        at org.springframework.web.servlet.DispatcherServlet.getHandlerAdapter(DispatcherServlet.java:1202)
    4
        at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:947)
    5
        at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:901)
    6
        at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
    7
        at org.springframework.web.servlet.FrameworkServlet.doOptions(FrameworkServlet.java:908)
    8
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:657)
    9
        at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
    10
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)

    二、问题的解决

    (1)异常的分析
        分析上面的异常信息,发现是在doOptions没找到合适的HandlerAdapter。跨域请求时是会发送2个请求的,第一个是就是options类型的请求。所以这里的问题就是在处理options请求时。
        再看了下代码中配置的HandlerAdapter,配置代码如下图
        注册的HandlerAdapter实例为 RequestMappingHandlerAdapter于是我怀疑是这个RequestMappingHandlerAdapter不支持options类型的请求。
    (2)验证自己的想法
        带着怀疑的想法,把xml配置中手动配置的HandlerAdapter给去掉了,然后加上<mvc:annotation-driven>这个标签。再运行项目,发现跨域请求居然可以处理了。说明确实是有handlerAdapter没有配置上去。
        debug了DispatcherServlet下里面的代码,发现处理options请求时需要的handlerAdapter是HttpRequestHandlerAdapter的实例。因此问题的根源就是我们的SpringMVC的配置中没有配置HttpRequestHandlerAdapter,导致没有找到支持options类型请求的handlerAdapter。
    (3)解决问题
        由于框架的问题,不适合直接使用<mvc:annotation-driven>这个标签(用了会导致扩展的功能失效)。分析了<mvc:annotation-driven>这个标签可知它会实例化3个HandlerAdapter,而我的配置文件只实例化了一个RequestMappingHandlerAdapter。因此我把另外两个handlerAdapter的实例也添加到配置文件中了。另外2个handlerAdapter的其中之一就是HttpRequestHandlerAdapter,这个handlerAdapter就可以处理options请求。
        我把代码还原至没添加<mvc:annotation-driven>的状态,然后在注册RequestMappingHandlerAdapter的代码后面加上如下代码:
        <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>
    2
     
    1
        <bean class="org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter"/>
    2
        <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter"/>

    三、小结

        (1)SpringMVC处理Options类型的请求,需要HttpRequestHandlerAdapter,如果没有就会抛异常
        (2)当我们不使用<mvc:annotation-driven>这个标签时,尽量手动把它会注册的HandlerAdapter都注册一遍,防止出现No adapter for handler的异常


  • 相关阅读:
    nginx的那些事儿
    mysql优化初探
    mysql使用心得
    mysql 利用触发器来实现check约束
    mybtatis添加数据返回主键
    maven导入本地jar包
    mariadb做读写分离
    linux网络(一)
    kali进行arp嗅骗和攻击的一次记录
    Vue项目中:axios请求拦截器添加token验证
  • 原文地址:https://www.cnblogs.com/zeng1994/p/3557b0b3d61782225ae737c332efdf1b.html
Copyright © 2020-2023  润新知