SpringMVC-03

本章节主要是创建SSM项目。
SSM:代表着表现层SpringMVC、业务层Spring框架、持久层Mybatis三者的结合。需要使用Spring框架去整合SpringMVC和Mybatis。
1.创建简单的SpringMVC
2.在SpringMVC项目中创建Spring
3.Spring整合SpringMVC
4.SpringMVC项目中mybatis的单独运行
5.SpringMVC整合mybatis
6.SSM项目的mybatis事务
在这里插入图片描述

1.创建SpringMVC项目

1.1 IDEA创建SpringMVC项目

(1)创建SpringMVC项目

可以按照SpringMVC-01笔记 第 2.1节IDEA创建SpringMVC 中所记,创建SpringMVC项目。

(2)补全项目目录

在这里插入图片描述

(3).导入对应的项目依赖

我们创建的SSM项目需要导入的包:Spring的包、SpringMVC的包、SpringAOP的包、Spring事务的包、单元测试的包、mybatis的包、mysql的包。

<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
      <!--SpringAOP切面需要导入的包:spring-aop、aspectjweaver-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.6.8</version>
        </dependency>
      <!--Spring事务导入的包-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
      <!--SpringMVC导入的包:spring-webmvc、spring-web、servlet-api、jsp-api-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.0</version>
        </dependency>
      <!--单元测试junit-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>RELEASE</version>
        </dependency>
      <!--mybatis依赖-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>RELEASE</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.28</version>
        </dependency>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.0.20.RELEASE</version>
        </dependency>
      <!--Spring整合mybatis的依赖包-->
        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.0</version>
        </dependency>
    </dependencies>

(4)在resources目录下创建springMVC.xml

SpringMVC项目启动之后会加载web.xml,然后加载SpringMVC.xml文件。
在SpringMVC.xml文件中,我们需要进行1.开启包扫描;2.开启SpringMVC对注解的支持;3.配置视图解析器。
此处需要非常注意的是,SpringMVC包扫描的路径应该是只包括controller层的,不应该包括service层和dao层。 否则到后面SpringMVC使用Spring整合mybatis事务的时候会出现事务不生效的情况。

<!--SpringMVC中通过mybatis进行事务控制出现事务无法生效:
        1.SpringMVC.xml文件是mvc的配置文件,applicationContext.xml是Spring 的配置文件,事务控制在applicationContext.xml中配置
        当SSM项目启动的时候,会先加载SpringMVC.xml,后加载applicationContext.xml,
        如果在SpringMVC.xml加载的时候,将Service层的类扫描进去,后面加载applicationContext.xml就不会扫描Service层的类,事务也不会生效
        为了让事务可以生效,在SpringMVC.xml中配置的包扫描路径应该是 : 不包含Service层,可以直接指定扫描controller层
        注意:SpringMVC.xml必须不扫描service层,applicationContext.xml去扫描service层,事务才可以生效
-->
<context:component-scan base-package="com.Eheart.controller">
  <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
 <!--开启对springmvc注解的支持-->
<mvc:annotation-driven></mvc:annotation-driven>

<!--视图解析器-->
<bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="prefix" value="/WEB-INF/pages/"></property>
  <property name="suffix" value=".jsp"></property>
</bean>

(5)web.xml文件创建

SpringMVC项目启动的时候会加载web.xml文件,我们在web.xml中通过前端控制器去加载SpringMVC.xml文件。

  <!--前端控制器-->
  <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:springMVC.xml</param-value>
    </init-param>
  </servlet>
  <servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>

(6)创建Controller层

@Controller
public class HelloController {
    @Autowired
    private IUserService userService;
    
    @RequestMapping("/hello")
    public String sayHello(){
        System.out.println("hello");
        return "success";
    }
}

(7)index.jsp前端页面

<html>
  <head>
    <title>Index</title>
  </head>
  <body>
    <!--相对路径访问hello,不需要添加前缀斜杠  / -->
    <a href="hello">sayHello!!</a> <br/>
    
  </body>
</html>

(8)将Springweb项目部署到tomcat服务器上

可以按照以下步骤将Springweb项目部署到tomcat服务器。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
部署完项目之后,当启动tomcat服务器后,会弹出index.jsp的页面。我们点击 上面的定义的 sayHello!! 超链接,如果后台打印出 hello,且前端成功跳到success页面,则创建Springmvc成功。

1.2 在SpringMVC中创建Spring

此处我们创建的Spring是一个单独的Spring,还没有和SpringMVC整合的。

(1)创建对应的service、dao层、domain层文件和目录

在domain目录下,创建实体对象。
对service、dao下创建对应的接口、类文件并且添加注释:@Service、@Repository

  • AccountService
package com.Eheart.service;
import com.Eheart.domain.Account;
import java.util.List;
public interface IAccountService {
    public List<Account > findAllAccounts();
    public void changeAccount(Account account1,Account account2,double money) ;
    public Account findAccountById(Integer id);
}

  • AccountServiceImpl
@Service("accountService")
public class AccountServiceImpl implements IAccountService {

    @Autowired
    private IAccountDao iAccountDao;
    @Override
    public List<Account> findAllAccounts() {
        System.out.println("service层查询......findAllAccounts");
        return iAccountDao.selectAllAccounts();
    }

    @Override
    @Transactional(readOnly = false,propagation = Propagation.REQUIRED)
    public void changeAccount(Account account1, Account account2, double money)  {
        System.out.println("service层......changeAccount");
        account1.setMoney(account1.getMoney() - money);
        account2.setMoney(account2.getMoney() +money);
        iAccountDao.updateAccount(account1);
        System.out.println("【"+account1+"】更新");
        int i=1/0;
        iAccountDao.updateAccount(account2);
        System.out.println("【"+account2+"】更新");
    }

    @Override
    public Account findAccountById(Integer id) {
        System.out.println("service层.....findAccountById");
        return iAccountDao.selAccountById(id);
    }
}

  • AccountDao
@Repository("accountDao")
public interface IAccountDao {

    public Account selectAccountById(Integer id);

    public void updateAccount(Account account);

}
  • AccountDaoImpl
public class IAccountDaoImpl implements IAccountDao {
    @Override
    public Account selectAccountById(Integer id) {
        System.out.println("dao层....selectAccountById");
        return null;
    }

    @Override
    public void updateAccount(Account account) {
        System.out.println("dao层.....updateAccount");
    }
}

(2)创建applicationContext.xml文件

在resources资源目录下,创建applicationContext.xml,这个是Spring的配置文件。
此处的applicationContext.xml,开启包扫描,应该扫描的路径是:service、dao层。controller层应该是springMVC进行扫描的包路径,但是spring扫描是后于springmvc扫描路径的,所以此处spring扫描的包路径包括controller也是可以的。

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <!--包扫描,不扫描controller层-->
    <context:component-scan base-package="com.Eheart.*">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
    </context:component-scan>

</beans>

(3)测试Spring

通过ClassPathXmlApplicationContext 加载Spring的配置文件,我们可以通过bean的id获取对应的实体对象。

    @Test
    public void test01(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        IUserService iUserService = ac.getBean("userService", IUserService.class);
        iUserService.findAllUsers();
    }

如果在这个测试案例中,可以通过iUserService.findAllUsers(); 调用service、dao层的方法,就说明Spring搭建好了。

1.3 Spring整合SpringMVC

在上面我们创建的Spring是单独的Spring,没有和SpringMVC整合的Spring。如果我们想通过SpringMVC的controller调用Spring的service、dao层,仅上面的操作是不可以的,我们还需要将Spring和SpringMVC整合到一起。
Spring整合SpringMVC的目的就是让我们可以通过controller调用service层,进而调用dao层操作数据库。

在这里插入图片描述

(1)修改web.xml

在web.xml中,我们配置 1.Spring的监听器listener、2、配置加载类路径的配置文件:applicationContext.xml。
通过web.xml的配置,可以让SpringMVC项目启动的时候,会加载applicationContext.xml的内容,可以让SpringMVC项目启动的时候整合Spring。

<!--在项目启动的时候,就去加载applicationContext.xml的配置文件,在web.xml中配置
    ContextLoaderListener监听器(该监听器只能加载WEB-INF目录下的applicationContext.xml的配置文件)-->
<!-- 配置Spring的监听器 -->
<listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

  <!-- 配置加载类路径的配置文件:applicationContext.xml -->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath:applicationContext.xml</param-value>
  </context-param>

(2)修改controller层

controller层进行修改,通过service层的对象调用service层的方法。

@Controller
public class AccountController {
    
    @Resource(name = "accountService")
    private IAccountService iAccountService;
    
    @RequestMapping("/changeAccount")
    public String changeAccount(){
        System.out.println("controller....changeAccount");

        Account account1 = iAccountService.findAccountById(1);
        System.out.println("查询到的账户1: 【"+account1+"】");
        
        return "success";
    }
}

(3)启动tomcat验证

启动tomcat,访问创建的changeAccount控制层,如果可以打印出service、dao层的信息,则说明Spring整合SpringMVC成功。

1.4在SpringMVC中mybatis单独运行

mybatis主要是通过 通过主配置文件加载1.数据库配置、2.mapper文件的配置。
当执行dao层的时候,可以通过dao层方法的全限定类名获取对应的mapper文件,根据方法名和mapper配置文件的id可以获取执行的sql语句。

(1)在resource目录下创建 mybatisConfig.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>
  <environments default="mysql">
    <environment id="mysql">
      <transactionManager type="JDBC"></transactionManager>
      <dataSource type="POOLED">
        <property name="url" value="jdbc:mysql://127.0.0.1:3306/dbtest"></property>
        <property name="driver" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
      </dataSource>
    </environment>
  </environments>
  <!--配置mapper文件-->
  <mappers>
    <package name="com.Eheart.dao" ></package>
  </mappers>
</configuration>

(2)定义dao层接口

@Repository("accountDao")
public interface IAccountDao {
    
    @Select("select  * from account where id = #{id} ")
    public Account selectAccountById(Integer id);
    
    @Update("update account set money = #{money} where id = #{id}")
    public void updateAccount(Account account);
    
    
}

(3)测试mybatis

mybatis单独运行是通过SqlSession来进行的,而spring整合mybatis是通过SqlSessionFactoryBen。

public class MybatisTest {

    @Test
    public void test01(){
        InputStream resource = MybatisTest.class.getClassLoader().getResourceAsStream("mybatisConfig.xml");

        SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = builder.build(resource);
        SqlSession sqlSession = factory.openSession();
        IUserDao iuserDao = sqlSession.getMapper(IUserDao.class);
        List<User> users = iuserDao.selectAllUsers();
        for (User user : users) {
            System.out.println(user);
        }
    }
}

如果可以打印出查询的结果,则mybatis单独搭建成功

1.5 Spring整合mybatis

通过上面mybatis的单独搭建,我们知道mybatis生效需要数据源、mapper层接口和SqlSession。
而Spring整合mybatis,我们可以将数据源、mapper层定义到applicationContext.xml中,mybatis-spring提供了SqlSessionFactoryBean来代替SqlSession,我们需要在bean中定义SqlSessionFactoryBean.

(1)修改applicationContext.xml文件

Spring的配置文件 applicationContext.xml 除了之前包扫描之外,还需要添加数据源、SqlSessionFactoryBean的配置、mapper的配置。

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       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/aop http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
    <context:component-scan base-package="com.Eheart.*">
        <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"></context:exclude-filter>
    </context:component-scan>
  
    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://114.116.10.158:3306/dbtest"></property>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="username" value="root"></property>
        <property name="password" value="lyt@0925"></property>
    </bean>

    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据库连接池 -->
        <property name="dataSource" ref="datasource"></property>
        <!-- 加载 mybatis 的全局配置文件 -->
        <property name="configLocation"  value="classpath:mybatisConfig.xml"></property>
    </bean>
  
    <!-- <!-- 配置 Mapper 扫描器 --> -->
    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.Eheart.dao"/>
    </bean>
</beans>

(2)启动tomcat测试

启动tomcat测试,访问controller层的方法,如果可以访dao层,并且进行数据库操作,说明springMVC整合mybatis成功了。

通过SpringMVC启动之后,访问controller层,我们可以通过Spring从IOC容器中获取到service、dao层的对象,进而dao层可以通过mybatis进行数据库操作,则说明SSM项目已经搭建完成了。

SSM中Spring、SpringMVC、Mybatis的不同的作用:

  • SpringMVC的作用是表现层:启动之后可以有前端页面,通过前端页面访问controller层。
  • Spring的作用主要是控制反转和依赖注入(切面AOP现在没有用到),将service、dao层的类对象创建在容器中,我们需要的时候从容器中取(即控制反转)。也可以给对象的变量赋值(即依赖注入)
  • mybatis的主要作用在持久层,操作数据库。

1.6 SSM的mybatis事务

在SSM中通过mybatis操作数据库,如果开启mybatis的事务,需要进行以下操作。

(1)applicationContext.xml配置DataSourceTransactionManager和开启 spring 对注解事务的支持

applicationContext.xml除了包扫描、mybatis的数据池配置、mybatis的mapper配置、mybatis的SqlSessionFactoryBean配置,还需要配置:DataSourceTransactionManager和开启 spring 对注解事务的支持

    <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="url" value="jdbc:mysql://114.116.10.158:3306/dbtest"></property>
        <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="username" value="root"></property>
        <property name="password" value="lyt@0925"></property>
    </bean>
    
     <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <!-- 数据库连接池 -->
        <property name="dataSource" ref="datasource"></property>
        <!-- 加载 mybatis 的全局配置文件
         <property name="configLocation"  value="classpath:mybatisConfig.xml"></property>
        -->
    </bean>
    
       <!-- 开启 spring 对注解事务的支持 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"></property>
    </bean>
    
  <!-- 配置扫描dao的包 -->
    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.Eheart.dao"/>
    </bean>

(2)service层配置

以下通过直接进行service层的配置。
在Service类、方法上添加注释@Transactional

  • 类上添加:@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)

  • 特定方法上添加:@Transactional(readOnly = false,propagation = Propagation.REQUIRED)
    这样的话,特定方法的运行就是原子性,遇到异常是会回滚的。

  • @Transactional的属性: readOnly 代表只读,为true生效。一般查询方法设置readOnly 为true,更新方法设置readOnly 为false。

  • @Transactional的属性: propagation (事务的传播行为),常见的值有: REQUIRED、 SUPPORTS。
    • REQUIRED:如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。一般的选择(默认值),更新方法一般会设置:REQUIRED
    • SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行(没有事务),查询方法可以设置为SUPPORTS
@Service("accountService")
@Transactional(readOnly = true,propagation = Propagation.SUPPORTS)
public class AccountServiceImpl implements IAccountService {

    @Resource(name ="accountDao" )
    private IAccountDao iAccountDao;


    @Override
    @Transactional(readOnly = false,propagation = Propagation.REQUIRED)
    public void changeAccount(Account account1, Account account2, double money) {
        account1.setMoney(account1.getMoney() - money   );
        account2.setMoney(account2.getMoney() + money   );

        iAccountDao.updateAccount(account1);
        System.out.println("更新【"+account1+"】");
        int i=1/0;      //异常
        iAccountDao.updateAccount(account2);
        System.out.println("更新【"+account2+"】");
    }
}

(3)调用service层方法:changeAccount()进行测试

在方法changeAccount()中,我们进行更新account、account2,
但是更新完account1之后会执行 int i=1/0; //异常
会出现异常,不会更新account2。如果事务生效的话,account1的更新是会回滚的,我们查询数据库就可以看到account1的更新没生效。

如果事务没有生效,出现的情况是account1更新了,但是account2没有更新。出现的场景就是:账户1扣了钱,但是没有将钱转给账户2。

(4)注意事项:SSM的mybatis事务不生效

● 检查上面的事务配置是否有错误;
● 检查SpringMVC.xml的包扫描的路径是否包括:Service层,SpringMVC.xml文件包扫描的路径应该不包含Service层。

1.SpringMVC.xml文件是mvc的配置文件,applicationContext.xml是Spring 的配置文件,事务控制在applicationContext.xml中配置。当SSM项目启动的时候,会先加载SpringMVC.xml,后加载applicationContext.xml,
如果在SpringMVC.xml加载的时候,将Service层的类扫描进去,后面加载applicationContext.xml就不会扫描Service层的类,事务也不会生效。为了让事务可以生效,在SpringMVC.xml中配置的包扫描路径应该是 : 不包含Service层,可以直接指定扫描controller层
注意:SpringMVC.xml必须不扫描service层,applicationContext.xml去扫描service层,事务才可以生效

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值