從零構建「用戶註冊登入」專案,逐步整合 Spring IOC、MyBatis、SpringMVC、事務、緩存、Security 等核心技術棧。本篇聚焦純 Java 配置(零 XML)的 IOC 容器啟動與組件掃描策略。
<properties>
<spring.version>4.3.1.RELEASE</spring.version>
</properties>
<dependencies>
<!-- Spring Core -->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>${spring.version}</version></dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-jdbc</artifactId><version>${spring.version}</version></dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-test</artifactId><version>${spring.version}</version></dependency>
<!-- MyBatis -->
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.4.1</version></dependency>
<dependency><groupId>org.mybatis</groupId><artifactId>mybatis-spring</artifactId><version>1.3.0</version></dependency>
<!-- DB -->
<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>6.0.3</version></dependency>
<dependency><groupId>c3p0</groupId><artifactId>c3p0</artifactId><version>0.9.1.2</version></dependency>
<!-- Validation -->
<dependency><groupId>javax.validation</groupId><artifactId>validation-api</artifactId><version>1.1.0.Final</version></dependency>
<dependency><groupId>org.hibernate</groupId><artifactId>hibernate-validator</artifactId><version>5.2.4.Final</version></dependency>
</dependencies>
@Configuration
@ComponentScan(
basePackages = "com.everSeeker",
excludeFilters = @ComponentScan.Filter(
type = FilterType.CUSTOM,
value = RootConfig.WebPackage.class // 排除 Web 層組件
)
)
@ImportResource("classpath:spring-mybatis.xml") // 保留 MyBatis XML 配置
public class RootConfig {
// 自定義過濾器:排除 com.everSeeker.web 包
public static class WebPackage extends RegexPatternTypeFilter {
public WebPackage() {
super(Pattern.compile("com\\.everSeeker\\.web"));
}
}
}
@Configuration
@EnableWebMvc
@ComponentScan("com.everSeeker.web")
public class WebConfig implements WebMvcConfigurer {
@Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
resolver.setExposeContextBeansAsAttributes(true);
return resolver;
}
@Bean
public MultipartResolver multipartResolver() throws IOException {
return new StandardServletMultipartResolver(); // Servlet 3.0+ 標準上傳解析
}
@Override
public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
configurer.enable(); // 靜態資源由預設 Servlet 處理
}
}
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[]{RootConfig.class}; // 根容器:Service、DAO、DataSource
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[]{WebConfig.class}; // Web 容器:Controller、ViewResolver
}
@Override
protected String[] getServletMappings() {
return new String[]{"/"}; // DispatcherServlet 映射根路徑
}
@Override
protected void customizeRegistration(Dynamic registration) {
// 檔案上傳限制:單檔 2MB、總請求 4MB、臨時目錄 /tmp/uploads
registration.setMultipartConfig(new MultipartConfigElement(
"/tmp/uploads", 2_097_152, 4_194_304, 0));
}
}
保留 spring-mybatis.xml 統一管理 DataSource、SqlSessionFactory、Mapper 掃描、事務管理器,避免 Java 配置過於冗長。
<context:property-placeholder location="classpath:db.properties"/>
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${db.mysql.driverClass}"/>
<property name="jdbcUrl" value="${db.mysql.jdbcUrl}"/>
<property name="user" value="${db.mysql.user}"/>
<property name="password" value="${db.mysql.password}"/>
<!-- 連線池參數略 -->
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis.xml"/>
<property name="mapperLocations" value="classpath*:mapper/*Mapper.xml"/>
</bean>
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.everSeeker.dao"/>
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
</bean>
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>
// User.java
public class User {
@Size(min=32, max=32) private String id;
@Size(min=1, max=32) private String username;
@NotEmpty @Size(max=32) private String password;
@NotEmpty @Email private String email;
@Size(min=11, max=11) private String cellphone;
private long regDate;
// 建構子、Getter/Setter、toString 略
}
// UserDao.java
@Repository
public interface UserDao {
void addUser(User user);
User getUserByUsername(String username);
}
// UserMapper.xml
<mapper namespace="com.everSeeker.dao.UserDao">
<insert id="addUser" parameterType="User">
INSERT INTO user(id, username, password, email, cellphone, regDate)
VALUES(#{id}, #{username}, #{password}, #{email}, #{cellphone}, #{regDate})
</insert>
<select id="getUserByUsername" resultType="User">
SELECT * FROM user WHERE username=#{username}
</select>
</mapper>
| 註解 | 作用 | 對應 XML |
|---|---|---|
| @Configuration | 聲明配置類 | <beans> |
| @ComponentScan | 啟用組件掃描 | <context:component-scan> |
| @ImportResource | 導入 XML 配置 | <import resource=""> |
| @EnableWebMvc | 啟用 SpringMVC 預設配置 | <mvc:annotation-driven> |
| @Bean | 方法回傳值註冊為 Bean | <bean> |
| @Repository/@Service/@Controller | 層級語義化組件 | <bean> + 掃描 |
純 Java 配置優勢:類型安全、IDE 重構友善、條件化裝配靈活(@Conditional)。實務中常採「Java 配置核心基礎設施 + XML 配置持久層」混合策略,兼顧可維護性與 MyBatis 的 XML 映射優勢。