Java web 之 Spring+Mybatis+Spring MVC框架整合(中)

xiaoxiao2021-02-28  153

我们接着上一篇讲,上一篇,我们已经成功搭建了我们的POM聚合Maven工程,其中ssm-web-test为Maven Module,项目类型为war;我们也成功运行了项目,我们再次看一下整个项目的目录结构:

1、在 src/main/java下创建5个包

com.appleyk.controller(spring mvc 控制器类)

com.appleyk.pojo  (对应数据结构的表,pojos对象,本项目来自于myb逆向工程)

com.appleyk.mapper(接口类和接口类映射的XML文件 本项目来自于mybatis逆向工程)

com.appleyk.service(我们自己定义的接口类)

com.appleyk.service.serviceImpl(自定义接口的 实现类)

2、在src/main/resources创建三个文件夹:

spring-mybatis(里面存放spring+mybatis的整合XML,spring-mybatis.xml

properties(里面放属性文件,这里我们放mysql的数据连接配置,mysql.properties)

springMVC(放Spring MVC配置XML,Spring-MVC.xml)

我们先配置mysql.properties属性文件的内容:

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8 jdbc.username=root jdbc.password=

我们接着整合Spring和Mybatis的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:p="http://www.springframework.org/schema/p" 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:mvc="http://www.springframework.org/schema/mvc" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd"> <!-- 加载配置文件 --> <context:property-placeholder location="classpath:properties/*.properties" /> <!-- 数据库连接池 --> <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="driverClassName" value="${jdbc.driver}" /> <property name="maxActive" value="10" /> <property name="minIdle" value="5" /> </bean> <!-- 让spring管理sqlsessionfactory 使用mybatis和spring整合包中的 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <!-- 数据库连接池 name 等于 上面的 bean id=‘dataSource’ --> <property name="dataSource" ref="dataSource" /> </bean> <!-- 添加mapper spring bean 组件 后面可以根据spring 上下文对象 getBean获得这个mapper接口中的类实例 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.appleyk.mapper" /> </bean> <!-- 事务管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <!-- 数据源 --> <property name="dataSource" ref="dataSource" /> </bean> <!-- 包扫描器,扫描带@Service注解的类 --> <context:component-scan base-package="com.appleyk.service"></context:component-scan> </beans>

3、我们先不急着配置Spring MVC,看下目前我们的项目结构目录:

ok,接下来,我们进行验证,Spring+Mybatis框架是整合了,但是整合后的项目是否能够运行,运行的效果怎么样,目前我们还看不出来,因为,我们的web项目中暂且只是一些配置文件,并没有实质上的接口、类和对象。

我们测试,肯定是要数据的,数据从哪来呢?肯定是从我们的mysql数据库来,但是这个构建pojo和接口实现的过程,我们要自己来吗?

当然不是,这里,我们通过Mybatis的逆向工程帮助我们实现数据库记录的映射。

逆向工程一般都是写好的Java Project,引入几个必须的jar包,然后在配置一下generatorConfig.xml文件(配置是关键),最后执行一下GeneratorSqlmap类即可生成pojos和mapper,其他基本不用改什么,很方便:

4、我们在项目中,import导入一个已经存在的项目到当前的工作空间中:

导入成功后,我们的逆向工程项目generatorSqlmapCustom文件目录结构图如下:

最关键的一个是jar包,就那几个,一个是generatorConfig.xml,一个是默认包下的GeneratorSqlmap.java,还有一个日志单元的属性文件(基本上不用再自己写demo):

generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"> <generatorConfiguration> <context id="testTables" targetRuntime="MyBatis3"> <commentGenerator> <!-- 是否去除自动生成的注释 true:是 : false:否 --> <property name="suppressAllComments" value="true" /> </commentGenerator> <!--数据库连接的信息:驱动类、连接地址、用户名、密码 --> <jdbcConnection driverClass="com.mysql.jdbc.Driver" connectionURL="jdbc:mysql://localhost:3306/test" userId="root" password=""> </jdbcConnection> <!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 和 NUMERIC 类型解析为java.math.BigDecimal --> <javaTypeResolver> <property name="forceBigDecimals" value="false" /> </javaTypeResolver> <!-- targetProject:生成PO类的位置 --> <javaModelGenerator targetPackage="com.appleyk.pojo" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> <!-- 从数据库返回的值被清理前后的空格 --> <property name="trimStrings" value="true" /> </javaModelGenerator> <!-- targetProject:mapper映射文件xml生成的位置 --> <sqlMapGenerator targetPackage="com.appleyk.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </sqlMapGenerator> <!-- targetPackage:mapper接口生成的位置 --> <javaClientGenerator type="XMLMAPPER" targetPackage="com.appleyk.mapper" targetProject=".\src"> <!-- enableSubPackages:是否让schema作为包的后缀 --> <property name="enableSubPackages" value="false" /> </javaClientGenerator> <!-- 指定逆向数据库表 --> <table schema="" tableName="user"></table> </context> </generatorConfiguration>

log4j.properties:

og4j.rootLogger=DEBUG, Console #Console log4j.appender.Console=org.apache.log4j.ConsoleAppender log4j.appender.Console.layout=org.apache.log4j.PatternLayout log4j.appender.Console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n log4j.logger.java.sql.ResultSet=INFO log4j.logger.org.apache=INFO log4j.logger.java.sql.Connection=DEBUG log4j.logger.java.sql.Statement=DEBUG log4j.logger.java.sql.PreparedStatement=DEBUG

GeneratorSqlmap.java:

import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import org.mybatis.generator.api.MyBatisGenerator; import org.mybatis.generator.config.Configuration; import org.mybatis.generator.config.xml.ConfigurationParser; import org.mybatis.generator.exception.XMLParserException; import org.mybatis.generator.internal.DefaultShellCallback; public class GeneratorSqlmap { public void generator() throws Exception{ List<String> warnings = new ArrayList<String>(); boolean overwrite = true; File configFile = new File("generatorConfig.xml"); ConfigurationParser cp = new ConfigurationParser(warnings); Configuration config = cp.parseConfiguration(configFile); DefaultShellCallback callback = new DefaultShellCallback(overwrite); MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings); myBatisGenerator.generate(null); } public static void main(String[] args) throws Exception { try { GeneratorSqlmap generatorSqlmap = new GeneratorSqlmap(); generatorSqlmap.generator(); } catch (Exception e) { e.printStackTrace(); } } }

.xml文件里面的这几个地方需要注意:

我们执行一下GeneratorSqlmap类的Main方法:

让我们的类根据xml配置文件去生成相应的包:

这时候我们在项目上刷新后发现多了两个包,正是我们xml里面配置,同时,也是我们ssm-web-test项目中需要的两个包:

至此,我们Mybatis逆向工程部分结束,下面我们继续。

5、将上述两个package,copy(覆盖)到ssm-web-test指定位置下:

展开com.appleyk.mapper包,如下:

定义一个接口:

UserService.java:

package com.appleyk.service; import com.appleyk.pojo.User; public interface UserService { public User getUserById(int userID); }

定义了接口,我们还差一个实现,因此,我们需要在Impl包下创建一个对应的实现接口的类:

UserServiceImpl.java:

package com.appleyk.service.Impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import com.appleyk.mapper.UserMapper; import com.appleyk.pojo.User; import com.appleyk.service.UserService; /** * * @author appleyk * 2017-8-31 13:45:00 * @Service("userService")注解是告诉Spring,当Spring要创建UserServiceImpl的的实例时, bean的名字必须叫做"userService",这样当Action需要使用UserServiceImpl的的实例时, 就可以由Spring创建好的"userService",然后注入给Action: 在Action只需要声明一个名字叫“userService”的变量来接收由Spring注入的"userService"即可, [我们也可以用xml标准来配置bean] 具体代码如下: // 注入userService @Resource(name = "userService") private UserService userService; */ @Service("userService") public class UserServiceImpl implements UserService{ @Autowired //@Autowired 注释 :对类成员变量、方法及构造函数进行标注,完成自动装配的工作 private UserMapper uMapper = null ; @Override public User getUserById(int userID) { User user = uMapper.selectByPrimaryKey(userID);//通过主键返回user return user; } } ok,到这里,我们基本上算是完成了service层和dao层的工作了,我们屡一下思路:

(1)定义一个接口,接口定义一个方法,方法根据userID返回一个User

(2)实现接口,利用注解,帮助我们完成工作(@service注解下面会说到,怎么用)

(3)如何使用?如何测试?

我们前面说过,我们所有的测试工作都放在src/test/java下面,因此,我们新建一个测试类,UserTest:

UserTest.java

import javax.annotation.Resource; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.appleyk.pojo.User; import com.appleyk.service.UserService; public class UserTest { //1、 拿到spring上下文对象 private ApplicationContext aContext = null ; @Resource(name = "userService") private UserService userService ; @Test public void Test() throws Exception{ try{ aContext = new ClassPathXmlApplicationContext("classpath:spring-mybatis/spring-mybatis.xml"); userService = (UserService)aContext.getBean("userService"); User user = userService.getUserById(1); System.out.println(user); } catch(Exception ex){ ex.printStackTrace(); } } } 有几个地方需要说明一下,如下图:

一切就绪后,我们现在只差运行这个test,看看是不是有数据返回,如果成功返回,证明我们的Spring+Mybatis整合成功,如果失败,说明,我们还有一些工作要做,我们右键run as JUnit Test,运行结果如下:

我们稍作调整,因为user是一个pojo对象,因此,里面包含了各个属性,使用如下:

我们也可采用下面的方式,直接获得UserMapper的代理实例,通过实例我们实现无条件查询,返回所有数据,因此,我们修改下UserTest类:

import java.util.List; import javax.annotation.Resource; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.alibaba.druid.sql.ast.expr.SQLCaseExpr.Item; import com.appleyk.mapper.UserMapper; import com.appleyk.pojo.User; import com.appleyk.pojo.UserExample; import com.appleyk.service.UserService; public class UserTest { //1、 拿到spring上下文对象 private ApplicationContext aContext = null ;//1、 拿到spring上下文对象 //@Resource(name = "userService") //private UserService userService ; @Test public void Test() throws Exception{ try{ aContext = new ClassPathXmlApplicationContext("classpath:spring-mybatis/spring-mybatis.xml"); // 第一种方法,使用java反射机制获得实现UserService接口的实例 // userService = (UserService)aContext.getBean("userService"); // User user = userService.getUserById(1); // System.out.println(user.getId().toString()+','+user.getName()+',' // +user.getAge().toString()+','+user.getPassword()); //第二种方法,我们使用spring上下文获得UserMapper代理实例 实现无条件查询 UserMapper uMapper = null; uMapper = aContext.getBean(UserMapper.class);//拿到uMapper的代理 UserExample example = new UserExample(); List<User> list = uMapper.selectByExample(example); if(list!=null & list.size()>0){ int i = 0; for(User item : list){ System.out.println(item.getName()+","+item.getEmail()+(i+1)); i++; //输出表中所有结果,如果表里面的数据太大,我们还可以使用Mybatis的分页插件PageHelper } } } catch(Exception ex){ ex.printStackTrace(); } } } 我们执行一下我们的上述测试类如下:

我们对比一下我们的 mysql数据库里面的记录数:

到这里,关于Spring+Mybatis的整合就算完成了,回顾一下,我们简单的配置了一下我们的整合XML(spring 一部分,Mybatis一部分),使用了Mybatis逆向工程生成pojos和mapper,我们自己定义了接口和接口的实现类,实现类中我们使用了spring注解方式,事实,证明这种注解方式很方便,因为,我们在JUnit Test中测试了一下,而且成功返回了我们的预期,接下来,我们会讲spring MVC框架的配置,我们发现,到目前为止,我们整个项目的web.xml里面,并没有写任何内容:

我们也依然可以在Tomcat上运行我们现有的框架:

小插曲:

如果出现上述错误,请将你当前项目引用Java环境 从JRE改成JDK:

然后,我们重新运行下整个项目:

浏览器,输入http://localhost:8080:

折腾一圈,我们又绕回来了,我们的项目,没有被折腾坏,O(∩_∩)O

这个时候,如果还要执行一下JUnit测试会是什么样的效果呢?这里,我要讲一个很有意思的地方:

我们测试之后,紧接着运行了Maven Clean重新运行了项目,我们返回来再来看一下,我们的测试demo是否还起作用:

原因就在于,我们重新运行整个项目的时候,Maven Clean会将编译好的class文件清理掉,但是maven会自动帮我们再编译一遍,所以项目又可以正常运行,也许Maven不顾及放在test下面的class文件,觉得它们是测试编译的,所以就不上心,因此,重启Maven项目的时候,我们测试时候编译的好的class不仅已经被清除掉了,而且也不会自动再次编译,因此最终,我们再次运行JUnit的时候,提示我们找不到UserTest class 。

下面是正常情况下项目中编译好的UserTest.class:

我们看一下,重新运行项目后的ssm-web-test/target下面少了哪些文件夹:

怎么办,我们的项目是运行起来了,可我们还想测试啊? 

这里提供一个解决方案,将整个project clean掉,然后我们观察效果:

点击ok后,我们观察一下ssm-web-test\target下面的文件夹,有哪些文件夹新增了:

此时,我们的控制台输出还停留在:

既然我们找回了UserTest.class(虽然每次运行测试的时候,都要project clean一次,有点麻烦,不过,测试本来就是服务的,存在感比较低),我们更加有底气了,so,让我们再来一次Test吧:

由于篇幅限制,本篇结束!下一篇我们继续,该讲我们 Spring MVC的配置了。

转载请注明原文地址: https://www.6miu.com/read-24746.html

最新回复(0)