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,這樣就可以抓到很多了
沒有留言:
張貼留言