文章
另外加上了一些自己的一些解釋和標記 注:紅色標記的是自己的一些筆記
很久沒更新博文了,不是沒有學習,而是很多東西記在OneNote里面,收獲很多啊,因為各種雜事,所以對于博客很久沒更新了。
個人覺得:博客比起OneNote或者為知筆記之類的云筆不同在于博客應該記載的是比較成體系的東西,所以很多東西我準備統一回顧我學到的東西后,再成體系的更新在這里來。
廢話說多了,先處理RT的問題。
一、問題由來
在學習SPRingMVC的過程中,對于URL的攔截,我使用了RESTful,這是一種在形式上沒有動詞沒有后綴結尾的URL表現形式,利用PUT/POST/DELETE/GET來表示 更新、添加、刪除、查找4個不同動作的一種變現形式,具體的說明,我想我可能后來會將它寫成博文,但是我更推薦的是大家如果想了解這個方面的知識,請參考:http://www.ruanyifeng.com/blog/2011/09/restful.html 他才是大神。
因為使用了RESTful所以,在將Servlet作為Controller中的時候,web.xml中配置攔截的url-pattern就寫成了 / ,如下所示:
<servlet> <servlet-name>SpringMVC</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring/spring-mvc.xml</param-value> </init-param> <!--load-on-startup這沒有默認值的,如果不寫或者值是負數的話,那在 Servlet 容器啟動時并不會初始化這個 Servlet,而會在第一次用到時才進行初始化。正數值越小優選級越高--> <load-on-startup>1</load-on-startup> <!--async = False 表示同步方式運行,即程序要等到該語句(比如xmlDom.load())運行完畢并返回結果后才繼續執行下一條語句。這種方式編程較簡單,但程序會發生停頓現象(也就是俗稱的卡); async = True 表示異步方式運行,就是說程序發出命令后不等其運行完畢就繼續執行下一條語句。程序會通過相應的事件處理過程來接收和處理該語句的運行結果--> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <!-- 此處可以可以配置成 *.do ,對應struts的后綴習慣 --> <url-pattern>/</url-pattern> </servlet-mapping>如果配置成這樣,對于靜態資源(js,CSS等)也會被攔截,因為沒有Mapping和其對應,很顯然會報404的錯誤。
二、問題處理方式
對于此靜態資源的問題,我采用了RT所示的
<mvc:resources mapping="/css/**" location="/WEB-INF/statics/css/" /> <mvc:resources mapping="/js/**" location="/WEB-INF/statics/js/" /> <mvc:resources mapping="/images/**" location="/WEB-INF/statics/images/" /> <mvc:resources mapping="/*.html" location="/" />項目目錄結構如下:
在項目最初將其集成進去的過程中,沒有任何錯誤,一切看上去都是那么的美好。。。但是主角的故事必定充滿意外。。。
終于在那么一天,當我把全局的Formatter 集成進去,想將字符串轉成Date的時候,出問題啦,此時對于SpringMVC我的配置是:
<mvc:annotation-driven conversion-service="conversionService" /> <!-- 靜態資源映射 --> <!-- 比如${basePath}/css/ht.css 會自動請求location中的css --> <mvc:resources mapping="/css/**" location="/WEB-INF/statics/css/" /> <mvc:resources mapping="/js/**" location="/WEB-INF/statics/js/" /> <mvc:resources mapping="/images/**" location="/WEB-INF/statics/images/" /> <mvc:resources mapping="/*.html" location="/" /> <!-- 日期統一轉換 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="com.mc.bsframe.formatter.DateFormatter"> <constructor-arg name="datePattern" value="yyyy-MM-dd HH:ss:mm" /> </bean> </set> </property> </bean>錯誤提示是:
2016-06-08 23:22:13,966 DEBUG org.springframework.beans.TypeConverterDelegate.convertIfNecessary() - Original ConversionService attempt failed - ignored since PropertyEditor based conversion eventually succeededorg.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.util.ArrayList<?>] to type [java.util.List<org.springframework.core.io.Resource>] for value '[/WEB-INF/statics/js/]'; nested exception is org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.ArrayList<?>] to type [org.springframework.core.io.Resource] at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:41) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:192) at org.springframework.beans.TypeConverterDelegate.convertIfNecessary(TypeConverterDelegate.java:173) at org.springframework.beans.AbstractNestablePropertyaccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:576) at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:603) at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:203) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.convertForProperty(AbstractAutowireCapableBeanFactory.java:1527) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1486) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1226) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482) at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772) at org.springframework.context.support.AbstractapplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:839) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:538) at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:666) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:632) at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:680) at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:551) at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:492) at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136) at javax.servlet.GenericServlet.init(GenericServlet.java:158) at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1238) at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1151) at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1038) at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:4996) at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285) at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1408) at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1398) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)Caused by: org.springframework.core.convert.ConverterNotFoundException: No converter found capable of converting from type [java.util.ArrayList<?>] to type [org.springframework.core.io.Resource] at org.springframework.core.convert.support.GenericConversionService.handleConverterNotFound(GenericConversionService.java:313) at org.springframework.core.convert.support.GenericConversionService.convert(GenericConversionService.java:195) at org.springframework.core.convert.support.CollectionToCollectionConverter.convert(CollectionToCollectionConverter.java:87) at org.springframework.core.convert.support.ConversionUtils.invokeConverter(ConversionUtils.java:35) ... 36 more其實我當時很納悶,之前用Spring3.X的時候記得沒有這個問題出現,目前換成Spring4.X的時候就出現這個問題了,具體的原因優點深奧,相關的資料也查找到了,大體上就是之前的是對于資源的存儲使用的是String[]現在改成了ArrayList<>造成的問題。
三、解決方法
以上說了這么多,解決方法對于大部分人來說才是最重要的。
*移除全局的Formatter。 *使用另外的方式進行靜態資源的映射。 經過考慮我使用了后者,處理步驟如下:
1.靜態資源從WEB-INF下移動到WebApp下面。 2.注釋 <mvc resource…>
代碼 3.在SpringMVC的xml配置中加上,它的意思就是沒有映射到的URL交給默認的web容器中的servlet進行處理:
最終的關鍵配置如下:
<mvc:annotation-driven conversion-service="conversionService" /> <!-- 如果使用了RESTful形式的攔截,那么對于靜態資源的處理上,就需要加上此句,靜態資源(沒有映射的)就會 --> <mvc:default-servlet-handler /> <!-- 日期統一轉換 --> <bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean"> <property name="formatters"> <set> <bean class="com.mc.bsframe.formatter.DateFormatter"> <constructor-arg name="datePattern" value="yyyy-MM-dd HH:ss:mm" /> </bean> </set> </property> </bean>接下來對于處理靜態資源,日期格式,整體搭建SSM,以及相關注意點后繼續出爐。
由于最后靜態文件交由RESTful形式攔截,去掉了<mvc:resources .../>
總感覺很不好,而且最后也沒說之后會有什么問題,所以結合了網上的一些資料,還有一種解決方案就是: 1.問題的原因是`<mvc:resources .../>
和bean中ID為conversionService在同時出現就會出現這個問題,具體什么原因還不清楚。 2.只需要把ean中ID為conversionService的名稱改一下就可以了,什么都不要動,配置還是原來的配置 3.具體代碼實現:
新聞熱點
疑難解答