【SaaS-Export项目】 - 03 SSM整合到每个子工程中,多模块工程整合SSM,export

it2026-04-23  5

文章目录

数据库准备1. dao层Spring整合MyBatis进行数据库访问(export_dao子工程)1.1 需要spring和mybatis的整合包(前面已经导入了)1.2 export_dao下创建属性文件(连接数据库c3p0连接池)1.3 export_dao子工程下创建applicationContext-dao.xml1.4 测试能否自动装载,能否查询到数据库 2. service依赖dao,测试读取dao的信息,配置事务管理(export_system_service子工程)2.1 关于classpath路径读取的使用2.2 创建测试类`TestCompanyService`2.3 创建Service接口及其实现类2.4 在export_system_service子工程创建spring事务管理2.5 测试运行如果出现异常情况,参考下面几种情况 3. Spring整合SpringMVC(export_web_manager子工程)3.1 创建log4j.properties日志属性文件3.2 web.xml配置3.3 配置springmvc.xml3.4 创建CompanyController进行测试3.5 创建company-list.jsp来测试数据显示3.5 配置tomcat服务器通过地址访问controller3.6 SpringMVC对于日期字符串向后台提交转Date问题3.7 配置自定义日期类型转换器实现Converter接口3.8 在springmvc.xml中配置转换工厂,并将转换器放入注解驱动中,并测试转换情况3.9 配置统一异常处理器(spring-mvc中配置统一异常处理器)

数据库准备

需要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 测试运行

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

如果出现applicationContext异常

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

@ContextConfiguration("classpath*:spring/applicationContext-*.xml") 如果出现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> 如果出现自己写的类找不到异常

需要在每个工程的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环境搭建成功了

最新回复(0)