今天要分享用Java Config初始化Java Web應用程式,不需要再撰寫web.xml檔,這項feature是自Servlet 3.0以後才支援,也意味著Tomcat 7以後才能跑,Springframwork提供一開始提供一個介面WebApplicationInitializer提供實作DispatchServlet,後來提供實作WebApplicationInitializer兩個抽象類別 AbstractDispatcherServletInitializer( for載入Spring組態設定檔, 如)application context.xml以及AbstractAnnotationConfigDispatcherServletInitializer( for 載入Java Config Class),其實差別僅在於前者必須透過XmlWebApplicationContext載入xml組態檔,後者提供Java Config class檔,前者code如下,新增一個class WebConfigForWebApplicationContext並繼承AbstractDispatcherServletInitializer,
package tw.blogger.springtech.springmvc.config;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.XmlWebApplicationContext;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
public class WebConfigForWebApplicationContext extends
AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createServletApplicationContext() {
// TODO Auto-generated method stub
XmlWebApplicationContext ctx=new XmlWebApplicationContext();
ctx.setConfigLocation("/WEB-INF/springconfig/dispatchservletcontext.xml");
return ctx;
}
@Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
// return null;
return new String[] { "/" };
}
@Override
protected WebApplicationContext createRootApplicationContext() {
// TODO Auto-generated method stub
//return null;
XmlWebApplicationContext ctx=new XmlWebApplicationContext();
ctx.setConfigLocation("/WEB-INF/springconfig/service.xml"); //如果有多個xml要載入的話,
//可以選擇setConfigLocations,以陣列型式傳入
return ctx;
}
}
另外service.xml改寫成ServiceConfig,boneCP的相關參數值用官方建議數值,然後新增jdbcTemplate bean以及拿掉MyDAO:
package tw.blogger.springtech.springmvc.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.core.JdbcTemplate;
import com.jolbox.bonecp.BoneCPDataSource;
@PropertySource(value="classpath:jdbc.properties")
@Configuration
public class ServiceConfig {
@Autowired
Environment env; //Environment物件存放Profile以及Property Source
@Bean
public BoneCPDataSource datasource(){
BoneCPDataSource datasource = new BoneCPDataSource();
/*以下就設定一些dataSource的參數,url, username及password key/value pair
* 另外存在jdbc.properties檔裡,再用eng.getProperty("key")取得value,
*/
datasource.setDriverClass("com.mysql.jdbc.Driver");
datasource.setJdbcUrl(env.getProperty("jdbc.url"));
datasource.setUsername(env.getProperty("jdbc.username"));
datasource.setPassword(env.getProperty("jdbc.password"));
datasource.setIdleConnectionTestPeriodInMinutes(60);
datasource.setIdleMaxAgeInMinutes(420);
datasource.setMaxConnectionsPerPartition(30);
datasource.setMinConnectionsPerPartition(10);
datasource.setPartitionCount(3);
datasource.setAcquireIncrement(5);
datasource.setStatementsCacheSize(100);
return datasource;
}
@Bean
public JdbcTemplate jdbcTemplate(){
return new JdbcTemplate(datasource()); //Dependency Injection只需要呼叫方法即可
}
}
Java Config的code如下,新增一個class WebConfigForJavaConfig並繼承AbstractAnnotationDispatcherServletInitializer,:
package tw.blogger.springtech.springmvc.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebConfigForJavaConfig extends
AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
// TODO Auto-generated method stub
// return null;
return new Class<?> []{ServiceConfig.class}; //如同contextListener載入Service.xml或是其他helper
}
@Override
protected Class<?>[] getServletConfigClasses() {
// TODO Auto-generated method stub
//return null;
return new Class<?>[]{MVCConfig.class}; //傳回DispatchServlet Java Config Class
}
@Override
protected String[] getServletMappings() {
// TODO Auto-generated method stub
//return null;
return new String[] {"/"}; //相當於Servlet Mapping底下的<url-pattern>/</url-pattern>
}
}
Java Config以及XML載入只能選一個,否則Server無法正常啟動,因為兩個基本上都是註冊DispatchServlet,錯誤訊息如下。
資訊: Spring WebApplicationInitializers detected on classpath: [tw.blogger.springtech.springmvc.config.WebConfigForJavaConfig@4a1ed3fc, tw.blogger.springtech.springmvc.config.WebConfigForWebApplicationContext@6cfca244]
.......
Caused by: java.lang.IllegalArgumentException: Failed to register servlet with name 'dispatcher'.Check if there is another servlet registered under the same name.
......
如果拿掉一個,成功執行畫以及專案目錄截圖如下:
<img src="http://ithelp.ithome.com.tw/upload/images/20141005/2014100522522154315b258199d_resize_600.png" style="height:304px; width:600px"></img><img src="http://ithelp.ithome.com.tw/upload/images/20141005/2014100522523654315b340d5b9_resize_600.png" style="height:534px; width:427px"></img>
另外之前的專案都忘記放入log4j的設定檔,放置位置在src/main/resources,其xml code如下:
<?xml version="1.0" encoding="UTF-8"?>
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
<!-- Appenders -->
<appender name="console" class="org.apache.log4j.ConsoleAppender">
<param name="Target" value="System.out" />
<layout class="org.apache.log4j.PatternLayout">
<param name="ConversionPattern" value="%d{HH:mm:ss} [%t] %c{1} - %m%n" />
</layout>
</appender>
<logger name="tw.blogger.springtech.springmvc.mvc">
<level value="debug" />
</logger>
<logger name="org.springframework.http">
<level value="debug" />
</logger>
<logger name="org.springframework.web">
<level value="debug" />
</logger>
<root>
<priority value="warn" />
<appender-ref ref="console" />
</root>
</log4j:configuration>
個人通常都看http、web及自己有興趣的部分,之後也可以再加。
今天就先到這裡,明天繼續囉