Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Configuring and Integrating Spring, Spring MVC, and MyBatis for Java Web Applications

Tech May 13 1

Integrating Spring, Spring MVC, and MyBatis requires a layered configuration approach where the root application context manages bussiness logic and persistence, while the child web context handles HTTP routing and controller execution. This annotation-driven architecture eliminates legacy XML descriptors and centralizes dependency management.

Root Application Context Setup

The foundational configuration class orchestrates component discovery, external property resolution, and module imports. It serves as the parent container for service and repository layers.

package com.example.app.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@ComponentScan(basePackages = {"com.example.app.service"})
@PropertySource(value = "classpath:db-connection.properties", ignoreResourceNotFound = true)
@Import({DataSourceConfiguration.class, PersistenceConfiguration.class})
@EnableTransactionManagement
public class AppContextConfiguration {
    // Parent container responsible for business beans and transaction management
}

Web Layer Configuration

The presentation context operates independently, focusing strictly on request mapping, view resolution, and HTTP serialization.

package com.example.app.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {"com.example.app.controller"})
public class WebMvcConfiguration {
    // Child container dedicated to Spring MVC components
}

Servlet Container Initialization

Replacing traditional web.xml deployments, an initializer binds the root and web contexts to the servlet engine. It also registers request-level filters for character encoding normalization.

package com.example.app.config;

import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

import javax.servlet.Filter;

public class WebInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class<?>[] getRootConfigClasses() {
        return new Class[]{AppContextConfiguration.class};
    }

    @Override
    protected Class<?>[] getServletConfigClasses() {
        return new Class[]{WebMvcConfiguration.class};
    }

    @Override
    protected String[] getServletMappings() {
        return new String[]{"/"};
    }

    @Override
    protected Filter[] getServletFilters() {
        CharacterEncodingFilter utfFilter = new CharacterEncodingFilter();
        utfFilter.setEncoding("UTF-8");
        utfFilter.setForceEncoding(true);
        return new Filter[]{utfFilter};
    }
}

Data Source and Persistence Configuration

Externalized connection parameters are injected into a pooled datasource. MyBatis is subsequently wired to consume this pool and auto-discover repository interfaces.

db-connection.properties

db.jdbc.driver=com.mysql.cj.jdbc.Driver
db.jdbc.url=jdbc:mysql://127.0.0.1:3306/project_db?useSSL=false&serverTimezone=UTC
db.jdbc.username=admin_user
db.jdbc.password=secure_credentials

DataSourceConfiguration.java

package com.example.app.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;

import javax.sql.DataSource;

public class DataSourceConfiguration {

    @Value("${db.jdbc.driver}")
    private String jdbcDriver;
    @Value("${db.jdbc.url}")
    private String connectionEndpoint;
    @Value("${db.jdbc.username}")
    private String credentialUser;
    @Value("${db.jdbc.password}")
    private String credentialPass;

    @Bean
    public DataSource initializePool() {
        DruidDataSource connectionPool = new DruidDataSource();
        connectionPool.setDriverClassName(jdbcDriver);
        connectionPool.setUrl(connectionEndpoint);
        connectionPool.setUsername(credentialUser);
        connectionPool.setPassword(credentialPass);
        return connectionPool;
    }

    @Bean
    public PlatformTransactionManager configureTransactions(DataSource targetSource) {
        return new DataSourceTransactionManager(targetSource);
    }
}

PersistenceConfiguration.java

package com.example.app.config;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class PersistenceConfiguration {

    @Bean
    public SqlSessionFactoryBean buildSessionFactory(DataSource connectionSource) {
        SqlSessionFactoryBean factory = new SqlSessionFactoryBean();
        factory.setDataSource(connectionSource);
        factory.setTypeAliasesPackage("com.example.app.model");
        return factory;
    }

    @Bean
    public MapperScannerConfigurer scanRepositoryInterfaces() {
        MapperScannerConfigurer interfaceScanner = new MapperScannerConfigurer();
        interfaceScanner.setBasePackage("com.example.app.repository");
        return interfaceScanner;
    }
}

Dependency Management

The following Maven coordinates establish the required runtime enviroment, handling framework integration, database drivers, and serialization utilities.

<dependencies>
    <!-- Core Framework Modules -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.25</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.3.25</version>
    </dependency>

    <!-- ORM & Integration Layer -->
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.14</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>2.1.1</version>
    </dependency>

    <!-- Connectivity & Pooling -->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.18</version>
    </dependency>
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-j</artifactId>
        <version>8.0.33</version>
        <scope>runtime</scope>
    </dependency>

    <!-- Web & Serialization -->
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>4.0.1</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.15.2</version>
    </dependency>

    <!-- Testing -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.3.25</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.13.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Request Processing Flow

During container startup, WebInitializer registers the DispatcherServlet and attaches it to the root path. The servlet loads WebMvcConfiguration, triggering component scans for @Controller classes and mapping HTTP endpoints. Simultaneously, the parent context instantiates service beans, transaction managers, and the MyBatis SqlSessionFactory. When an HTTP request arrives, it traverses the UTF-8 encoding filter, enters the DispatcherServlet, matches a handler mapping, and routes to the corresponding controller method. The controller delegates to service-layer components, which invoke auto-registered MyBatis mapper interfaces to execute parameterized SQL. Operations marked with @Transactional are intercepted by the DataSourceTransactionManager, ensuring atomic execution against the Druid connection pool before the serialized payload is returned to the client.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.