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

我们接着上一篇讲,上一篇,我们已经成功搭建了我们的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的配置了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值