SpringMVC處理跨域請求時的一個注意事項


    由於公司對SpingMVC框架里面的東西進行了擴展,在配置SpringMVC時沒有使用 <mvc:annotation-driven> 這個標簽。而且是自己手動來配置 HandlerMapping HandlerAdapter 。在處理跨域請求時,就拋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)

二、問題的解決

(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"/>

三、小結

    (1)SpringMVC處理Options類型的請求,需要HttpRequestHandlerAdapter,如果沒有就會拋異常
    (2)當我們不使用 < mvc:annotation-driven > 這個標簽時,盡量手動把它會注冊的 HandlerAdapter 都注冊一遍,防止出現No adapter for handler的異常



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM