【SaaS-Export项目】 - 03 SSM整合到每个子工程中,多模块工程整合SSM,export_dao子工程配置数据库访问,service子工程配置事务管理,web子工程整合SpringMVC

数据库准备

在这里插入图片描述
需要sql文件的可以点击这个:
Saas-Export数据库sql文件

1. dao层Spring整合MyBatis进行数据库访问(export_dao子工程)

1.1 需要spring和mybatis的整合包(前面已经导入了)

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>${mybatis.spring.version}</version>
        </dependency>

需要导入c3p0的依赖文件

        <!--c3p0数据库连接池-->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>

1.2 export_dao下创建属性文件(连接数据库c3p0连接池)

resources/properties/c3p0.properties

# key=value
#c3p0连接池属性文件
# 四大基本信息
c3p0.driverClass=com.mysql.jdbc.Driver
c3p0.jdbcUrl=jdbc:mysql://localhost:3306/saas-export?useUnicode=true&characterEncoding=UTF-8&useSSL=false
c3p0.user=root
c3p0.password=861221293

# 初始化连接数  取值要在minPoolSize和maxPoolSize之间(可包含,闭区间) 默认值:3
c3p0.initialPoolSize=10
# 最大连接数 (连接池中的连接数不能超过maxPoolSize最大连接数) 默认值:15
c3p0.maxPoolSize=50
#最小连接数  默认值:3
c3p0.minPoolSize=5
#c3p0连接池中数据连接不够时(无空闲连接可用),一次增长的个数(增长不能超过maxPoolSize最大连接个数) 默认值:3
c3p0.acquireIncrement=5
#连接的最大空闲时间,如果超过这个时间还没有被使用,就断开这个连接(设置为0或负数,就永远都不会被断开) 单位:秒  默认值 :0
c3p0.maxIdleTime=600
#从数据库获取新连接失败后重复尝试的次数。小于等于0表示无限次  默认值: 30
c3p0.acquireRetryAttempts=30
#两次连接的中间间隔时间(重新尝试的时间间隔)  单位:毫秒  默认值:1000
c3p0.acquireRetryDelay=1000
#连接关闭时,是否将所有未提交的操作进行事务回滚  默认值:false
c3p0.autoCommitOnClose = false
#当连接池用完时,客户端调用getConnection()后等待获取新连接的时间  单位:毫秒  默认值:0 (无限期等待)  按照设置的值,超时将抛出SQLException异常
c3p0.checkoutTimeout = 0
#每隔多少秒检查所有连接池中的空闲连接  单位:秒   默认值:0
c3p0.idleConnectionTestPeriod=60
#配置PreparedStatement缓存,设置连接池为数据源缓存的PreparedStatement的总数,为0的时候不缓存,同时maxStatementsPerConnection的配置无效。
# 由于PreparedStatement属于单个Connection,所以这个数量应该根据应用中平均连接数乘以每个连接的平均PreparedStatement来计算
c3p0.maxStatements=1000


# 连接池为数据源单个Connection缓存的PreparedStatement数,这个配置比maxStatements更有意义,因为它缓存的服务对象是单个数据连接,如果设置的好,肯定是可以提高性能的。为0的时候不缓存。
# c3p0.maxStatementsPerConnection

1.3 export_dao子工程下创建applicationContext-dao.xml

export_dao子工程交给spring来管理,创建一个对应的applicationContext-dao.xml
路径:resources/spring/applicationContext-dao.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"

       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">

<!-- dao子工程交给Spirng来管理,创建一个对应的applicationContext-dao.xml -->

    <!-- 引入c3p0的属性文件(里面是连接数据库四大信息键值对),在配置中通过占位使用 -->
    <context:property-placeholder location="classpath:properties/c3p0.properties" />

    <!-- 连接数据库的四大基本信息-->
    <!-- 数据库连接池c3p0 -->
    <!-- 用c3p0数据源配置连接池,里面有连接池  ComboPooledDataSource数据库连接池 -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!-- 连接池4大组件 -->
        <property name="driverClass" value="${c3p0.driverClass}"/>
        <property name="jdbcUrl" value="${c3p0.jdbcUrl}"/>
        <property name="user" value="${c3p0.user}"/>
        <property name="password" value="${c3p0.password}"/>

        <!--初始化连接数  取值要在minPoolSize和maxPoolSize之间(可包含,闭区间) 默认值:3 -->
        <property name="initialPoolSize" value="${c3p0.initialPoolSize}"/>
        <!-- 最大连接数 (连接池中的连接数不能超过maxPoolSize最大连接数) 默认值:15-->
        <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
        <!--最小连接数  默认值:3  -->
        <property name="minPoolSize" value="${c3p0.minPoolSize}"/>
        <!-- c3p0连接池中数据连接不够时(无空闲连接可用),一次增长的个数(增长不能超过maxPoolSize最大连接个数) 默认值:3 -->
        <property name="acquireIncrement" value="${c3p0.acquireIncrement}"/>
        <!-- 连接的最大空闲时间,如果超过这个时间还没有被使用,就断开这个连接(设置为0或负数,就永远都不会被断开) 单位:秒  默认值 :0 -->
        <property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>

        <!-- 从数据库获取新连接失败后重复尝试的次数。小于等于0表示无限次  默认值: 30-->
        <property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}"/>
        <!-- 两次连接的中间间隔时间(重新尝试的时间间隔)  单位:毫秒  默认值:1000 -->
        <property name="acquireRetryDelay" value="${c3p0.acquireRetryDelay}"/>
        <!-- 连接关闭时,是否将所有未提交的操作进行事务回滚  默认值:false -->
        <property name="autoCommitOnClose" value="${c3p0.autoCommitOnClose}"/>
        <!-- 当连接池用完时,客户端调用getConnection()后等待获取新连接的时间  单位:毫秒  默认值:0
                如果值设为 0,将无限期等待,直到有空闲连接。  否则按照设置的值,超时将抛出SQLException异常
                时间设置过小时会出现连接超时,这样会抛出SQLException异常,设置时间时需要小心,按照实际情况设置适当的值-->
        <property name="checkoutTimeout" value="${c3p0.checkoutTimeout}"/>
        <!-- 每隔多少秒检查所有连接池中的空闲连接  单位:秒   默认值:0 -->
        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}"/>

        <!-- 配置PreparedStatement缓存,设置连接池为数据源缓存的PreparedStatement的总数
                为0的时候不缓存,同时maxStatementsPerConnection的配置无效。
               由于PreparedStatement属于单个Connection,所以这个数量应该根据应用中平均连接数乘以每个连接的平均PreparedStatement来计算-->
        <property name="maxStatements" value="${c3p0.maxStatements}"/>

    </bean>


    <!-- 获取sqlSessionFactory-->
    <bean id="sqlSessionFactory"  class="org.mybatis.spring.SqlSessionFactoryBean">
        <!--配置数据源-->
        <property name="dataSource" ref="dataSource"/>
        <!-- 给整个包下的所有文件起别名,就是类名的首字母小写 com.xgf.domain.Person 简化成 person-->
        <property name="typeAliasesPackage" value="com.xgf.domain"/>
    </bean>
    <!-- 配置映射文件扫描器  : IPersonDao.xml和IPersonDao.java-->
    <bean id="mapperScanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <!-- 扫描dao接口和映射xml编译后的类路径 -->
        <property name="basePackage" value="com.xgf.dao"/>
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
    </bean>

</beans>

1.4 测试能否自动装载,能否查询到数据库

jaca》》com/xgf/dao/company/ICompanyDao

@Repository
public interface ICompanyDao {
    //查询所有的公司记录
    //select * from ss_company
    List<Company> findAll();
}

resources》》com/xgf/dao/company/ICompanyDao.xml

<mapper namespace="com.xgf.dao.company.ICompanyDao">
    <!-- 数据库表字段名(列名)与类的成员变量不一致的解决办法
        1. sql语句通过 as取别名,与类的成员变量一致
        2. 使用mybatis的resultMap映射实现(column表的列名,property类的属性名映射
     -->
    <resultMap id="companyMap" type="company">
         <id column="id" property="id"/>
         <result  column="expiration_date" property="expirationDate"/>
         <result  column="license_id" property="licenseId"/>
         <result  column="company_size" property="companySize"/>
    </resultMap>
    <select id="findAll" resultMap="companyMap">
        select
            *
        from ss_company
    </select>
</mapper>

test》》com/xgf/dao/company/ICompanyDaoTest

//通过Spring自带的junit测试 - 两个注解
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/applicationContext-dao.xml")
public class TestCompanyDao {
    //通过@Autowrie从spring中获取dao的实现类对象
    @Autowired
    ICompanyDao companyDao;//自动装载,就相当于ICompanyDao iCompanyDao = new iCompanyDao()
    @Test
    public void test01(){
        //测试自动装载能否实现
        System.out.println("companyDao对象:" + companyDao);

        List<Company> companyList = companyDao.findAll();
        System.out.println(companyList);
    }
}

测试结果:(自动装载成功,查询数据库成功)
在这里插入图片描述

2. service依赖dao,测试读取dao的信息,配置事务管理(export_system_service子工程)

子工程export_system_service依赖子工程export_domain

2.1 关于classpath路径读取的使用

@ContextConfiguration("classpath*:spring/applicationContext-*.xml")

classpath加载当前maven工程的resources目录下的配置文件
classpath*::加载当前maven工程及其依赖工程的resources目录下的配置文件
applicationContext-.xml*:读取所有符合规则的文件(比如前面的applicationContext-dao.xml文件)

2.2 创建测试类TestCompanyService

》test/com/xgf/service/company/TestCompanyService

//Spring的单元测试
//@ContextConfiguration("classpath*:spring/applicationContext-*.xml")
//  加载当前maven工程及其依赖工程的resources目录下的配置文件,读取所有符合规则的文件(tx和dao)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath*:spring/applicationContext-*.xml")
public class TestCompanyService {
    @Autowired
    ICompanyService companyService;
    @Test
    public void test01(){
        //1:编写了业务逻辑的测试
        //ICompanyService  companyService = new CompanyServiceImpl();
        List<Company> list = companyService.findAll();
        System.out.println(list);
    }

}

2.3 创建Service接口及其实现类

》test/com/xgf/service/company/ICompanyService

public interface ICompanyService {
    public List<Company> findAll();
}

》test/com/xgf/service/impl/CompanyServiceImpl

@Service //注解 @Service,该类交由Spring管理创建
public class CompanyServiceImpl implements ICompanyService {
    @Autowired
    ICompanyDao companyDao;
    public List<Company> findAll() {
        //service要调用dao查询数据,所以要注入
        return companyDao.findAll();
    }
}

2.4 在export_system_service子工程创建spring事务管理

》resources/spring/applicationContext-tx.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:tx="http://www.springframework.org/schema/tx"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:context="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/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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!-- Service子工程,进行事务管理,交给Spring事务管理,applicationContext-tx.xml -->
    <!-- 扫描Service实现类@Service注解 -->
    <context:component-scan base-package="com.xgf.service"/>

    <!--配置Spring框架的 声明式事务管理(底层是AOP):三个步骤 -->
    <!--1. 配置事务管理器  DataSourceTransactionManager是spring给我们的管理事务的对象,
            这个对象要用到连接池,用完需要将连接放回连接池
            管理事务:DataSource.Connection.commit() rollback()方法-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- 2. 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <!--配置事务细节特征-->
        <tx:attributes>
            <!--查询方法,使用默认的隔离级别 及 SUPPORTS传播行为-->
            <tx:method name="find*" isolation="DEFAULT" propagation="SUPPORTS"/>
            <tx:method name="query*" isolation="DEFAULT" propagation="SUPPORTS"/>
            <tx:method name="select*" isolation="DEFAULT" propagation="SUPPORTS"/>
            <tx:method name="get*" isolation="DEFAULT" propagation="SUPPORTS"/>
            <!--增删改方法,使用默认的隔离级别 及 REQUIRED传播行为-->
            <tx:method name="*" isolation="DEFAULT" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>

    <!-- 3. 配置事务切面: 切面=通知+切入点 -->
    <aop:config>
        <!-- expression表达式的值,按照你的路径配置
            * com.xgf.service.impl.*ServiceImpl.*(..))
                第一个* 是返回值通配符
                然后是包的路径,*ServiceImpl表示配置的所有满足类名+ServiceImpl后缀的且在com.xgf.service.*.impl目录下的
                *(..) : *表示所有方法 (..)表示匹配所有参数
        -->
        <!--配置切入点-->
        <aop:pointcut id="pt" expression="execution(* com.xgf.service.*.impl.*ServiceImpl.*(..))"/>
        <!-- 切面 = 通知+切入点  -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
    </aop:config>

</beans>

2.5 测试运行

在这里插入图片描述

如果出现异常情况,参考下面几种情况

  1. 如果出现applicationContext异常

可能是加载配置文件错误,因为我们要加载当前service子工程的spring/applicationContext-tx.xml事务管理也要加载service所依赖的dao子工程的
spring/applicationContext-dao.xml模块,所以用下面这种方式加载。

@ContextConfiguration("classpath*:spring/applicationContext-*.xml")
  1. 如果出现UTF-8异常,可能是父工程的pom.xml没有配置UTF-8
    去父工程,加上这个:
	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
  1. 如果出现自己写的类找不到异常

需要在每个工程的pom.xml写packaging的打包方式

<!-- 父工程 export_parent 设置packaging为pom -->
	<packaging>pom</packaging>

<!-- 非web子工程(export_domain、export_dao、export_system_service)设置packaging为jar -->
	<packaging>jar</packaging>

<!-- web子工程 export_web_manager 设置packaging为war(因为tomcat只能运行war包) -->
	<packaging>war</packaging>

3. Spring整合SpringMVC(export_web_manager子工程)

3.1 创建log4j.properties日志属性文件

直接创建在子工程的resources下

# 将debug等级(可修改)的日志信息输出到CONSOLE和LOGFILE这两个目的地(多个按,逗号隔开)
# CONSOLE和LOGFILE定义在下面的代码,【可以任意起名,可以有多个,不一定只是两个】
# 等级:OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL
#    比如(配置OFF全部都不显示,配置为INFO这样只显示INFO、WARN、ERROR的log信息,而DEBUG信息不会被显示)
log4j.rootCategory=debug, CONSOLE, LOGFILE

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.
log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

# =======================================================================================
# CONSOLE配置(名称可以自定义) - 这里配置控制台输出日志

# log4j.appender.CONSOLE -->  定义名为CONSOLE的输出端是哪种类型,有五个值
# org.apache.log4j.ConsoleAppender(控制台)
# org.apache.log4j.FileAppender(文件)
# org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
# org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
# org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
# 这里CONSOLE输出端是控制台
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender 

# log4j.appender.CONSOLE.layout  -->  定义名为CONSOLE的输出端的layout布局方式是哪种类型,有四个值
# org.apache.log4j.PatternLayout(可以灵活地指定布局模式)【***】
# org.apache.log4j.HTMLLayout(以HTML表格形式布局)
#org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
#org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
# 这里设置为PatternLayout,可以灵活指定布局的模式
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

# log4j.appender.CONSOLE.layout.ConversionPattern
# 使用PatternLayout布局需要指定打印信息的具体格式ConversionPattern,参数:
#   %d 输出日志时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy-MM-dd HH:mm:ss,SSS},输出类似:2020-10-16 17:02:28,968
#   %r 输出自应用启动到输出该log信息耗费的毫秒数
#   %t 输出产生该日志事件的线程名(比如main、gc)
#   %p 输出优先级,即DEBUG,INFO,WARN,ERROR,FATAL等方式
#   %c 输出所属的类目,通常就是所在类的全名;
#   %m 输出代码中指定的消息
#   %M 输出打印该条日志的方法名
#   %n 输出一个回车换行符,Windows平台为"rn”,Unix平台为"n”;

#   %l 输出日志事件的发生位置,及在代码中的行数;
#   [QC]是log信息的开头,可以为任意字符,一般为项目简称。
log4j.appender.CONSOLE.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} %-6r [%t] %-5p %30.30c - %m%n

# 输出消息编码
#log4j.appender.CONSOLE.encoding=UTF-8

# =======================================================================================
# LOGFILE配置 (名称可以自定义) 这里配置日志文件存储(存储到指定路径)

# log4j.appender.LOGFILE 用于定义名为LOGFILE的输出端的类型为每天产生一个日志文件。
log4j.appender.LOGFILE=org.apache.log4j.FileAppender
# log4j.appender.LOGFILE.File 定义名为LOGFILE的输出端的文件名为E:\logFile\SSM\ssm.log(可以自行修改)
log4j.appender.LOGFILE.File=E:\\logFile\\saas-export\\saas-export.log

log4j.appender.LOGFILE.Append=true
# log4j.appender.LOGFILE.layout 输出日志布局设置PatternLayout,和上面的一样
log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout
# log4j.appender.LOGFILE.layout.ConversionPattern 自定义格式输出,和上面一样
log4j.appender.LOGFILE.layout.ConversionPattern=%d{ISO8601} %-6r [t] %-5p %30.30c %x - %m%n


3.2 web.xml配置

加载spring核心配置文件applicationContext-*.xml,配置字符编码过滤器,配置监听器,配置前端控制器进行请求分发

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
  <display-name>Archetype Created Web Application</display-name>

  <!--这些配置是有顺序的 context-param参数,后面是filter过滤器,然后是listener监听器,然后是servlet前端控制器 -->

  <!--1. spring监听器: 读取applicationContext.xml配置文件
      设置spring核心配置文件的路径 applicationContext-tx.xml和applicationContext-dao.xml-->
  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring/applicationContext-*.xml</param-value>
  </context-param>

  <!--  2. 配置字符编码过滤器characterEncodingFilter  解决中文乱码(统一编码) -->
  <filter>
    <filter-name>characterEncodingFilter</filter-name>
    <!-- spring自带编码过滤器 -->
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
      <!-- 读取键值对 key-取名 value-设置的编码 -->
      <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>


  <!--3. 配置Spring的监听器,默认只加载WEB-INF目录下的applicationContext.xml配置文件-->
  <listener>
    <!-- ContextLoaderListener监听器的作用就是启动Web容器时,自动装配applicationContext的配置信息 -->
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>


  <!--4. 配置前端控制器,进行接收请求转发至controller,解决Controller的问题(web层)-->
  <servlet>
    <!-- 前端控制器取名 可以更改,但是要和下面的一样 -->
    <servlet-name>DispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <!--加载springmvc.xml配置文件-->
    <init-param>
      <!-- 整合SpringMVC,需要加载springmvc核心配置文件 -->
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath:spring/springmvc.xml</param-value>
    </init-param>
    <!--数字越大优先级越低, 数字为1,启动服务器,立即创建该servlet -->
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <!-- 要和上面的前端控制器命名相同 -->
    <servlet-name>DispatcherServlet</servlet-name>
    <!-- *.do 表示所有后缀为do的请求 -->
    <!--<url-pattern>*.do</url-pattern>-->
    <!-- /表示拦截所有请求进行请求转发 -->
    <url-pattern>/</url-pattern>
  </servlet-mapping>

</web-app>


3.3 配置springmvc.xml

路径:resources/spring/springmvc.xml,开启注解驱动,配置过滤文件,配置视图解析器,扫描controller。

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!--springmvc是web层(Controller处理请求)  UserController  @Controller -->
    <!--1.扫描Controller所在包-->
    <context:component-scan base-package="com.xgf.web"/>

    <!--2. 配置的视图解析器对象,success  路径/WEB-INF/pages/success.jsp -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--3. 配置文件 - 过滤静态资源  前面的前端控制器拦截所有,静态css、js这些也都拦截
            配置使.js .css img这些静态文件不被拦截,保证静态文件都不拦截
             用过mvc标签进行放行,这些目录下文件都不拦截      -->
    <mvc:resources location="/css/" mapping="/css/**" />
    <mvc:resources location="/img/" mapping="/img/**" />
    <mvc:resources location="/js/" mapping="/js/**" />
    <mvc:resources location="/fonts/" mapping="/fonts/**" />
    <mvc:resources location="/plugins/" mapping="/plugins/**" />

    <!-- 4. 开启注解驱动,开启SpringMVC的注解的支持 @RequestMapping @RequestBody @ResponseBody这些注解需要使用 -->
    <mvc:annotation-driven/>
</beans>

3.4 创建CompanyController进行测试

com/xgf/web/controller/company/CompanyController.java

@Controller
@RequestMapping("/company")
public class CompanyController {
    private static final Logger l = LoggerFactory.getLogger(CompanyController.class);
    @Autowired
    ICompanyService companyService;

    //list.do -> list 前端控制器拦截后缀为.do的文件
    @RequestMapping(path="/list.do",method = RequestMethod.GET)
    public String list(Model model){
        List<Company> list = companyService.findAll();
        //打印重要数据
        l.info("list  list="+list);
        model.addAttribute("list",list);
        return "company/company-list";
    }
}

3.5 创建company-list.jsp来测试数据显示

WEB-INF/pages/company/company-list.jsp

@Controller
@RequestMapping("/company")
public class CompanyController {
    private static final Logger l = LoggerFactory.getLogger(CompanyController.class);
    @Autowired
    ICompanyService companyService;

    //list.do -> list 前端控制器拦截后缀为.do的文件
    @RequestMapping(path="/list.do",method = RequestMethod.GET)
    public String list(Model model){
        List<Company> list = companyService.findAll();
        //打印重要数据
        l.info("list  list="+list);
        model.addAttribute("list",list);
        return "company/company-list";
    }
}

3.5 配置tomcat服务器通过地址访问controller

在这里插入图片描述

3.6 SpringMVC对于日期字符串向后台提交转Date问题

springMVC默认不支持页面上的日期字符串(类似2020-10-14或2020/10/14之类的)到后台的Date的转换。(会报400错误)
jsp页面设置一个接收date数据的input。

<% pageContext.setAttribute("path",request.getContextPath()); %>
<form action="${path}/testDate.do" method="get">
    请选择日期:<input type="date" name="date">
    <br/>
    <input type="submit" value="提交"/>
</form>

后台controller接收数据进行跳转

	@RequestMapping(path="/testDate.do",method = RequestMethod.GET)
    //该参数接收浏览器提交的日期字符
    public String testDate(Date date, Model model){
        System.out.println("testDate date="+date);
        model.addAttribute("date",date);
        return "stringToDateConverter";
    }

运行结果400错误
在这里插入图片描述

3.7 配置自定义日期类型转换器实现Converter接口

export_web_manager/com/xgf/web/controller/TestStringToDateConverter

import org.springframework.core.convert.converter.Converter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;

 /*自定义类型参数转换器: 将字符串日期格式转成Date类型的数据.
      Converter<S,T>  S: 代表的是源,将要转换的数据类型  T:目标类型,将会转成什么数据类型
 */
 //日期格式转换器
public class DateFormatConverter implements Converter<String,Date>{
  //转换方法
  //String source 将会传递过来的日期的字符串
  public Date convert(String source) {
   //参数填写为你想要转换的数据格式
​    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");try {
​      Date date = sdf.parse(source);return date;} catch (ParseException e) {
​      e.printStackTrace();}return null;
  }

3.8 在springmvc.xml中配置转换工厂,并将转换器放入注解驱动中,并测试转换情况

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!--springmvc是web层(Controller处理请求)  UserController  @Controller -->
    <!--1.扫描Controller所在包-->
    <context:component-scan base-package="com.xgf.web"/>

    <!--2. 配置的视图解析器对象,success  路径/WEB-INF/pages/success.jsp -->
    <bean id="internalResourceViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/pages/"/>
        <property name="suffix" value=".jsp"/>
    </bean>

    <!--3. 配置文件 - 过滤静态资源  前面的前端控制器拦截所有,静态css、js这些也都拦截
            配置使.js .css img这些静态文件不被拦截,保证静态文件都不拦截
             用过mvc标签进行放行,这些目录下文件都不拦截      -->
    <mvc:resources location="/css/" mapping="/css/**" />
    <mvc:resources location="/img/" mapping="/img/**" />
    <mvc:resources location="/js/" mapping="/js/**" />
    <mvc:resources location="/fonts/" mapping="/fonts/**" />
    <mvc:resources location="/plugins/" mapping="/plugins/**" />

    <!-- 4. 开启注解驱动,开启SpringMVC的注解的支持 @RequestMapping @RequestBody @ResponseBody这些注解需要使用 -->
    <mvc:annotation-driven/>

    <!-- 5. 配置类型转换器  -->
    <!-- 创建类型转换器对象 -->
    <bean id="stringToDateConverter" class="com.xgf.web.converter.StringToDateConverter"/>
    <!-- 把转换器对象放入SpringMVC转换器工厂中 -->
    <bean id="conversionServiceFactory" class="org.springframework.context.support.ConversionServiceFactoryBean">
        <property name="converters">
            <set>
                <!-- 引入日期转换器对象(上面创建的) -->
                <ref bean="stringToDateConverter"/>
                <!-- 或者直接将转换器类写到这里面 -->
                <!--<bean id="stringToDateConverter" class="com.xgf.web.converter.StringToDateConverter"/>-->
            </set>
        </property>
    </bean>

    <!--6. 把转换器工厂放入到注解驱动,转换器才会生效 -->
    <mvc:annotation-driven conversion-service="conversionServiceFactory" />

</beans>

注意事项【*

上述代码中的<mvc:annotation-driven conversion-service=“conversionServiceFactory” />一定要放到springmvc的注解驱动mvc:annotation-driven/后面,不然就会报400错误。(你都没有开启注解驱动,怎么放进去呢?)

运行结果(转换成功)
在这里插入图片描述

3.9 配置统一异常处理器(spring-mvc中配置统一异常处理器)

配置自己的异常处理类实现HandlerExceptionResolver 接口
export_web_manager/src/main/java/com/xgf/web/exceptions/MyExceptionResolver.java

//1. 实现接口
public class MyExceptionResolver implements HandlerExceptionResolver {
    @Override
    public ModelAndView resolveException(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) {
        //Exception e 表示由程序抛出来的异常
        //返回值 为什么是 ModelAndView?  添加数据 再将数据显示在指定页面
        ModelAndView mv = new ModelAndView();
        mv.addObject("exception",e.getMessage());//添加异常信息
        mv.setViewName("error");//指定一个显示错误的美观页面
        return mv;
    }
}

将MyExceptionResolver配置到springmvc.xml中注册我们自己的统一异常处理类。

    <!-- spring-mvc注册我们的统一异常处理类 -->
    <bean id="myExceptionResolver" class="com.xgf.web.exceptions.MyExceptionResolver"/>

写一个错误接收页面error.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java"  isELIgnored="false" %>
<html>
<head>
    <title>系统出错页面</title>
</head>
<body>
不好意思,我们已在拼抢抢修中 :${exception}
</body>
</html>

创建测试类测试统一异常处理是否生效

@Controller
public class TestException {
    private static final Logger l = LoggerFactory.getLogger(CompanyController.class);

    //测试统一异常处理类
    @RequestMapping(path="/testException.do",method = RequestMethod.GET)
    public String testDate(Date date){
        System.out.println();
        l.info("testDate date="+date);
        int num = 1/0;	//抛出异常
        return "result";
    }
}

访问testException.do抛出异常跳转我们自己的异常处理页面
在这里插入图片描述

SSM环境搭建成功了

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值