import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.annotation.WebListener; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; @WebListener public class SpringListener implements ServletContextListener { private ApplicationContext context; @Override public void contextInitialized(ServletContextEvent e) { String ooo = e.getServletContext().getInitParameter("ooo"); context = new ClassPathXmlApplicationContext(ooo); e.getServletContext().setAttribute("xxx", context); } @Override public void contextDestroyed(ServletContextEvent arg0) { ((ClassPathXmlApplicationContext) context).close(); } }
※自己模擬一支啟動時的 Spring
※web.xml
<context-param> <param-name>ooo</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <!-- <listener> --> <!-- <listener-class>package.className</listener-class> --> <!-- </listener> -->
※尤於上面已經有Annotation,所以此時的 listener 可以不要
※Spring API裡的 org.springframework.web.context.ContextLoaderListener
建構子有說明使用 contextClass 或 contextConfigLocation
意思就是我上面的ooo,Spring 取名為 contextConfigLocation,對應的是xml設定檔
但如果用的不是設定檔,是Class,那就寫成 contextClass
寫 ooo 是無效的,不要被誤導了
而ApplicationContext,也就是如上的xxx,被存成一個常數,叫
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE
ContextLoaderListener 的父類別 ContextLoader 還有說
預設會去 /WEB-INF/applicationContext.xml 抓設定檔
所以如果你的設定檔放在這個路徑,而且也叫 applicationContext.xml
那 context-param 就可以不用寫
※使用Spring 的Web
<context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/applicationContext.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
※ContextLoaderListener 是 ServletContextListener 的子類
※測試
※pom.xml
<properties> <jdk.version>1.8</jdk.version> <spring.version>3.2.15.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> </dependencies> <build> <finalName>SpringWeb</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>${jdk.version}</source> <target>${jdk.version}</target> </configuration> </plugin> </plugins> </build>
※
※applicationContext.xml
<bean id="b" class="Book"> <property name="bookName" value="DragonBall" /> <property name="bookMoney" value="70" /> </bean>
※
※bean
public class Book { private String bookName; private int bookMoney; // setter/getter... }
※
※jsp頁面
<form action="xxx" method="post"> <input type="submit" value="送出" /> </form>
※
※Servlet
@WebServlet(urlPatterns = { "/xxx" }) public class ServletTest extends HttpServlet { protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String app = WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE; ApplicationContext ctx = (ApplicationContext) getServletContext().getAttribute(app); System.out.println(ctx.getBeanDefinitionCount()); for (String s : ctx.getBeanDefinitionNames()) { System.out.println(s); } Book b = ctx.getBean("b", Book.class); System.out.println(b); } }
※使用 Annotation 時,在啟動時出現 @EnableAsync annotation metadata was not injected 的錯誤,我將 Book.java 增加 package 就解決了,也有可能是 component-Scan 寫錯
※使用 annotation 的設定
※<context-param> <param-name>contextConfigLocation</param-name> <param-value>bean.Animal</param-value> </context-param> <context-param> <param-name>contextClass</param-name> <param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener>
※並不一定要使用常數的方式取得 applicationContxt,還可以用 ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
※多個 class 可用「,」隔開,或者用 @ComponentScan
※取得 @Autowired
super.init(); // super.init(config); WebApplicationContextUtils.getWebApplicationContext(getServletContext()) .getAutowireCapableBeanFactory() .autowireBean(this); // WebApplicationContextUtils.getWebApplicationContext(getServletContext()) // .getAutowireCapableBeanFactory() // .configureBean(this, "animal");
※覆寫 init 方法,有兩個,隨便一個都可以,有參數的可用 config.getServletContext() 取得 ServletContext
※兩者選其一即可
※animal 可以寫 @ComponentScan,這樣就可以抓到很多了