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

Page: [index.html] (v2017-03-01_21-00)

  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 :
        • 样例 - 用户管理:
          1. 环境准备:
            修改 pom.xml ,添加需要的库 (并由 Eclipse 的 Maven 插件自动下载、导入) :
            <project ……>
            	……
            	<dependencies>
            		……
            		<dependency>
            			<!-- For [Spring 3] JDBC Template. -->
            			<groupId>org.springframework</groupId>
            			<artifactId>spring-jdbc</artifactId>
            			<version>3.2.8.RELEASE</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
              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. 编写 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/03_jdbc_template_crud.xml ,注册 Spring JDBC Template 对象、指定 ID ,以供DAO 使用:
                <?xml version="1.0" encoding="UTF-8"?>
                <beans ……>
                	<bean id="jt" class="org.springframework.jdbc.core.JdbcTemplate">
                		<property name="dataSource" ref="ds"/>
                	</bean>
                </beans>
                

              2. 修改 ApplicationContext 主配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/applicationContext.xml ,添加上述分项:
                <?xml version="1.0" encoding="UTF-8"?>
                <beans ……>
                	……
                	<import resource="sub_files/02_basic_jdbc_crud.xml"/>
                	<import resource="sub_files/03_jdbc_template_crud.xml"/>
                </beans>
                

              3. 编写使用 Spring JDBC Template 的 DAO 实现类 tfw.integration_demo._04_spring_web_mvc._02_crud._02_spring_jdbc_template_crud.dao.impl.oracle.UserDAO
                ……
                
                /**
                 * Either "@Component(...)" or "@Repository(...)" is OK!<br />
                 * 
                 * ……
                 */
                @Component("crud.spring_jdbc_template.userDAO")
                // @Repository("crud.spring_jdbc_template.userDAO")
                public class UserDAO implements I_UserDAO
                {
                
                	@Resource(name = "jt")
                	private JdbcTemplate jt;
                
                	private RowMapper<User> rowMapper = new RowMapper<User>()
                	{
                
                		……
                		public User mapRow(ResultSet rs, int rowNum) throws SQLException
                		{
                			User user = new User();
                
                			Object obj = rs.getObject("id");
                			user.setId(NumberToolE.o2I(obj, null));
                
                			obj = rs.getObject("name");
                			user.setName(TextToolE.o2s(obj, null));
                
                			obj = rs.getObject("passwd");
                			user.setPasswd(TextToolE.o2s(obj, null));
                
                			obj = rs.getObject("stat");
                			user.setStat((null != obj && obj instanceof Number)
                					? ((Number) obj).byteValue() : null);
                
                			obj = rs.getObject("remark");
                			user.setRemark(TextToolE.o2s(obj, null));
                
                			return user;
                		}
                	};
                
                	……
                	public int create(User user) throws SQLException
                	{
                		……
                
                		try
                		{
                			KeyHolder keyHolder = new GeneratedKeyHolder();
                			final String strSql =
                					"insert into tfw_dash_user(id, name, passwd, stat, remark) values(tfw_seq_dash_user_id.nextval, ?, ?, ?, ?)";
                			System.out.println(strSql);
                			final Object[] o1dValues = new Object[] { user.getName(),
                					user.getPasswd(), user.getStatus(), user.getRemark() };
                			System.out.println(ArrayToolE.arrayForConsole(o1dValues));
                
                			PreparedStatementCreator psc = new PreparedStatementCreator()
                			{
                
                				……
                				public PreparedStatement createPreparedStatement(
                						Connection cnct) throws SQLException
                				{
                					PreparedStatement pstmt = cnct.prepareStatement(strSql,
                							new String[] { "id" });
                					for (int intIdx = 0; intIdx < o1dValues.length; intIdx++)
                					{
                						pstmt.setObject(intIdx + 1, o1dValues[intIdx]);
                					}
                					return pstmt;
                				}
                
                			};
                
                			int intJdbcCode = jt.update(psc, keyHolder);
                			Object oCol1 = keyHolder.getKeys().get("id");
                			user.setId(NumberToolE.o2I(oCol1, null));
                
                			return intJdbcCode;
                		}
                		catch (Exception e)
                		{
                			e.printStackTrace();
                			if (e instanceof SQLException)
                			{
                				throw (SQLException) e;
                			}
                			else
                			{
                				throw new RuntimeException(e);
                			}
                		}
                	}
                
                	……
                	public User findById(Integer itgUserId) throws SQLException
                	{
                		try
                		{
                			String strSql =
                					"select id, name, passwd, stat, remark from tfw_dash_user where id"
                							+ ((null == itgUserId) ? " is null" : "=?");
                			System.out.println(strSql);
                			final Object[] o1dValues = (null == itgUserId) ? new Object[0]
                					: new Object[] { itgUserId };
                
                			List<User> lstUsers = jt.query(strSql, o1dValues, rowMapper);
                			User user = null;
                			……
                			return user;
                		}
                		catch (Exception e)
                		{
                			……
                		}
                	}
                
                	……
                
                }
                

                说明 / 注意事项:
                1. @Component("……")” / “@Repository("……")”:
                  以 XML 文件配置方式之外的办法将 DAO 对象注册到 ApplicationContext 中、并指定 ID
                  对于程序运行来说,这两个注解没有明显区别,但“@Repository("……")”在字面上含有“数据来源”之意,用此注解令程序的可读性略有提高。
                2. @Resource(name = "jt")”:
                  Spring 框架扫描到此注解时,从 ApplicationContext 提取 ID 为 jt 的 Spring JDBC Template 对象,以反射方式注入给带有此注解的成员变量。
                3. private RowMapper<User> rowMapper”:
                  Spring JDBC Template 需要一个 RowMapper 型对象,此对象负责将结果集中的行组织成实体对象;
                4. KeyHolder keyHolder”:
                  在 create(...) 方法中利用 Spring JDBC Template 的 keyHolder 取得为特定的键“id”自动生成的值 oCol1
              4. 本样例由 Spring 框架扫描带有 Spring 注解的类 (而非读取 XML 配置文件) 的方式将 DAO 注册到 ApplicationContext 中,所以在 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/03_jdbc_template_crud.xml 中声明“启用扫描功能”,并指明要扫描的包:
                <?xml version="1.0" encoding="UTF-8"?>
                <beans ……>
                	<bean id="jt" ……>
                		……
                	</bean>
                
                	<context:component-scan
                			base-package="tfw.integration_demo._04_spring_web_mvc._02_crud._02_spring_jdbc_template_crud"/>
                </beans>
                

                说明 / 注意事项:
                • <context:component-scan ……>……</context:component-scan>”:
                  启用扫描功能。
                  • base-package="tfw.integration_demo._04_spring_web_mvc._02_crud._02_spring_jdbc_template_crud"”:
                    递归扫描此包下所有层次中的内容。
              5. 编写测试用例 tfw.integration_demo._04_spring_web_mvc._02_crud._02_spring_jdbc_template_crud.UserMgrTestCase ,测试配置的正确性及 DAO 类中的各方法。
                ……
                public class UserMgrTestCase
                {
                
                	private String strConfFile =
                			"tfw/integration_demo/_04_spring_web_mvc/applicationContext.xml";
                
                	private AbstractApplicationContext actxt;
                
                	private I_UserDAO userDAO;
                
                	@Test
                	public void testObjects()
                			throws FileNotFoundException, SQLException
                	{
                		……
                
                		AbstractApplicationContext actxt =
                				new ClassPathXmlApplicationContext(strClasspathConfFile);
                		System.out.println("Application Context:\n\t" + actxt);
                
                		JdbcTemplate jt = actxt.getBean("jt", JdbcTemplate.class);
                		System.out.println("JdbcTemplate:\n\t" + jt);
                
                		// I_UserDAO userDAO = new UserDAO(jt); // [X] No such constructor!
                		I_UserDAO userDAO = actxt.getBean("crud.spring_jdbc_template.userDAO",
                				I_UserDAO.class);
                		System.out.println("DAO:\n\t" + userDAO);
                
                		actxt.close();
                		System.out.println("Application Context Closed:\n\t" + actxt);
                	}
                
                	@Before
                	public void init()
                	{
                		actxt = new ClassPathXmlApplicationContext(strConfFile);
                		System.out.println("Application Context:\n\t" + actxt);
                
                		userDAO = actxt.getBean("crud.spring_jdbc_template.userDAO",
                				I_UserDAO.class);
                		System.out.println("DAO:\n\t" + userDAO);
                	}
                
                	@After
                	public void close()
                	{
                		……
                	}
                
                	@Test
                	public void testUserDAO_create() throws SQLException
                	{
                		……
                	}
                
                	@Test
                	public void test……() ……
                	{
                		……
                	}
                
                	……
                
                	private void showUsers(List<User> lstUsers)
                	{
                		……
                	}
                
                }
                

            3. 业务层:
              1. 逻辑同“基本 JDBC CRUD”样例,只是使用新的 DAO ,所以沿用“基本 JDBC CRUD”样例既有的业务层类
                修改 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/03_jdbc_template_crud.xml ,以新的 ID 注册业务层对象,并向其注入 DAO
                <?xml version="1.0" encoding="UTF-8"?>
                <beans ……>
                	……
                
                	<context:component-scan
                			……/>
                
                	<bean id="crud.spring_jdbc_template.userMgrSvc"
                			class="tfw.integration_demo._04_spring_web_mvc._02_crud._01_basic_jdbc_crud.service._01_UserMgrService">
                		<property name="userDAO" ref="crud.spring_jdbc_template.userDAO"/>
                	</bean>
                </beans>
                

                说明 / 注意事项:
                • <property name="userDAO" ref="crud.spring_jdbc_template.userDAO"/>”:
                  标有注解的 DAO 也会被注册到 ApplicationContext 中,其 ID 可以用在 XML 配置文件中。
              2. 改造测试用例 tfw.integration_demo._04_spring_web_mvc._02_crud._02_spring_jdbc_template_crud.UserMgrTestCase ,测试配置的正确性及业务层类中的各方法。
                ……
                public class UserMgrTestCase
                {
                
                	……
                
                	private I_UserDAO userDAO;
                
                	private _01_UserMgrService userMgrSvc;
                
                	@Test
                	public void testObjects()
                			throws FileNotFoundException, SQLException
                	{
                		……
                
                		// I_UserDAO userDAO = new UserDAO(jt); // [X] No such constructor!
                		I_UserDAO userDAO = actxt.getBean("crud.spring_jdbc_template.userDAO",
                				I_UserDAO.class);
                		System.out.println("DAO:\n\t" + userDAO);
                
                		// _01_UserMgrService userMgrSvc = new _01_UserMgrService();
                		// userMgrSvc.setUserDAO(userDAO);
                		_01_UserMgrService userMgrSvc =
                				actxt.getBean("crud.spring_jdbc_template.userMgrSvc",
                						_01_UserMgrService.class);
                		System.out.println("Service:\n\t" + userMgrSvc);
                
                		actxt.close();
                		System.out.println("Application Context Closed:\n\t" + actxt);
                	}
                
                	@Before
                	public void init()
                	{
                		……
                
                		userDAO = actxt.getBean("crud.spring_jdbc_template.userDAO",
                				I_UserDAO.class);
                		System.out.println("DAO:\n\t" + userDAO);
                
                		userMgrSvc = actxt.getBean("crud.spring_jdbc_template.userMgrSvc",
                				_01_UserMgrService.class);
                		System.out.println("Service:\n\t" + userMgrSvc);
                	}
                
                	@After
                	public void close()
                	{
                		……
                	}
                
                	……
                
                	@Test
                	public void testUserDAO_discardById() throws SQLException
                	{
                		……
                	}
                
                	@Test
                	public void testUserMgrSvc_createUser() throws SQLException
                	{
                		……
                	}
                
                	……
                
                	private void showUsers(List<User> lstUsers)
                	{
                		……
                	}
                
                }
                

            4. 表示层:
              1. “控制器”的逻辑与“基本 JDBC CRUD”样例完全一致;对“基本 JDBC CRUD”样例做“灵活性改进试验”,以沿用控制器类:
                1. TODO 修改“控制器”类 tfw.integration_demo._04_spring_web_mvc._02_crud._01_basic_jdbc_crud.controller._01_UserMgrController
                  1. 跳转方向不再写死,而由 Properties 型 bean 属性 jumpTarget 决定;
                  2. JSP 页面标题由 String 型 bean 属性 pageTitle 决定。
                  ……
                  public class _01_UserMgrController implements Controller
                  {
                  
                  	……
                  	public void setUserMgrSvc(_01_UserMgrService userMgrSvc)
                  	{
                  		……
                  	}
                  
                  	private String strTitle;
                  
                  	……
                  	public void setPageTitle(String strTitle)
                  	{
                  		this.strTitle = strTitle;
                  	}
                  
                  	private Properties propsTarget;
                  
                  	……
                  	public void setJumpTarget(Properties propsTarget;)
                  	{
                  		this.propsTarget = propsTarget;
                  	}
                  
                  	……
                  	public ModelAndView handleRequest(HttpServletRequest request,
                  			HttpServletResponse response) throws Exception
                  	{
                  		……
                  
                  		String strTarget = propsTarget.getProperty("result");
                  		// "/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/result.jsp";
                  		if ("do_add".equals(strCmd))
                  		{
                  			……
                  		}
                  		else if ("show_detail".equals(strCmd))
                  		{
                  			……
                  
                  			strTarget = propsTarget.getProperty("detail");
                  			// "/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/detail.jsp";
                  		}
                  		else if ("do_edit".equals(strCmd))
                  		{
                  			……
                  		}
                  		else if ("discard".equals(strCmd))
                  		{
                  			……
                  		}
                  		else if ("to_login".equals(strCmd))
                  		{
                  			strTarget = propsTarget.getProperty("login");
                  			// "/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/login.html";
                  		}
                  		else if ("do_login".equals(strCmd))
                  		{
                  			……
                  		}
                  		else
                  		{
                  			……
                  
                  			strTarget = propsTarget.getProperty("list");
                  			// "/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/list.jsp";
                  		}
                  
                  		request.setAttribute("page_title", strTitle);
                  		return new ModelAndView(strTarget);
                  	}
                  
                  }
                  

                2. 在 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/02_basic_jdbc_crud.xml 中找到此“控制器”对象、对其追加注入跳转目标页面标题
                  <?xml version="1.0" encoding="UTF-8"?>
                  <beans ……>
                  	……
                  
                  	<bean id="crud.basic_jdbc.userMgrSvc"
                  			……>
                  		……
                  	</bean>
                  
                  	<bean id="crud.basic_jdbc.userMgrCtrl"
                  			class="tfw.integration_demo._04_spring_web_mvc._02_crud._01_basic_jdbc_crud.controller._01_UserMgrController">
                  		<property name="userMgrSvc" ref="crud.basic_jdbc.userMgrSvc"/>
                  		<property name="pageTitle"
                  				value="Integration&amp;nbsp;Demo / 04&amp;nbsp;Spring&amp;nbsp;Web&amp;nbsp;MVC / 02&amp;nbsp;Create,&amp;nbsp;Read,&amp;nbsp;Update&amp;nbsp;&amp;amp;&amp;nbsp;Discard / 01&amp;nbsp;Basic&amp;nbsp;JDBC&amp;nbsp;CRUD / 01&amp;nbsp;User&amp;nbsp;Management - "/>
                  		<property name="jumpTarget">
                  			<props>
                  				<prop key="result">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/result.jsp</prop>
                  				<prop key="detail">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/detail.jsp</prop>
                  				<prop key="login">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/login.html</prop>
                  				<prop key="list">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/list.jsp</prop>
                  			</props>
                  		</property>
                  	</bean>
                  
                  	<!-- [########################################] -->
                  
                  	<bean id="crud.basic_jdbc.itemDAO"
                  			……>
                  		……
                  	</bean>
                  
                  	……
                  </beans>
                  

                3. 修改 JSP 页面,标题不再写死,改为从 request 中提取。
              2. 修改 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/03_jdbc_template_crud.xml以新的 ID 注册此“控制器”对象,并对其注入业务层对象页面标题跳转目标
                <?xml version="1.0" encoding="UTF-8"?>
                <beans ……>
                	……
                
                	<bean id="crud.spring_jdbc_template.userMgrSvc"
                			……>
                		……
                	</bean>
                
                	<bean id="crud.spring_jdbc_template.userMgrCtrl"
                			class="tfw.integration_demo._04_spring_web_mvc._02_crud._01_basic_jdbc_crud.controller._01_UserMgrController">
                		<property name="userMgrSvc" ref="crud.spring_jdbc_template.userMgrSvc"/>
                		<property name="pageTitle"
                				value="Integration&amp;nbsp;Demo / 04&amp;nbsp;Spring&amp;nbsp;Web&amp;nbsp;MVC / 02&amp;nbsp;Create,&amp;nbsp;Read,&amp;nbsp;Update&amp;nbsp;&amp;amp;&amp;nbsp;Discard / 02&amp;nbsp;Spring&amp;nbsp;JDBC&amp;nbsp;Template&amp;nbsp;CRUD / 01&amp;nbsp;User&amp;nbsp;Management - "/>
                		<property name="jumpTarget">
                			<props>
                				<prop key="result">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/result.jsp</prop>
                				<prop key="detail">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/detail.jsp</prop>
                				<prop key="login">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/02_spring_jdbc_template_crud/01_user_mgr/login.html</prop>
                				<prop key="list">/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/01_basic_jdbc_crud/01_user_mgr/list.jsp</prop>
                			</props>
                		</property>
                	</bean>
                </beans>
                

              3. 修改 ApplicationContext 分项配置文件 src/main/resources/tfw/integration_demo/_04_spring_web_mvc/sub_files/03_jdbc_template_crud.xml ,注册“URL 映射”、指定 ID ,并将 URI /tfw/integration_demo/04_spring_web_mvc/02_crud/02_spring_jdbc_template_crud/01_user_mgr/action.spr 映射至此“控制器”对象:
                <?xml version="1.0" encoding="UTF-8"?>
                <beans ……>
                	……
                
                	<bean id="crud.spring_jdbc_template.userMgrCtrl"
                			……>
                		……
                	</bean>
                
                	<bean id="crud.spring_jdbc_template.urlMapping"
                			class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
                		<property name="mappings">
                			<props>
                				<prop key="/tfw/integration_demo/04_spring_web_mvc/02_crud/02_spring_jdbc_template_crud/01_user_mgr/action.spr">crud.spring_jdbc_template.userMgrCtrl</prop>
                			</props>
                		</property>
                	</bean>
                </beans>
                

              4. 修改 或/及 新增相关的索引页,添加指向此控制器的 URI ,确认控制器配置正确。
              5. 编写本样例的专用页面“src/main/webapp/WEB-INF/pages/tfw/integration_demo/04_spring_web_mvc/02_crud/02_spring_jdbc_template_crud/01_user_mgr/login.html”。
              6. 测试本样例的“登录”和增删改查功能。
      3. ……