Maven搭建SSM(SpringMVC+Spring+MyBatis)框架入门教程(超级详细)

  • 内容
  • 评论
  • 相关

前面介绍了基于 Maven 使用 Struts+Spring+Hibernate(SSH)框架,模仿企业级应用的开发过程,实现了用户的 CRUD 功能。接下来再使用 SpringMVC+Spring+MyBatis(SSM)框架,同样模仿企业级应用的开发过程,实现用户的 CRUD 功能。

目的很明确,让用户能直接基于 SSH 和 SSM 两个流行框架进行项目开发,减少学习到使用之间的转换过程。

创建公共 POM

为了使公司项目有正常的沉淀和重用,先创建基于 SSM 框架开发的公共 POM 构件,以免以后项目和开发人员的重复搭建。

基于 SSM 框架,用户可以独立搭建 SpringMVC、Spring 和 MyBatis 三个基本的 POM 构件。其中,Spring 的 POM 在前面的样例中已经搭建好了,叫 SpringPOM 构件。本节主要介绍 SpringMVC 和 MyBatis 构件 POM。

1. SpringMVC POM

因为 SpringMVC 同 Spring 已经在 SpringPOM 配置好了,现在只需继承 SpringPOM。

另外,SpringMVC 封装的是 Web 层应用,底层使用的是 Jsp/Servlet 技术,所以在 SpringMVC POM 中需要加入 Jsp/Servlet 相关的依赖。

因为在用户 CRUD 样例中需要有 JSON 的响应,而且 JSON 的请求和响应在实际项目中也很普通,所以在 SpringMVC POM 中也添加了 JSON 的相关依赖。

pom.xml 的详细内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.com.mvn.pom</groupId>
    <artifactId>SpringPOM</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>SpringPOM</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- 3.2.16.RELEASE,3.1.4.RELEASE -->
        <project.build.spring.version>4.2.7.RELEASE
        </project.build.spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-aspects -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${project.build.spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.0.0.Final</version>
        </dependency>
    </dependencies>
    <distributionManagement>
        <repository>
            <id>archivaServer</id>
            <url>http://localhost:8080/repository/internal</url>
        </repository>
        <snapshotRepository>
            <id>archivaServer</id>
            <url>http://localhost:8080/repository/snapshots</url>
        </snapshotRepository>
    </distributionManagement>
</project>

2. MyBatis POM

考虑到 MyBatis 最终要同 Spring 集成,并且是基于 MySQL 数据库。在 MyBatis 的 POM 中需要定义如下关键的依赖。

  • MyBatis 构件。
  • MyBatis 同 Spring 集成的构件。
  • 连接池构件。
  • MySQL 数据库驱动构件。

MyBatis4MySQLPOM 的 pom.xml 详细内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>cn.com.mvn.pom</groupId>
    <artifactId>MyBatis4MySQLPOM</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>pom</packaging>

    <name>MyBatis4MySQLPOM</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <!-- 3.6.5.Final,3.3.2.GA -->
        <project.build.mybatis.version>3.4.0</project.build.mybatis.version>
    </properties>

    <dependencies>
        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>${project.build.mybatis.version}</version>
        </dependency>
        <!-- MyBatis同Spring的集成构件 -->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
        <dependency>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-core</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- Datasource连接池 -->
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
            <version>1.4</version>
        </dependency>
        <!-- MySQL数据库驱动 -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.34</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <distributionManagement>
        <repository>
            <id>archivaServer</id>
            <url>http://localhost:8080/repository/internal</url>
        </repository>
        <snapshotRepository>
            <id>archivaServer</id>
            <url>http://localhost:8080/repository/snapshots</url>
        </snapshotRepository>
    </distributionManagement>
</project>

实现MyBatis DAO模块

因为它同 SSH 框架实现的用户 CRUD 功能一样,所以在 SSM 中,DAO 层的接口同 SSH 中的 DAO 层接口是一样的,这里就不再重新定义了,直接重用前面样例中创建的 MvnSSHDemo.DAO 构件。这里直接创建 MyBatis 的 DAO 实现部分工程,对 DAO 层接口基于 MyBatis 进行实现。

1. 创建 MvnSSMDemo.DAO.MyBatis 工程

MvnSSMDemo.DAO.MyBatis 的工程中,只需创建 Maven 的普通 Java 工程就行。

2. 编写 pom.xml

MvnSSMDemo.DAO.MyBatis 是基于 MyBatis 实现的,所以 pom 先继承 MyBatis4MySQLPOM,然后考虑到同 Spring 集成,并且实现的是 MvnSSHDemo.DAO 中定义的接口,所以需要添加 SpringPOM 和 MvnSSHDemo.DAO 的构件依赖。

注意,因为 SpringPOM 是 pom 构件,所以在应用它的依赖的时候,需要指定 type 为 pom,详细情况查看 pom.xml。

pom.xml 内容如下:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.com.mvn.pom</groupId>
        <artifactId>MyBatis4MySQLPOM</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>cn.com.mvn.ssm.demo</groupId>
    <artifactId>MvnSSMDemo.DAO.MyBatis</artifactId>
    <packaging>jar</packaging>

    <name>MvnSSMDemo.DAO.MyBatis</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <!--SpringPOM构件依赖 -->
        <dependency>
            <groupId>cn.com.mvn.pom</groupId>
            <artifactId>SpringPOM</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <type>pom</type>
        </dependency>
        <!--DAO接口依赖 -->
        <dependency>
            <groupId>cn.com.mvn.ssh.demo</groupId>
            <artifactId>MvnSSHDemo.DAO</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
    <distributionManagement>
        <repository>
            <id>archivaServer</id>
            <url>http://localhost:8080/repository/internal</url>
        </repository>
        <snapshotRepository>
            <id>archivaServer</id>
            <url>http://localhost:8080/repository/snapshots</url>
        </snapshotRepository>
    </distributionManagement>
</project>

3. 编写实现代码

基于 MyBatis 实现的 DAO 持久层,需要写以下代码。

MyBatisConfiguration.java,配置 MyBatis 的基本信息,包括数据库连接信息。

package cn.com.mvn.ssm.demo.dao.mybatis;

import java.io.IOException;
import java.util.Properties;

import javax.sql.DataSource;

import org.apache.commons.dbcp.BasicDataSource;
import org.apache.ibatis.io.Resources;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;

@Configuration // 允许注解
@ComponentScan(basePackages = { "cn.com.mvn" }) // 注解类的基本包
public class MyBatisConfiguration {
    // 将方法结果按Bean管理,别的地方可以按类型进行装配
    @Bean(autowire = Autowire.BY_TYPE)
    public DataSource dataSource() {
        // 创建数据源
        BasicDataSource dataSource = new BasicDataSource();
        Properties prop = null;
        try {
            // 读资源文件中的数据库连接信息
            prop = Resources.getResourceAsProperties("db.properties");
            String driverClass = prop.getProperty("jdbc.driverClassName");
            String jdbcUrl = prop.getProperty("jdbc.url");
            String uname = prop.getProperty("jdbc.username");
            String password = prop.getProperty("jdbc.password");

            dataSource.setDriverClassName(driverClass);
            dataSource.setUrl(jdbcUrl);
            dataSource.setUsername(uname);
            dataSource.setPassword(password);
            dataSource.setRemoveAbandonedTimeout(60);
            dataSource.setRemoveAbandoned(true);
            dataSource.setLogAbandoned(false);
            dataSource.setMinIdle(10);
            dataSource.setMinEvictableIdleTimeMillis(30000);
            dataSource.setMaxWait(10);
            dataSource.setInitialSize(2);
            dataSource.setMaxActive(10);
            dataSource.setTimeBetweenEvictionRunsMillis(30000);
            dataSource.setValidationQuery("SELECT 1");
            dataSource.setTestOnReturn(false);
            dataSource.setTestOnBorrow(true);
            dataSource.setTestWhileIdle(true);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return dataSource;

    }

    // 将返回结果对象定义成一个name为sqlSessionFactory的bean
    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactoryBean getSqlSesssionFactoryBean() {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource());
        /*
         * ClassPathResource re = new ClassPathResource("myBatisConfig.xml");
         * bean.setConfigLocation(re);
         */
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        Resource[] resources;
        try {
            // 设置MyBatis视图映射文件的路径
            resources = resolver.getResources("classpath:cn/com/mvn/ssm/demo/dao/mybatis/entity/*Mapper.xml");
            bean.setMapperLocations(resources);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return bean;
    }

    // 创建Mapper和接口的绑定配置器Bean,名称为mapper
    @Bean(name = "mapper", autowire = Autowire.BY_NAME)
    public MapperScannerConfigurer getMapperScannerConfigurer() {
        MapperScannerConfigurer conf = new MapperScannerConfigurer();
        // 设置要绑定的接口基本包路径
        conf.setBasePackage("cn.com.mvn.ssm.demo.dao.mybatis.impl");
        // 设置连接数据库的sqlSessionFactory
        conf.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return conf;
    }
}

IMvnDAO4MyBatis.java,继承前面定义的 DAO 接口,完成 MyBatis 接口定义。

package cn.com.mvn.ssm.demo.dao.mybatis.impl;
import cn.com.mvnb.ssh.demo.dao.IMvnUserDAO;

public interface IMvnUserDAO4MyBatis extends IMvnUserDAO {

}

MvnUserMapper.xml,MvnUser 实体的映射文件。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper
    namespace="cn.com.mvn.ssm.demo.dao.mybatis.impl.IMvnUserDAO4MyBatis">
    <resultMap type="cn.com.mvn.ssh.demo.entity.MvnUser"
        id="UserMap">
        <id column="ur_id" property="urId" />
        <result column="ur_user_name" property="urUserName" />
        <result column="ur_password" property="urPassword" />
        <result column="ur_age" property="urAge" />
        <result column="ur_status" property="urStatus" />
    </resultMap>
    <insert id="addUser" useGeneratedKeys="true" keyProperty="urId"
        parameterType="cn.com.mvn.ssh.demo.entity.MvnUser">
        insert into mvn_user
        (ur_user_name,ur_password,ur_age,ur_status)
        values
        (#{urUserName},#{urPassword},#{urAge},#{urStatus})
    </insert>
    <update id="update"
        parameterType="cn.com.mvn.ssh.demo.entity.MvnUser">
        update mvn_user set
        ur_age=#{urAge},ur_status=#{urStatus} where
        ur_id=#{urId}
    </update>
    <delete id="deleteUser"
        parameterType="cn.com.mvn.ssh.demo.entity.MvnUser">
        delete from mvn_user where ur_id=#{urId}
    </delete>
    <select id="findUserById" resultMap="UserMap"
        parameterType="int">
        select * from mvn_user where ur_id=#{id}
    </select>
    <select id="findUserByUserName" resultMap="UserMap"
        parameterType="java.lang.String">
        select * from mvn_user where ur_user_name=#{userName}
    </select>
    <select id="findUsers" resultMap="UserMap">
        select * from mvn_user order by ur_id
    </select>
</mapper>

db.properties,数据库连接信息配置文件。

jdbc.username=root
jdbc.password=root
jdbc.url=jdbc:mysql://localhost:3306/mvn_db
jdbc.driverClassName=com.mysql.jdbc.Driver

4. 编写测试代码

测试代码是 TestMvnUserDAOImp.java 类,里面基于 JUnit 对 DAO 接口中的每个方法做了测试。

为了完成它,同时避免 MyBatisDAO 集成到系统项目中的改动,添加了一个供 MvnUserDAOImpl 测试的服务类。里面不加业务逻辑,直接调用 DAO 接口中的方法,只是在类上面添加了事务管理。所以测试代码主要有以下几个部分。

1)IMvnUserService.java,临时测试用的服务层接口。

package cn.com.mvn.ssm.demo.mybatis.service;

import java.util.List;
import cn.com.mvn.ssh.demo.entity.MvnUser;

public interface IMvnUserService {
    /**
     * 在数据库中,添加一个新的MvnUser对象
     *
     * @param user 需要添加的用户实体对象,该对象需要有用户名、密码、年龄和状态属性
     *
     * @return void
     * @throws RuntimeException 添加失败或出现其它意外
     */
    public void addUser(MvnUser user);

    /**
     * 更新MvnUser对象。该对象中需要设置年龄、状态和id属性,属性和状态是要更新的新值,id为条件
     *
     * @param user 需要更新的MvnUser对象
     *
     * @return void
     * @throws RuntimeException 更新失败或出现其它意外
     */
    public void update(MvnUser user);

    /**
     * 删除MvnUser对象,该对象中需要有要删除对象的id属性,id属性为删除条件
     *
     * @param user 要删除的MvnUser对象
     *
     * @return void
     * @throws RuntimeException 删除失败或出现其它意外
     */
    public void deleteUser(MvnUser user);

    /**
     * 根据id查询对应的MvnUser对象
     *
     * @param id 要查询的MvnUser对象的id
     * @return MvnUser id对应的MvnUser对象,如果没有对象,返回null
     * @throws RuntimeException 出现意外情况
     */
    public MvnUser findUserById(int id);

    /**
     * 根据用户名查询对应的MvnUser对象
     *
     * @param userName 要查询的MvnUser对象的用户名
     * @return MvnUser 用户对应的MvnUser对象,如果没有对象,返回null
     * @throws RuntimeException 出现意外情况
     */
    public MvnUser findUserByUserName(String userName);

    /**
     * 查找数据库中所有的用户对象,以List集合的形式返回
     *
     * @return List<MvnUser> 所有用户对象的集合
     * @throws RuntimeException 出现意外情况
     */
    public List<MvnUser> findUsers();
}

2)MvnUserServiceImpl.java,临时测试的服务层实现类。

package cn.com.mvn.ssm.demo.mybatis.service.impl;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.com.mvn.ssh.demo.dao.IMvnUserDAO;
import cn.com.mvn.ssh.demo.entity.MvnUser;
import cn.com.mvn.ssm.demo.mybatis.service.IMvnUserService;

@Service("userService")
@Transactional
public class MvnUserServiceImpl implements IMvnUserService {
    @Autowired
    private IMvnUserDAO userDAO;

    public void addUser(MvnUser user) {
        this.userDAO.addUser(user);
    }

    public void update(MvnUser user) {
        this.userDAO.update(user);
    }

    public void deleteUser(MvnUser user) {
        this.userDAO.deleteUser(user);
    }

    public MvnUser findUserById(int id) {
        return this.userDAO.findUserById(id);
    }

    public MvnUser findUserByUserName(String userName) {
        return this.userDAO.findUserByUserName(userName);
    }

    public List<MvnUser> findUsers() {
        return this.userDAO.findUsers();
    }
}

3)TestMvnUserDAOImpl.java,基于 JUnit 的单元测试类。

package cn.com.mvn.ssm.demo.dao.mybatis.impl;

import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.com.mvn.ssh.demo.entity.MvnUser;
import cn.com.mvn.ssh.demo.entity.Status;
import cn.com.mvn.ssm.demo.mybatis.service.IMvnUserService;
import junit.framework.Assert;

public class TestMvnUserDAOImpl {
    private ApplicationContext ctx;
    private IMvnUserService userService;

    @Before
    public void init() {
        this.ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        this.userService = (IMvnUserService) ctx.getBean("userService");
    }

    @Test
    public void testAddUser() {
        MvnUser user = new MvnUser();
        user.setUrAge(11);
        user.setUrPassword("11");
        user.setUrStatus(Status.ACTIVE.getStatus());
        user.setUrUserName("myBatisUserName");
        this.userService.addUser(user);
        user = this.userService.findUserByUserName("myBatisUserName");
        Assert.assertTrue(user != null && user.getUrAge() == 11);
        this.userService.deleteUser(user);
    }

    @Test
    public void testDeleteUser() {
        MvnUser user = new MvnUser();
        user.setUrAge(11);
        user.setUrPassword("11");
        user.setUrStatus(Status.ACTIVE.getStatus());
        user.setUrUserName("myBatisUserName");
        this.userService.addUser(user);
        user = this.userService.findUserByUserName("myBatisUserName");
        this.userService.deleteUser(user);
        MvnUser u = this.userService.findUserByUserName("myBatisUserName");
        Assert.assertTrue(user != null && u == null);

    }

    @Test
    public void testFindUserById() {
        MvnUser user = this.userService.findUserById(1);
        Assert.assertEquals(user.getUrUserName(), "zhangsan");
    }

    @Test
    public void testFindByUserName() {
        MvnUser user = this.userService.findUserByUserName("zhangsan");
        Assert.assertEquals("123", user.getUrPassword());
    }

    @Test
    public void testFindUsers() {
        List<MvnUser> userList = this.userService.findUsers();
        Assert.assertTrue(userList.size() > 0);
    }

    @After
    public void destory() {
        this.userService = null;
        this.ctx = null;
    }
}

4)applicationContext.xml,测试的时候,Spring 的配置文件。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="cn.com.mvn" />
</beans>

5. 测试、安装和发布

同前面的类似。

实现 Spring 的 Service 层模块

SSM 中的 Service 层实现同 SSH 框架中的 Service 层实现一样。唯一不同的是 DAO 的注入只能用 @Autowired 根据类型注入,不能用 @Qualifier 根据名称注入。

因为前面 MyBatis DAO 的实现使用的是 MyBatis3 的新特征:接口和映射文件自动绑定,没有自己独立实现 DAO 类,更没有在 Spring 容器中配置 DAO Bean、指定 Bean 的名称。

MvnSSMDemo.Service.Impl 工程的实现步骤如下。

1. 创建 MvnSSMDemo.Service.Impl 工程

只需创建 Maven 的简单 Java 工程。

2. 编写 pom.xml 骨架文件

pom 内容主要体现在以下几个方面。

  • 继承 SpringPOM 公共构件,避免重复配置对 Spring 相关构件的依赖。
  • 添加 MvnSSHDemo.DAO 接口依赖和 MvnSSHDemo.Service 接口依赖。
  • 为了方便测试,添加 MvnSSMDemo.DAO.MyBatis 依赖,scope 范围是 test。

pom.xml 的代码如下所示:

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>cn.com.mvn.pom</groupId>
        <artifactId>SpringPOM</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </parent>
    <groupId>cn.com.mvn.ssm.demo</groupId>
    <artifactId>MvnSSMDemo.Service.Impl</artifactId>
    <packaging>jar</packaging>

    <name>MvnSSMDemo.Service.Impl</name>
    <url>http://maven.apache.org</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>cn.com.mvn.ssh.demo</groupId>
            <artifactId>MvnSSHDemo.DAO</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>cn.com.mvn.ssh.demo</groupId>
            <artifactId>MvnSSHDemo.Service</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>cn.com.mvn.ssm.demo</groupId>
            <artifactId>MvnSSMDemo.DAO.MyBatis</artifactId>
            <version>0.0.1-SNAPSHOT</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
</project>

3. 编写实现代码

Service 层主要实现用户对象的 CRUD 功能,同 SSH 中的 Service 层的代码类似,唯一不同的是,对 DAO 对象的注入只能用 byType 的自动注入,不能用 byName。Service 层的内容如下。

UserServiceImpl.java,实现用户的 CRUD 功能。

package cn.com.mvn.ssh.demo.service.impl;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.com.mvn.ssh.demo.dao.IMvnUserDAO;
import cn.com.mvn.ssh.demo.entity.MvnUser;
import cn.com.mvn.ssh.demo.service.IUserService;

//@Configuration
@Service("userService") // 注册成服务组件
@Transactional // 要求启动事务
public class UserServiceImpl implements IUserService {
    @Autowired // 自动根据类型注入
    // @Qualifier("userDAO") // 根据name注入
    private IMvnUserDAO userDAO;

    @Transactional(propagation = Propagation.REQUIRED) // 需要进行事务管理
    public void createUser(MvnUser user) {
        // 验证输入的用户是否为null
        if (user == null) {
            throw new RuntimeException("创建的user不能为null");
        }
        // 验证用户名是否有存在
        MvnUser u = this.userDAO.findUserByUserName(user.getUrUserName());
        if (u != null) {
            throw new RuntimeException(u.getUrUserName() + " 已经存在");
        }
        this.userDAO.addUser(user);
    }

    @Transactional(propagation = Propagation.REQUIRED) // 需要进行事务管理
    public void editUser(int age, String status, int id) {
        // 根据id找到以前的用户对象
        MvnUser user = this.userDAO.findUserById(id);
        // 判断用户是否存在,不存在抛异常,存在就更新
        if (user == null) {
            throw new RuntimeException("id为" + id + "用户不存在");
        } else {
            user.setUrAge(age);
            user.setUrStatus(status);
            this.userDAO.update(user);
        }
    }

    @Transactional(propagation = Propagation.REQUIRED) // 需要进行事务管理
    public void deleteUser(int id) {
        // 根据id找到以前的用户对象
        MvnUser user = this.userDAO.findUserById(id);
        // 判断用户是否存在,不存在抛异常,存在就删除
        if (user == null) {
            throw new RuntimeException("id为" + id + "用户不存在");
        } else {
            this.userDAO.deleteUser(user);
        }
    }

    @Transactional(readOnly = true) // 只读,不需要进行事务管理
    public MvnUser searchUser(int id) {
        MvnUser user = null;
        user = this.userDAO.findUserById(id);
        return user;
    }

    @Transactional(readOnly = true) // 只读,不需要进行事务管理
    public MvnUser searchUser(String userName) {
        MvnUser user = null;
        user = this.userDAO.findUserByUserName(userName);
        return user;
    }

    @Transactional(readOnly = true) // 只读,不需要进行事务管理
    public List<MvnUser> searchUsers() {
        List<MvnUser> userList = null;
        userList = this.userDAO.findUsers();
        return userList;
    }
}

4. 编写测试代码

MvnSSMDemo.Service.Impl 的测试代码有两个。

1)TestUserServiceImpl.java

实现测试 UserServiceImpl.java 的 JUnit 代码,内容如下所示:

package cn.com.mvn.ssh.demo.service.impl;

import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.com.mvn.ssh.demo.entity.MvnUser;
import cn.com.mvn.ssh.demo.entity.Status;
import cn.com.mvn.ssh.demo.service.IUserService;
import junit.framework.Assert;

public class TestUserServiceImpl {
    private IUserService userService;
    private ApplicationContext ctx = null;

    @Before
    public void init() {
        this.ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        this.userService = (IUserService) ctx.getBean("userService");
    }

    @Test
    public void testCreateUser() {
        MvnUser user = new MvnUser();
        user.setUrAge(11);
        user.setUrPassword("11");
        user.setUrStatus(Status.ACTIVE.getStatus());
        user.setUrUserName("service1");
        this.userService.createUser(user);
        MvnUser u = this.userService.searchUser("service1");
        boolean bool = u != null && u.getUrAge() == 11 && u.getUrStatus().equals(Status.ACTIVE.getStatus());
        Assert.assertTrue(bool);
        // 删除用户
        this.userService.deleteUser(u.getUrId());
    }

    @Test
    public void testEditUser() {
        MvnUser user = new MvnUser();
        user.setUrAge(11);
        user.setUrPassword("11");
        user.setUrStatus(Status.ACTIVE.getStatus());
        user.setUrUserName("service1");
        this.userService.createUser(user);
        MvnUser u = this.userService.searchUser("service1");
        this.userService.editUser(88, Status.INACTIVE.getStatus(), u.getUrId());
        u = this.userService.searchUser("service1");
        Assert.assertTrue(u.getUrAge() == 88 && u.getUrStatus().equals(Status.INACTIVE.getStatus()));
        this.userService.deleteUser(u.getUrId());
    }

    @Test
    public void testDeleteUser() {
        MvnUser user = new MvnUser();
        user.setUrAge(11);
        user.setUrPassword("11");
        user.setUrStatus(Status.ACTIVE.getStatus());
        user.setUrUserName("service1");
        this.userService.createUser(user);
        MvnUser u = this.userService.searchUser("service1");
        this.userService.deleteUser(u.getUrId());
        MvnUser u2 = this.userService.searchUser(u.getUrId());
        Assert.assertTrue(u != null && u2 == null);
    }

    @Test
    public void testSearchUserById() {
        MvnUser user = this.userService.searchUser(1);
        Assert.assertNotNull(user);
    }

    @Test
    public void testSearchUserByUserName() {
        MvnUser user = this.userService.searchUser("zhangsan");
        Assert.assertNotNull(user);
    }

    @Test
    public void testSearchUsers() {
        List<MvnUser> userList = this.userService.searchUsers();
        Assert.assertTrue(userList != null && userList.size() > 0);
    }

    @After
    public void destory() {
        this.userService = null;
        this.ctx = null;
    }
}

2)applicationContext.xml

测试时要初始化 Spring 容器。因为只在测试起作用,所以该文件要同前面的 TestUserServiceImpl.java 代码一样,放在 src/test 的对应子目录下,代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd">

    <context:component-scan base-package="cn.com.mvn" />
</beans>

5. 测试安装和发布

右击“工程”,选择 Run As→Maven test→install→deploy 命令完成测试安装和发布,发布完成后,Archiva 私服上可以看到 MvnSSMDemo.Service.Impl 的构件。

实现 SpringMVC Web 模块

用户 CRUD 模块的 SSM Web 层实现,这里采用的是 SpringMVC 4.x 版本,用的是零配置方式实现的。

所以要理解后面的代码实现需要有 SpringMVC 4.x 的开发基础,建议没有接触过的读者先参考 SpringMVC 4.0 注解开发 Web 应用的相关资料。

Web 层基于框架的开发流程可以抽象成以下几个部分。

  • 在 web.xml 中配置框架的拦截入口,可能是过滤器,也可能是 servlet。
  • 开发显示层代码一般是 jsp 页面。
  • 开发控制层代码,实现接收请求数据,调用 service 处理请求数据,返回结果 view 层的标记。
  • 通过配置文件描述框架运行时,对请求的处理代码的对应关系和页面转换流程。

基于 SpringMVC 4.x 用零配置方式开发 Web 层也是同样的流程。只是因为是零配置方式,也就看不到配置文件相关的代码,但是以前配置文件描述的信息肯定还是要描述的,只是用注解或其他方式体现。

对 SpringMVC Web 的实现思路有了基本了解后,接下来就开始实现 SSMDemo 的 Web 层功能。

1. 创建 Maven 的 Web 工程

前面大部分工程都是基于 Maven 的普通 Java 工程。这里要基于创建 Web 应用的插件创建 Web 工程,详细过程如下。

单击 Maven 中的创建 Maven Project 的选项,如图 1 所示。

创建Maven Project
图 1  创建 Maven Project

本文标题:Maven搭建SSM(SpringMVC+Spring+MyBatis)框架入门教程(超级详细)

本文地址:http://www.hosteonscn.com/6265.html

评论

0条评论

发表评论

邮箱地址不会被公开。 必填项已用*标注