Valid XHTML 1.0 Transitional集成演练路线图 (P13)

Page: [index.html] (v2017-03-01_19-30)

  1. 项目基础:……
  2. Servlet :……
  3. Spring Web MVC :
    1. 基本 Web 应用:……
    2. CRUD :
      1. Spring Web MVC + DataSource + 基本 JDBC :……
      2. Spring Web MVC + DataSource + Spring JDBC Template :……
      3. Spring Web MVC + DataSource + MyBatis :
        1. 方式 - 人工编写 DAO 实现类:……
        2. 方式 - 自动代理 DAO 实现类:
          • 样例 - 用户管理:
            1. 环境准备:
              修改 pom.xml ,添加需要的库 (并由 Eclipse 的 Maven 插件自动下载、导入) ,以使用 org.mybatis.spring.mapper.MapperScannerConfigurer 类:
              <project ……>
              	……
              	<dependencies>
              		……
              		<dependency>
              			<!-- [MyBatis 3] and [Spring 3] advanced integration. -->
              			<groupId>org.Mybatis</groupId>
              			<artifactId>mybatis-spring</artifactId>
              			<version>1.2.2</version>
              		</dependency>
              	</dependencies>
              </project>
              

              说明 / 注意事项:
              • 目前通过 Maven 引入的库有:
                aopalliance-1.0.jar
                commons-codec-1.10.0.jar
                commons-codec-1.10.jar
                commons-dbcp-1.4.jar
                commons-logging-1.1.3.jar
                commons-pool-1.5.4.jar
                hamcrest-core-1.3.jar
                junit-4.12.jar
                mybatis-3.2.8.jar
                mybatis-spring-1.2.2.jar
                ojdbc5-11.2.0.4.jar
                spring-aop-3.2.8.RELEASE.jar
                spring-beans-3.2.8.RELEASE.jar
                spring-context-3.2.8.RELEASE.jar
                spring-core-3.2.8.RELEASE.jar
                spring-expression-3.2.8.RELEASE.jar
                spring-jdbc-3.2.8.RELEASE.jar
                spring-tx-3.2.8.RELEASE.jar
                spring-web-3.2.8.RELEASE.jar
                spring-webmvc-3.2.8.RELEASE.jar
            2. 样例编写:
              1. 实体类:
                沿用“基本 JDBC CRUD”样例既有的实体类 tfw.integration_demo._04_spring_web_mvc._02_crud._01_basic_jdbc_crud.entity.User
              2. DAO 层:
                1. 映射器:
                  1. 编写映射器接口 tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao.I_UserDAO
                    ……
                    public interface I_UserDAO extends
                    		tfw.integration_demo._04_spring_web_mvc._02_crud._01_basic_jdbc_crud.dao.I_UserDAO
                    {
                    
                    	……
                    	List<User> listByRange(@Param("start_row_index") int intStartRowIdx,
                    			@Param("select_row_count") int intSelectRowCount)
                    			throws SQLException;
                    
                    }
                    

                    说明 / 注意事项:
                    1. I_UserDAO extends tfw.……._01_basic_jdbc_crud.dao.I_UserDAO”:
                      所有功能都已在 tfw.……._01_basic_jdbc_crud.dao.I_UserDAO 中声明;
                      但部分方法的参数前需要另行添加 MyBatis 注解,所以做一道继承。
                    2. List<User> listByRange(@Param("start_row_index") ……, @Param("select_row_count") ……) ……”:
                      每个数据操作方法必须令参数能正确地传入 MyBatis ;
                      这个这个接口已经被多个类实现,如果将此方法修改为接收“java.util.Map”型参数,涉及的改动量过大;
                      如果不修改而直接沿用此方法,则需要有序、互相区分地向 MyBatis 传入不止一个参数;
                      添加在方法参数前的 MyBatis 注解“@Param{……}”提供了这种支持;
                      start_row_index”和“select_row_count”即为参数在 MyBatis 映射文件中的名字。
                  2. 编写 MyBatis 映射文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/_02_auto_dao_way/dao/impl/oracle/User.mybatis_mapping.xml
                    <?xml version="1.0" encoding="UTF-8" ?>
                    <!DOCTYPE mapper PUBLIC "-//ibatis.apache.org//DTD Mapper 3.0//EN"
                    		"http://ibatis.apache.org/dtd/ibatis-3-mapper.dtd">
                    <mapper namespace="tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao.I_UserDAO">
                    	<!--
                    	<insert id=""/>
                    	……
                    	<delete id=""/>
                    	-->
                    
                    	<insert id="create"
                    			……>
                    		……
                    	</insert>
                    	……
                    	<select id="listByRange" ……
                    			……>
                    		select ……
                    		from (
                    			select rownum rn, t.*
                    			from (
                    				……
                    			) t
                    			where rownum&lt;=(#{start_row_index}+#{select_row_count})
                    		)
                    		where rn&gt;=(#{start_row_index}+1)
                    	</select>
                    	……
                    </mapper>
                    

                    说明 / 注意事项:
                    1. 文件路径:
                      映射文件只要能被 MyBatis 找到,即可;映射文件的路径和映射器接口的路径没有任何关系
                      在本样例中两者路径相似、相关,仅为项目结构上便于查找、管理。
                    2. namespace="tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao.I_UserDAO"”:
                      基本上完全沿用“src/main/resources/tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/_01_manual_dao_way/dao/impl/oracle/User.mybatis_mapping.xml”,但将“namespace="……"”属性的值改为前述映射器接口。
                    3. #{start_row_index}”、“#{select_row_count}”:
                      传入的参数,名称必须和映射器接口的“@Param{……}”中的名称一致。
                  3. 修改 MyBatis 主配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/mybatis-config.xml ,在“mappers”节点下添加此映射文件:
                    <?xml version="1.0" encoding="UTF-8" ?>
                    <!DOCTYPE ……>
                    <configuration>
                    	<!-- Connection and transaction parameters: -->
                    	<environments ……>
                    		……
                    	</environments>
                    
                    	<!-- Mappers: -->
                    	<mappers>
                    		<!--
                    		<mapper resource=".../.../XXXMapping.xml"/>
                    		<mapper resource=".../.../YYYMapping.xml"/>
                    		-->
                    		<mapper resource="tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/_01_manual_dao_way/dao/impl/oracle/User.mybatis_mapping.xml"/>
                    		<mapper resource="tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/_02_auto_dao_way/dao/impl/oracle/User.mybatis_mapping.xml"/>
                    	</mappers>
                    </configuration>
                    

                  4. 编写测试用例 tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.user_mgr_testcase._01_MyBatisDAO ,测试 DAO 的生成过程及各种功能:
                    ……
                    public class _01_MyBatisDAO
                    {
                    
                    	private String strClasspathConfFile =
                    			"tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/mybatis-config.xml";
                    
                    	private SqlSession session;
                    
                    	private I_UserDAO userDAO;
                    
                    	@Test
                    	public void testObjects() throws IOException
                    	{
                    		SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
                    		System.out.println("SqlSessionFactoryBuilder:\n\t" + ssfb);
                    
                    		System.out.println("Configuration File:\n\t" + strClasspathConfFile);
                    		InputStream isMyBatisCfg =
                    				ClasspathFileToolT.getURLInputStream(strClasspathConfFile);
                    		System.out.println("Configuration InputStream:\n\t" + isMyBatisCfg);
                    
                    		SqlSessionFactory ssf = ssfb.build(isMyBatisCfg);
                    		System.out.println("SqlSessionFactory:\n\t" + ssf);
                    		isMyBatisCfg.close();
                    		System.out.println(
                    				"Configuration InputStream Closed:\n\t" + isMyBatisCfg);
                    
                    		SqlSession session = ssf.openSession();
                    		System.out.println("SqlSession:\n\t" + session);
                    
                    		I_UserDAO userDAO = session.getMapper(
                    				tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao.I_UserDAO.class);
                    		System.out.println("DAO:\n\t" + userDAO);
                    
                    		session.close();
                    		System.out.println("SqlSession Closed:\n\t" + session);
                    	}
                    
                    	@Before
                    	public void init() throws IOException
                    	{
                    		……
                    		System.out.println(
                    				"Configuration InputStream Closed:\n\t" + isMyBatisCfg);
                    
                    		session = ssf.openSession();
                    		System.out.println("SqlSession:\n\t" + session);
                    
                    		userDAO = session.getMapper(
                    				tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao.I_UserDAO.class);
                    		System.out.println("DAO:\n\t" + userDAO);
                    	}
                    
                    	@After
                    	public void close()
                    	{
                    		session.close();
                    		System.out.println("SqlSession Closed:\n\t" + session);
                    	}
                    
                    	@Test
                    	public void testUserDAO_create() throws SQLException
                    	{
                    		……
                    	}
                    
                    	……
                    }
                    

                    说明 / 注意事项:
                    1. userDAO = session.getMapper(…….I_XXXDAO.class);”:
                      1. 本样例不再采用“new XXXDAO(...);”的方式生成 DAO ,改由“session.getMapper(…….I_XXXDAO.class);”方式以反射、代理技术自动生成,无需再人工编写其实现类“XXXDAO
                        MyBatis 加载主配置文件时一并加载映射文件,建立映射文件和其中记录的映射器接口间的匹配关系
                      2. tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao.I_UserDAO.class”:
                        易错点,必须使用MyBatis 映射文件中指定的类;
                        由于和上级接口的类名相同,没法同时 import ,所以在此使用完整的类名。
                    2. 经试验,实际生成的 DAO 的类型为“org.apache.ibatis.binding.MapperProxy”。
                2. Spring-MyBatis 集成组件介入:
                  本样例中,DAO 已可自动生成,但对于 Spring 来说是不可控、不可用的;
                  必须引入 Spring-MyBatis 集成组件,用其提供的“映射扫描配置器”从指定的包下扫描映射器接口,根据接口的类名或注解将 DAO 注册到 ApplicationContext 中。
                  1. 基本介入:
                    1. 修改 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/04_mybatis_crud.xml ,注册“映射扫描配置器”对象:
                      <?xml version="1.0" encoding="UTF-8"?>
                      <beans ……>
                      	……
                      
                      	<bean id="crud.mybatis.manual_dao.ssf"
                      			……>
                      		……
                      	</bean>
                      
                      	……
                      
                      	<bean id="crud.mybatis.urlMapping"
                      			……>
                      		……
                      	</bean>
                      
                      	<!-- [########################################] -->
                      
                      	<bean id="crud.mybatis.auto_dao.msc"
                      			class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                      		<property name="sqlSessionFactory" ref="crud.mybatis.manual_dao.ssf"/>
                      		<property name="basePackage"
                      				value="tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao"/>
                      	</bean>
                      </beans>
                      

                      说明 / 注意事项:
                      1. <property name="sqlSessionFactory" ……"/>”:
                        指定 SqlSessionFactory 对象;如果 ApplicationContext 中只有一个 SqlSessionFactory 则无需指定,但考虑后续有可能添加更多的 SqlSessionFactory ,所以在此指定。
                      2. <property name="basePackage" ……/>”:
                        指定扫描范围,递归扫描 tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao 包。
                    2. 修改映射器接口 tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao.I_UserDAO ,添加注解:
                      ……
                      
                      /**
                       * Either "@Component(...)" or "@Repository(...)" is OK!<br />
                       * 
                       * @…… ……
                       */
                      // @Component("crud.mybatis.auto_dao.userDAO")
                      @Repository("crud.mybatis.auto_dao.userDAO")
                      public interface I_UserDAO extends
                      		tfw.integration_demo._04_spring_web_mvc._02_crud._01_basic_jdbc_crud.dao.I_UserDAO
                      {
                      
                      	……
                      
                      }
                      

                      说明 / 注意事项:
                      • @Component("……")” / “@Repository("……")”:
                        指定 DAO 在 ApplicationContext 中的 ID ,如果不用注解指定,ID 会是首字母小写的类名“i_UserDAO”;
                        对于程序运行来说,这两个注解没有明显区别,但“@Repository("……")”在字面上含有“数据来源”之意,用此注解令程序的可读性略有提高。
                    3. 编写测试用例 tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.user_mgr_testcase._02_MyBatisDAO_with_Spring ,逐步将各对象改为从 ApplicationContext 中获取,并在此过程中测试 DAO 的获取步骤及功能:
                      ……
                      public class _02_MyBatisDAO_with_Spring extends A_UserMgrTestCaseBase
                      {
                      
                      	private String strSpringClasspathConfFile =
                      			"tfw/integration_demo/_04_spring_web_mvc/applicationContext.xml";
                      
                      	private AbstractApplicationContext actxt;
                      
                      	private String strMyBatisClasspathConfFile =
                      			"tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/mybatis-config.xml";
                      
                      	// private SqlSession session;
                      
                      	private I_UserDAO userDAO;
                      
                      	@Test
                      	public void testObjects() throws IOException
                      	{
                      		……
                      
                      		System.out.println("MyBatis Configuration File:\n\t"
                      				+ strMyBatisClasspathConfFile);
                      		InputStream isMyBatisCfg = ClasspathFileToolT
                      				.getURLInputStream(strMyBatisClasspathConfFile);
                      		System.out.println(
                      				"MyBatis Configuration InputStream:\n\t" + isMyBatisCfg);
                      
                      		……
                      	}
                      
                      	@Test
                      	public void testObjects2() throws IOException
                      	{
                      		System.out.println(
                      				"Spring Configuration File:\n\t" + strSpringClasspathConfFile);
                      
                      		AbstractApplicationContext actxt =
                      				new ClassPathXmlApplicationContext(strSpringClasspathConfFile);
                      		System.out.println("Application Context:\n\t" + actxt);
                      
                      		// SqlSessionFactoryBuilder ssfb = new SqlSessionFactoryBuilder();
                      		SqlSessionFactoryBuilder ssfb = actxt.getBean(
                      				"crud.mybatis.manual_dao.ssfb", SqlSessionFactoryBuilder.class);
                      		System.out.println("SqlSessionFactoryBuilder:\n\t" + ssfb);
                      
                      		// System.out.println("MyBatis Configuration File:\n\t"
                      		// + strMyBatisClasspathConfFile);
                      		// InputStream isMyBatisCfg = ClasspathFileToolT
                      		// .getURLInputStream(strMyBatisClasspathConfFile);
                      		InputStream isMyBatisCfg = actxt.getBean(
                      				"crud.mybatis.manual_dao.mybatis_cfg_is", InputStream.class);
                      		System.out.println(
                      				"MyBatis Configuration InputStream:\n\t" + isMyBatisCfg);
                      
                      		// SqlSessionFactory ssf = ssfb.build(isMyBatisCfg);
                      		SqlSessionFactory ssf = actxt.getBean("crud.mybatis.manual_dao.ssf",
                      				SqlSessionFactory.class);
                      		System.out.println("SqlSessionFactory:\n\t" + ssf);
                      		isMyBatisCfg.close();
                      		System.out.println(
                      				"MyBatis Configuration InputStream Closed:\n\t" + isMyBatisCfg);
                      
                      		// SqlSession session = ssf.openSession();
                      		// System.out.println("SqlSession:\n\t" + session);
                      		//
                      		// I_UserDAO userDAO = session.getMapper(I_UserDAO.class);
                      		I_UserDAO userDAO =
                      				actxt.getBean("crud.mybatis.auto_dao.userDAO", I_UserDAO.class);
                      		System.out.println("DAO:\n\t" + userDAO);
                      
                      		// session.close();
                      		// System.out.println("SqlSession Closed:\n\t" + session);
                      
                      		actxt.close();
                      		System.out.println("Application Context Closed:\n\t" + actxt);
                      	}
                      
                      	@Before
                      	public void init() // throws IOException
                      	{
                      		System.out.println(
                      				"Spring Configuration File:\n\t" + strSpringClasspathConfFile);
                      
                      		actxt = new ClassPathXmlApplicationContext(strSpringClasspathConfFile);
                      		System.out.println("Application Context:\n\t" + actxt);
                      
                      		userDAO =
                      				actxt.getBean("crud.mybatis.auto_dao.userDAO", I_UserDAO.class);
                      		System.out.println("DAO:\n\t" + userDAO);
                      	}
                      
                      	@After
                      	public void close()
                      	{
                      		// session.close();
                      		// System.out.println("SqlSession Closed:\n\t" + actxt);
                      
                      		actxt.close();
                      		System.out.println("Application Context Closed:\n\t" + actxt);
                      	}
                      
                      	@Test
                      	public void testUserDAO_create() throws SQLException
                      	{
                      		……
                      	}
                      
                      	……
                      
                      }
                      

                  2. 进阶介入:
                    MyBatis-Spring 集成组件提供了更强大的 SqlSessionFactory ,无需在 ApplicationContext 中注册过多初级对象,且可直接使用 ApplicationContext 中已注册的数据源,在 Spring 环境中使用更方便
                    1. 修改 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/04_mybatis_crud.xml ,注册新型 SqlSessionFactory 对象,并以此替换“映射扫描配置器”中原本使用的 SqlSessionFactory 对象
                      <?xml version="1.0" encoding="UTF-8"?>
                      <beans ……>
                      
                      	……
                      
                      	<bean id="crud.mybatis.urlMapping"
                      			……>
                      		……
                      	</bean>
                      
                      	<!-- [########################################] -->
                      
                      	<bean id="crud.mybatis.auto_dao.msc"
                      			class="org.mybatis.spring.mapper.MapperScannerConfigurer">
                      		<!--
                      		<property name="sqlSessionFactory" ref="crud.mybatis.manual_dao.ssf"/>
                      		-->
                      		<property name="sqlSessionFactory" ref="crud.mybatis.auto_dao.ssf"/>
                      		<property name="basePackage"
                      				value="tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.dao"/>
                      	</bean>
                      
                      	<bean id="crud.mybatis.auto_dao.ssf"
                      			class="org.mybatis.spring.SqlSessionFactoryBean">
                      		<property name="dataSource" ref="ds"/>
                      		<property name="mapperLocations"
                      				value="classpath:tfw/integration_demo/_04_spring_web_mvc/_02_crud/_03_mybatis_crud/_02_auto_dao_way/dao/impl/oracle/User.mybatis_mapping.xml"/>
                      	</bean>
                      </beans>
                      

                      说明 / 注意事项:
                      1. <bean id="crud.mybatis.auto_dao.ssf" class="org.mybatis.spring.SqlSessionFactoryBean">……</bean>”:
                        MyBatis-Spring 集成组件提供的新 SqlSessionFactory 类型。
                        1. <property name="dataSource" ref="ds"/>”:
                          支持直接使用 ApplicatioContext 中的第三方数据源。
                        2. <property name="mapperLocations" ……/>”:
                          只需要指明 MyBatis 映射文件的路径,不再需要从主配置文件中取得数据源信息;
                          也免去 (已封装) 了以编程或配置的方式读取配置文件、生成输入流及 SqlSessionFactory 、SqlSession 等繁琐步骤。
                      2. <property name="sqlSessionFactory" ref="crud.mybatis.auto_dao.ssf"/>”:
                        新型 SqlSessionFactory 对象代替先前的 SqlSessionFactory 对象
                    2. 不作修改地重新运行测试用例 tfw.integration_demo._04_spring_web_mvc._02_crud._03_mybatis_crud._02_auto_dao_way.user_mgr_testcase._02_MyBatisDAO_and_Service_from_Spring ,以检查 ApplicationContext 配置的正确性。
              3. ……