SSM整合

作者: YMeng_Zhang | 来源:发表于2021-10-10 19:21 被阅读0次

    前言

    在分别了解spring,springmvc和mybatis后,这篇文章将以实现一个小的需求的形式,对其进行整合。

    需求和步骤分析

    需求:使用 SSM 框架完成对 account 表的增删改查操作。

    步骤分析:

    1. 准备数据库和表记录
    2. 创建 web 项目
    3. 编写 MyBatis 在 SSM 环境中可以单独使用
    4. 编写 Spring 在 SSM 环境中可以单独使用
    5. Spring 整合 MyBatis
    6. 编写 SpringMVC 在 SSM 环境中可以单独使用
    7. Spring 整合 SpringMVC
    • 环境搭建

    1. 准备数据库和表记录

    CREATE TABLE `account` (
        `id` int(11) NOT NULL AUTO_INCREMENT,
        `name` varchar(32) DEFAULT NULL,
        `money` double DEFAULT NULL,
        PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    insert into `account`(`id`,`name`,`money`) values (1,'tom',1000),(2,'jerry',1000);
    

    2. 创建 web 项目
    使用 Maven 创建名为 ssm 的 web 项目

    3. 编写 MyBatis 在 SSM 环境中可以单独使用

    需求:基于 MyBatis 先来实现对 account 表的查询

    相关坐标

    ...
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.47</version>
    </dependency>
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.15</version>
    </dependency>
    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis</artifactId>
        <version>3.5.1</version>
    </dependency>
    ...
    

    Account 实体

    public class Account {
    
        private Integer id;
        private String name;
        private Double money;
        // getter and setter ...   
    }
    

    AccountDao 接口

    public interface AccountDao {
        public List<Account> findAll();
    }
    

    AccountDao.xml 映射

    <?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="com.zm.dao.AccountDao">
        <select id="findAll" resultType="com.zm.domain.Account">
            select * from account
        </select>
    </mapper>
    

    MyBatis 核心配置文件
    jdbc.properties

    jdbc.driverClassName=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql:///spring_db?characterEncoding=utf8&useSSL=false
    jdbc.username=root
    jdbc.password=password
    

    SqlMapConfig.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
    
        <!-- 加载 properties -->
        <properties resource="jdbc.properties"/>
    
        <!-- 类型别名配置 -->
        <typeAliases>
            <package name="com.zm.domain"/>
        </typeAliases>
    
        <!-- 环境配置 -->
        <environments default="mysql">
            <environment id="mysql">
                <transactionManager type="JDBC"/>
                <dataSource type="POOLED">
                    <property name="driver" value="${jdbc.driverClassName}"/>
                    <property name="url" value="${jdbc.url}"/>
                    <property name="username" value="${jdbc.username}"/>
                    <property name="password" value="${jdbc.password}"/>
                </dataSource>
            </environment>
        </environments>
    
        <!-- 加载映射 -->
        <mappers>
            <package name="com.zm.dao"/>
        </mappers>
    
    </configuration>
    

    测试代码

    public class MyBatisTest {
        @Test
        public void  testMybatis() throws IOException {
            InputStream resourceAsStream = Resources.getResourceAsStream("SqlMapConfig.xml");
    
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
    
            SqlSession sqlSession = sqlSessionFactory.openSession();
    
            AccountDao mapper = sqlSession.getMapper(AccountDao.class);
    
            List<Account> all = mapper.findAll();
            for (Account account : all) {
                System.out.println(account);
            }
    
            sqlSession.close();
        }
    }
    

    4. 编写 Spring 在 SSM 环境中可以单独使用

    相关坐标

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.8.13</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-jdbc</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-tx</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-test</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
    

    AccountService 接口

    public interface AccountService {
        List<Account> findAll();
    }
    

    AccountServiceImpl 实现

    @Service
    public class AccountServiceImpl implements AccountService {
        @Override
        public List<Account> findAll() {
            System.out.println("findAll 执行了...");
            return null;
        }
    }
    

    Spring 核心配置文件
    applicationContext.xml

    <?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:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:conext="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!-- 配置 IOC 相关操作: 开启注解扫描 -->
        <conext:component-scan base-package="com.zm.service"/>
    
    </beans>
    

    测试代码

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringTest {
        @Autowired
        private AccountService accountService;
    
        @Test
        public void testSpring() throws Exception {
            List<Account> accountList = accountService.findAll();
            System.out.println(accountList);
        }
    }
    

    5. Spring 整合 MyBatis

    整合思想
    将 MyBatis 接口代理对象的创建权交给 Spring 管理,我们就可以把 Dao 的代理对象注入到 Service 中,此时也就完成了 Spring 与 MyBatis 的整合了。
    导入整合包

    <dependency>
        <groupId>org.mybatis</groupId>
        <artifactId>mybatis-spring</artifactId>
        <version>1.3.1</version>
    </dependency>
    

    Spring 配置文件管理 MyBatis
    此时可以将 MyBatis 主配置文件 SqlMapConfig.xml 删除,在 applicationContext.xml 配置文件中加入 MyBatis:

    <?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:context="http://www.springframework.org/schema/context"
           xmlns:tx="http://www.springframework.org/schema/tx"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xmlns:conext="http://www.springframework.org/schema/context"
           xsi:schemaLocation="
            http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
    
        <!-- 配置 IOC 相关操作: 开启注解扫描 -->
        <conext:component-scan base-package="com.zm.service"/>
    
        <!-- spring 整合 mybatis 开始 -->
    
        <!-- 引入 jdbc.properties -->
        <context:property-placeholder location="classpath:jdbc.properties"/>
        <!-- 创建数据源 -->
        <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
            <property name="driverClassName" value="${jdbc.driverClassName}"/>
            <property name="url" value="${jdbc.url}"/>
            <property name="username" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
        </bean>
        <!-- sqlSessionFactory 的创建权交给了 spring,生产 sqlSession -->
        <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
            <property name="dataSource" ref="dataSource"/>
            <property name="typeAliasesPackage" value="com.zm.domain"/>
            <!-- 引入加载 mybatis 的核心配置文件,可以不用去加载 -->
    <!-- <property name="configLocation" value="classpath:SqlMapConfig.xml"/>-->
        </bean>
        <!-- mapper 映射扫描 MapperScannerConfigurer 扫描该包下所有接口,生成代理对象存到 IOC 容器中 -->
        <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
            <property name="basePackage" value="com.zm.dao"/>
        </bean>
        <!-- spring 整合 mybatis 结束 -->
    
    </beans>
    

    修改 AccountServiceImpl

    @Service
    public class AccountServiceImpl implements AccountService {
        @Autowired
        AccountDao accountDao;
    
        @Override
        public List<Account> findAll() {
            return accountDao.findAll();
        }
    }
    

    测试代码

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration("classpath:applicationContext.xml")
    public class SpringTest {
    
        @Autowired
        private AccountService accountService;
    
        @Test
        public void testSpring() {
            System.out.println(accountService.findAll());
        }
    
    }
    

    6. 编写 SpringMVC 在 SSM 环境中可以单独使用

    需求:访问到 Controller 里面的方法查询所有账户,并跳转到 list.jsp 页面进行列表展示。
    相关坐标

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>5.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>javax.servlet.jsp</groupId>
        <artifactId>jsp-api</artifactId>
        <version>2.2</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>jstl</groupId>
        <artifactId>jstl</artifactId>
        <version>1.2</version>
    </dependency>
    </dependencies>
    

    导入页面资源
    在 webapp 目录下导入 JSP 页面相关的资源:add.jspindex.jsplist.jspupdate.jsp

    index.jsp

    ...
    <div align="center">
        <a href="account/findAll" style="text-decoration:none;font-size:33px">
            查询账户信息列表
        </a>
    </div>
    ...
    

    前端控制器 DispatcherServlet

    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
             version="4.0">
    
        <!-- 前端控制器 -->
        <servlet>
            <servlet-name>DispatcherServlet</servlet-name>
            <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
            <init-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>classpath:spring-mvc.xml</param-value>
            </init-param>
            <load-on-startup>2</load-on-startup>
        </servlet>
        <servlet-mapping>
            <servlet-name>DispatcherServlet</servlet-name>
            <url-pattern>/</url-pattern>
        </servlet-mapping>
    
        <!-- 中文乱码过滤器:解决 post 方式提交的乱码 -->
        <filter>
            <filter-name>CharacterEncodingFilter</filter-name>
            <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
            <init-param>
                <param-name>encoding</param-name>
                <param-value>UTF-8</param-value>
            </init-param>
        </filter>
        <filter-mapping>
            <filter-name>CharacterEncodingFilter</filter-name>
            <url-pattern>/*</url-pattern>
        </filter-mapping>
    
    </web-app>
    

    AccountController

    @Controller
    @RequestMapping("/account")
    public class AccountController {
    
        @RequestMapping("/findAll")
        public String findAll(Model model) {
            ArrayList<Object> arrayList = new ArrayList<>();
            arrayList.add(new Account(1, "张三", 1000d));
            arrayList.add(new Account(2, "李四", 2000d));
            model.addAttribute("list", arrayList);
            return "list";
        }
    
    }
    

    list.jsp

    ···
    <c:forEach items="${list}" var="account">
        <tr>
            <td>
                <input type="checkbox" name="ids" value="${account.id}">
            </td>
            <td>${account.id}</td>
            <td>${account.name}</td>
            <td>${account.money}</td>
            <td>
                <a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/update.jsp">修改</a>&nbsp;
                <a class="btn btn-default btn-sm" href="">删除</a>
            </td>
        </tr>
    </c:forEach>
    ...
    

    SpringMVC 核心配置文件

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:mvc="http://www.springframework.org/schema/mvc"
           xmlns:context="http://www.springframework.org/schema/context"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    
        <!-- 1. 组件扫描:只扫描 controller -->
        <context:component-scan base-package="com.zm.controller"/>
    
        <!-- 2. mvc 注解增强:处理器映射器及处理器适配器 -->
        <mvc:annotation-driven/>
    
        <!-- 3. 视图解析器 -->
        <bean id="resourceViewResolve" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
            <property name="prefix" value="/"/>
            <property name="suffix" value=".jsp"/>
        </bean>
    
        <!-- 4. 放行静态资源 -->
        <mvc:default-servlet-handler/>
    
    </beans>
    

    7. Spring 整合 SpringMVC

    整合思想

    Spring 和 SpringMVC 本来就已经整合好了,都是属于 Spring 全家桶一部分。

    但是需要做到 Spring 和 web 容器整合,让 web 容器启动的时候自动加载 Spring 配置文件,web 容 器销毁的时候 Spring 的 IOC 容器也销毁。

    Spring 和 Web 容器整合

    ContextLoaderListener 加载

    可以使用 spring-web 包中的 ContextLoaderListener 监听器,来监听 servletContext 容器的创建和销毁,来同时创建或销毁 IOC 容器。

    web.xml

    <!-- 配置 spring 的监听器 -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
    

    修改 AccountController

    @Controller
    @RequestMapping("/account")
    public class AccountController {
        @Autowired
        private AccountService accountService;
    
        @RequestMapping("/findAll")
        public String findAll(Model model) {
            model.addAttribute("list", accountService.findAll());
            return "list";
        }
    }
    

    8. Spring 配置声明式事务

    Spring 配置文件加入声明式事务

    applicationContext.xml

    <!-- 1. 事务管理器 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 2. 开始事务注解的支持 -->
    <tx:annotation-driven/>
    

    AccountServiceImpl 实现类

    @Service
    @Transactional
    public class AccountServiceImpl implements AccountService {
        ...
    }
    

    add.jsp

    ...
    <form action="${pageContext.request.contextPath}/account/save" method="post">
        <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name" placeholder="请输入姓名">
        </div>
        <div class="form-group">
            <label for="money">余额:</label>
            <input type="text" class="form-control" id="money" name="money" placeholder="请输入余额">
        </div>
        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交"/>
            <input class="btn btn-default" type="reset" value="重置"/>
            <input class="btn btn-default" type="button" onclick="history.go(-1)" value="返回"/>
        </div>
    </form>
    ...
    

    AccountDao

    void save(Account account);
    

    AccountDao.xml 映射

    <insert id="save" parameterType="account">
        insert into account (`name`, `money`) values (#{name}, #{money});
    </insert>
    

    AccountService 接口和实现类

    ···
    void save(Account account);
    ···
    ···
    @Override
    public void save(Account account) {
        accountDao.save(account);
    }
    ···
    

    AccountController

    @RequestMapping("/save")
    public String save(Account account) {
        accountService.save(account);
        // 跳转到 findAll 方法重新查询一次数据库进行数据的遍历展示
        return "redirect:/account/findAll";
    }
    

    9. 修改操作

    • 数据回显

    AccountController

    @RequestMapping("/findById")
    public String findById(Integer id,Model model){
        // 存到 model 中
        model.addAttribute("account", accountService.findById(id));
        // 视图跳转
        return  "update";
    }
    

    AccountService 接口和实现类

    ···
    Account findById(Integer id);
    ···
    
    @Override
    public Account findById(Integer id) {
        return accountDao.findById(id);
    }
    ···
    

    AccountDao 接口和 AccountDao.xml 映射文件

    ···
    Account findById(Integer id);
    ···
    
    
    ···
    <select id="findById" parameterType="int" resultType="account">
        select * from account where id = #{id}
    </select>
    

    update.jsp

    ...
    <form action="${pageContext.request.contextPath}/account/update" method="post">
        <input type="hidden" name="id" value="${account.id}">
        <div class="form-group">
            <label for="name">姓名:</label>
            <input type="text" class="form-control" id="name" name="name" value="${account.name}" placeholder="请输入姓名">
        </div>
        <div class="form-group">
            <label for="money">余额:</label>
            <input type="text" class="form-control" id="money" name="money" value="${account.money}"placeholder="请输入余额">
        </div>
        <div class="form-group" style="text-align: center">
            <input class="btn btn-primary" type="submit" value="提交"/>
            <input class="btn btn-default" type="reset" value="重置"/>
            <input class="btn btn-default" type="button" onclick="history.go(-1)" value="返回"/>
        </div>
    </form>
    ...
    

    list.jsp

    ...
    <td>
        <a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/account/findById?id=${account.id}">修改</a>&nbsp;
        <a class="btn btn-default btn-sm" href="">删除</a>
    </td>
    ...
    
    • 账户更新

    AccountController

    @RequestMapping("/update")
    public String update(Account account) {
        accountService.update(account);
        return "redirect:/account/findAll";
    }
    

    AccountService 接口和实现类

    ···
    void update(Account account);
    ···
    
    ···
    @Override
    public void update(Account account) {
        accountDao.update(account);
    }
    ···
    

    AccountDao 接口和 AccountDao.xml 映射文件

    ···
    void update(Account account);
    ···
    
    ···
    <update id="update" parameterType="account">
        update account set name = #{name}, money = #{money} where id = #{id}
    </update>
    ···
    

    10. 批量删除

    list.jsp

    <form action="${pageContext.request.contextPath}/account/deleteBatch" method="post" id="deleteBatchForm">
        <table border="1" class="table table-bordered table-hover">
            <tr class="success">
                <th>
                    <input type="checkbox" id="checkAll">
                </th>
                <th>编号</th>
                <th>姓名</th>
                <th>余额</th>
                <th>操作</th>
            </tr>
    
            <c:forEach items="${list}" var="account">
                <tr>
                    <td>
                        <input type="checkbox" name="ids" value="${account.id}">
                    </td>
                    <td>${account.id}</td>
                    <td>${account.name}</td>
                    <td>${account.money}</td>
                    <td>
                        <a class="btn btn-default btn-sm" href="${pageContext.request.contextPath}/account/findById?id=${account.id}">
                            修改
                        </a>&nbsp;
                        <a class="btn btn-default btn-sm" href="">
                            删除
                        </a>
                    </td>
                </tr>
            </c:forEach>
    
            <tr>
                <td colspan="9" align="center">
                    <a class="btn btn-primary" href="${pageContext.request.contextPath}/add.jsp">添加账户</a>
                    <input class="btn btn-primary" type="button" value="删除选中" id="deleteBatchBtn">
                </td>
            </tr>
        </table>
    </form>
    
    ...
    
    <script>
        /* 实现全选全不选效果 */
        $('#checkAll').click(function () {
            $('input[name="ids"]').prop('checked', $(this).prop('checked'));
        });
    
        /* 给删除选中按钮绑定点击事件 */
        $('#deleteBatchBtn').click(function () {
            if (confirm('确定要删除吗')) {
                if ($('input[name=ids]:checked').length > 0) {
                    /* 提交表单 */
                    $('#deleteBatchForm').submit();
                }
            } else {
                alert('操作被取消')
            }
        });
    </script>
    ...
    

    AccountController

    
    @RequestMapping("/deleteBatch")
    public String deleteBatch(Integer[] ids) {
        accountService.deleteBatch(ids);
        return "redirect:/account/findAll";
    }
    

    AccountService 接口和实现类

    void deleteBatch(Integer[] ids);
    
    
    @Override
    public void deleteBatch(Integer[] ids) {
        accountDao.deleteBatch(ids);
    }
    

    AccountDao 接口和 AccountDao.xml 映射文件

    void deleteBatch(Integer[] ids);
    
    
    <delete id="deleteBatch" parameterType="int">
        delete from account
        <where>
            <foreach collection="array" open="id in(" close=")" separator="," item="id">
                #{id}
            </foreach>
        </where>
    </delete>
    

    相关文章

      网友评论

          本文标题:SSM整合

          本文链接:https://www.haomeiwen.com/subject/fanqoltx.html