為了修複生產數據,需要執行一段一次性的代碼。 鑒於是spring老項目,就想到了InitializingBean。 代碼如下。服務啟動後,log里發現出現2條“一次性任務開始”。 好在裡面邏輯做了防重控制,沒有受到什麼影響。 @Slf4j @Component public class TransT ...
為了修複生產數據,需要執行一段一次性的代碼。 鑒於是spring老項目,就想到了InitializingBean。
代碼如下。服務啟動後,log里發現出現2條“一次性任務開始”。 好在裡面邏輯做了防重控制,沒有受到什麼影響。
@Slf4j @Component public class TransToBankBean implements InitializingBean { @Autowired private FixedLdysZhOrdersService xxxService; @Override public synchronized void afterPropertiesSet() { log.info("一次性任務開始"); .... } }
今天理了一下程式配置。發現web.xml配置有問題。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:spring-mvc.xml,classpath:spring-mybatis.xml,classpath:spring-dubbo.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <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-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> </web-app>
註意到上面web.xml中有兩個contextConfigLocation, 一個位於context-param參數中, 另一個位於servelt的init-param參數中。
問題就出現在這個contextConfigLocation上。
contextConfigLocation,名如其義,指的是context配置(文件)的位置。
servelt/init-param的contextConfig是為了載入DispatcherServlet的, 而context-param的contextConfig是為了載入web程式需要載入的資料庫等等配置。
再來說說servlet節點配置:
servlet有這麼幾個屬性:servlet-name、servlet-class、init-param。其中,servlet-class通常就是我們熟知的 DispatcherServlet。init-param中可以指定contextConfigLocation。
1) init-param里如果未配置contextConfigLocation,則要求程式在WEB-INF存在名為[servlet-name]-servlet.xml的配置文件,否則程式啟動會報異常:java.io.FileNotFoundException:Could not open ServletContext resource [/WEB-INF/SpringMVC-servlet.xml] 。(註意:我這裡servlet-name的值是SpringMVC,所以文件名字會是 SpringMVC-servlet.xml)
2) init-param里如果有contextConfigLocation配置,則DispatcherServlet會使用這個指定的配置文件作為配置。例如,我指定的參數值是classpath:spring-mvc.xml, 這個文件定義在main/resources下,編譯後存在於程式包的classes目錄中。
顯然,上面web.xml中兩個contextConfigLocation都指定了spring-mvc.xml。這個context文件里指定了component-scan包掃描路徑。
上面定義的InitializingBean實現類就在這些package下麵。所以,不難理解,這個類所覆寫的afterPropertiesSet會被執行兩次。
好,瞭解了上面的解釋。那麼,我們就知道該怎麼改了。------>分離配置,解決掃描兩遍的問題。
改造後的web.xml如下, 兩處contextConfigLocation分別指定的是application-context.xml 和 spring-mvc.xml。兩者各司其職 -----> application-context.xml是spring應用程式的上下文配置,不含springmvc配置; spring-mvc.xml中只有springmvc配置。
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <context-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:application-context.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <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-mvc.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> <async-supported>true</async-supported> </servlet> <servlet-mapping> <servlet-name>SpringMVC</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>/index.jsp</welcome-file> </welcome-file-list> </web-app>
spring-mvc.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 擴充了註解驅動,可以將請求參數綁定到控制器參數 --> <mvc:annotation-driven/> <mvc:default-servlet-handler/> <!-- controller所在包--> <context:component-scan base-package="com.levy.rpcprovider.controller"/> </beans>
當看到一些不好的代碼時,會發現我還算優秀;當看到優秀的代碼時,也才意識到持續學習的重要!--buguge
本文來自博客園,轉載請註明原文鏈接:https://www.cnblogs.com/buguge/p/16286630.html