第44天(就業班) SSH項目實戰課程-國稅協同辦公平台


1  項目介紹

1.1 項目背景

國稅協同辦公平台包括了行政管理、后勤服務、在線學習、納稅服務、我的空間等幾個子系統;我們本次主要的開發功能是納稅服務子系統的部分模塊和基於納稅服務子系統信息的個人工作台首頁。納稅服務子系統是辦稅PC前端或移動端的后台管理系統,主要包括的功能有系統角色管理、用戶管理、信息發布管理、投訴受理、納稅咨詢、易告知、服務預約、服務調查等模塊。



1.1 項目前期

項目前期;一般是由客戶經理從客戶那邊了解到有關該項目的招標信息,然后開發公司再組織競標;編寫標書和詳細的項目建設方案。這個階段一般由商務部門和開發部門的管理層參與。建設方案由部門經理或者項目經理協助完成。項目建設方案中一般包括初步的系統功能、模塊設計、軟硬件設備、開發組人員介紹等。提供這些信息給客戶后他們再評估相應開發公司是否有承建系統能力。

1.2 需求分析

當項目中標后,公司的客戶經理、項目經理再到客戶環境進行詳細的需求調研,完成調研后將初步的調研結果轉化成正式的需求文檔。需求文檔是所有后續流程的基礎和非常重要的文檔,開發和測試都需要按照需求來開發測試。詳細需求見《國稅協同平台-納稅服務需求規格說明書.docx》

1.3 設計

在這個階段主要是針對需求進行詳細的開發前的分析和對具體模塊的設計。在設計過程中可能包括到的有系統原型設計的完善、界面美工設計切圖、數據庫設計(概念、物理模型)等;最終需要出詳細設計說明書。見《國稅協同平台-納稅服務詳細設計說明書.docx》

1.4 制定開發計划

在需求和詳細設計都已經確定的情況下;項目需要根據開發的時間和任務數來制定開發計划;計划中需要描述所有的開發階段,從需求階段到部署上線期間所有要做的任務,每個任務對應具體的開始時間、結束時間,前置任務,工作時長,資源名稱。后續的開發都根據該計划進行在每周開周例會上確認開發進度是否和計划保持一致,如果不一致則需要預測好相應方案;保證能如期提交系統給到客戶。

1.5 開發

根據開發計划,項目經理將組織開發團隊完成具體的開發任務,每周向公司部門、客戶主管人員匯報項目進度。對應具體的開發人員則熟悉、理解需求,明白設計文檔;按照計划中時間點開發功能,提交代碼。

SSH框架整合

1.1 新建數據庫及web項目

1.1.1  創建itcastTax數據庫

-- 創建數據庫

CREATEDATABASE itcastTax DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

1.1.1  新建web項目

新建工作空間指定項目編碼(或工作空間編碼)為utf-8,再建 web project,配置buildpath


 


如若對應的MyEclipse版本沒有上述的“MyEclipse Server Library”;可以選擇“My Eclipse Library”然后選擇ee的包。


選擇對應配置的tomcat版本即可。


添加jstl jar包和mysql驅動包;
 


1.1 框架整合
1.1.1 添加struts2的jar包和配置文件
添加jar包:
commons-fileupload-1.3.1.jar,commons-io-2.2.jar,commons-lang-2.4.jar ,commons-lang3-3.2.jar,freemarker-2.3.19.jar,ognl-3.0.6.jar,struts2-core-2.x.jar
,struts2-spring-plugin-2.x.jar,xwork-core-2.x.jar 到web-inf/lib目錄下。
添加struts.xml到src目錄下。可在“struts-2.x\apps\struts2-blank\WEB-INF\classes”下復制。
在struts.xml中添加幾個常用屬性:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
"http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>
<!-- 禁用動態方法訪問 -->
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<!-- 配置成開發模式 -->
<constant name="struts.devMode" value="true" />
<!-- 配置拓展名為action -->
<constant name="struts.action.extention" value="action" />
<!-- 把主題配置成simple -->
<constant name="struts.ui.theme" value="simple" />
</struts>


配置web.xml:添加struts2 過濾器:
  <filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
1.1.1 添加hibernate的jar包和配置文件
添加hibernate jar包:
 hibernate3.jar,lib/required/*.jar,lib\jpa\hibernate-jpa-2.0-api-1.0.0.Final.jar,lib\bytecode\cglib\cglib-2.2.jar到web-inf/lib目錄下。


至於hibernate.cfg.xml文件,因項目使用spring來整合管理實體和數據庫的連接等hibernate原本的工作,所以這個配置文件不再需要。
1.1.2 添加spring的jar包和配置文件
添加spring3.0.2中的jar包:
 


添加spring配置文件applicationContext.xml 到src目錄下;


在web.xml中注冊spring監聽器,啟動spring容器:
<listener>
       <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:applicationContext.xml</param-value>
    </context-param>
整合的jar包如圖所示
  
1.1 整合測試項目
1.1.1 整合struts 和 spring
預期:如果可以在action中能夠正確調用service里面的方法執行並返回到一個頁面中;那么我們認定struts和spring的整合是成功的。
編寫JUnit測試類,測試spring加載是否正確:
package cn.itcast.test;


import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;


import cn.itcast.test.service.TestService;
public class TestMerge {
@Test
public void testSpring()
{
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
TestService ts=(TestService)ctx.getBean("testService");
ts.say();
}
}
編寫 TestService 接口 和實現類 TestServiceImpl
 package cn.itcast.test.service;
public interface TestService {
public void say();
}


在applicationContext.xml中添加bean掃描配置信息;這邊使用導入配置文件的方式配置。①首先在cn.itcast.test.conf中建立test-spring.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:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd 
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- 掃描service -->
<context:component-scan base-package="cn.itcast.test.service.impl"></context:component-scan>
</beans>
里面的配置就是普通的bean掃描,只是將掃描范圍縮小了。
②將test-spring.xml導入到applicationContext.xml中如下:
<import resource="classpath:cn/itcast/*/conf/*-spring.xml" />
編寫TestAction類
package cn.itcast.test.action;
import javax.annotation.Resource;
import cn.itcast.test.service.TestService;
import com.opensymphony.xwork2.ActionSupport;
public class TestAction extends ActionSupport {
@Resource
TestService testService;
public String execute(){
testService.say();
return SUCCESS;
}
}


在test的conf文件夾下新建test-struts.xml中配置TestAction :
<struts>
<package name="test-action" namespace="/" extends="struts-default">
<action name="test_*" class="cn.itcast.test.action.TestAction" method="{1}">
<result name="success">/WEB-INF/jsp/test/test.jsp</result>
</action>
</package>
</struts>


將test-struts.xml導入到struts.xml文件中。
<include file="cn/itcast/test/conf/test-struts.xml"/>


在webRoot目錄下新建test/test.jsp
在瀏覽器中輸入:http://localhost:8080/itcastTax/test.action 查看后台是否能輸入service中的打印信息。
1.1.1 整合hibernate 和 spring
在applicationContext.xml中配置如下原本在hibernate.cfg.xml中需要配置的信息,在spring中配置后hibernate.cfg.xml 可刪除。
1、 配置c3p0數據庫連接源:
<!-- 導入外部的properties配置文件 -->
<context:property-placeholder location="classpath:db.properties" />


<!-- 配置c3p0數據源 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="jdbcUrl" value="${jdbcUrl}"></property>
<property name="driverClass" value="${driverClass}"></property>
<property name="user" value="${user}"></property>
<property name="password" value="${password}"></property>
<!--初始化時獲取三個連接,取值應在minPoolSize與maxPoolSize之間。Default: 3 -->
<property name="initialPoolSize" value="${initialPoolSize}"></property>
<!--連接池中保留的最小連接數。Default: 3 -->
<property name="minPoolSize" value="3"></property>
<!--連接池中保留的最大連接數。Default: 15 -->
<property name="maxPoolSize" value="${maxPoolSize}"></property>
<!--當連接池中的連接耗盡的時候c3p0一次同時獲取的連接數。Default: 3 -->
<property name="acquireIncrement" value="3"></property>
<!--最大空閑時間,1800秒內未使用則連接被丟棄,若為0則永不丟棄。Default: 0 -->
<property name="maxIdleTime" value="1800"></property>
</bean>


2、 db.properties
jdbcUrl=jdbc:mysql://localhost:3306/itcastTax?useUnicode=true&characterEncoding=utf8
driverClass=com.mysql.jdbc.Driver
user=root
password=root
initialPoolSize=10
maxPoolSize=30


3、 配置sessionFactory,並將dataSource指向c3p0創建的dataSource:

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.hbm2ddl.auto">update</prop>
<prop key="javax.persistence.validation.mode">none</prop>
</props>
</property>
<property name="mappingLocations">
<list>
<!-- <value>classpath:cn/itcast/nsfw/*/entity/*.hbm.xml</value> -->
<value>classpath:cn/itcast/test/entity/*.hbm.xml</value>
</list>
</property>
</bean>
編寫實體類Person和對應的映射文件Person.hbm.xml:
package cn.itcast.test.entity;


import java.io.Serializable;
//Serializable接口可以對對象直接進行讀和寫和傳對象
public class Person implements Serializable {
private String id;
private String name;
public Person() {
}
public Person(String id, String name) {
this.id = id;
this.name = name;
}

public Person(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}


映射文件的頭部信息:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.test.entity.Person" table="person">
<id name="id" type="java.lang.String">
<column name="id" length="32" />
<generator class="uuid.hex" />
</id>
<property name="name" type="java.lang.String">
<column name="name" length="20" not-null="true" />
</property>
</class>
</hibernate-mapping>
編寫完實體映射文件后,用JUnit測試hibernate和spring的整合,在測試用例中啟動spring容器的時候將掃描Person類根據其創建數據庫表,並在測試時將向表插入一條數據。
測試hibernate,添加一個人員
@Test
public void testHibernate() {
SessionFactory sf = (SessionFactory)ctx.getBean("sessionFactory");
Session session = sf.openSession();
Transaction transaction = session.beginTransaction();
//保存人員
session.save(new Person("人員1"));
transaction.commit();
session.close();
}
測試框架分層的整合(service 與 dao)
TestDao 中新增方法 save ,在TestService中通過調用testDao來保存人員信息。
package cn.itcast.test.service;


import java.io.Serializable;
import cn.itcast.test.entity.Person;
public interface TestService {
//輸出
public void say();
//保存人員
public void save(Person person);
//根據id查詢人員
public Person findPerson(Serializable id);
}


package cn.itcast.test.dao;
import java.io.Serializable;
import cn.itcast.test.entity.Person;
public interface TestDao {
//保存人員
public void save(Person person);
//根據id查詢人員
public Person findPerson(Serializable id);
}
package cn.itcast.test.dao.impl;
import java.io.Serializable;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import cn.itcast.test.dao.TestDao;
import cn.itcast.test.entity.Person;
public class TestDaoImpl extends HibernateDaoSupport implements TestDao {
@Override
public void save(Person person) {
getHibernateTemplate().save(person);
}
@Override
public Person findPerson(Serializable id) {
return getHibernateTemplate().get(Person.class, id);
}
}
在test-spring。Xml做如下配置
 


package cn.itcast.test.service.impl;


import java.io.Serializable;


import javax.annotation.Resource;


import org.springframework.stereotype.Service;


import cn.itcast.test.dao.TestDao;
import cn.itcast.test.entity.Person;
import cn.itcast.test.service.TestService;
@Service("testService")
public class TestServiceImpl implements TestService {

@Resource
TestDao testDao;


@Override
public void say() {
System.out.println("service saying hi.");
}


@Override
public void save(Person person) {
testDao.save(person);
int i = 1/0;
}


@Override
public Person findPerson(Serializable id) {
save(new Person("test"));
return testDao.findPerson(id);
}


}
TestMerfe.java
@Test
public void testServiceAndDao() {
TestService ts = (TestService)ctx.getBean("testService");
ts.save(new Person("人員2"));
//System.out.println(ts.findPerson("4028eea54c8cdb1f014c8cdb20ab0000").getName());
}


1.1.3 配置spring事務管理
<!—事務管理-->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!—事務通知-->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="find*" read-only="true" />
<tx:method name="get*" read-only="true" />
<tx:method name="load*" read-only="true" />
<tx:method name="list*" read-only="true" />
<tx:method name="search*" read-only="true" />
<tx:method name="*" rollback-for="Throwable" />
</tx:attributes>
</tx:advice>


<!—配置需要進行事務控制的類 -->
<aop:config>
<aop:pointcut id="serviceOperation" expression="bean(*Service)" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation" />
</aop:config>




【注意:上面的pointcut  expression 表示攔截以Service結尾的bean,或者可寫成
execution(* cn.itcast..service.impl.*.*(..))】
完善 TestService接口和TestServiceImpl;利用service中的操作來驗證上面配置的事務管理是否生效。


測試方法
 


Dao中
package cn.itcast.test.dao.impl;


import java.io.Serializable;


import org.springframework.orm.hibernate3.support.HibernateDaoSupport;


import cn.itcast.test.dao.TestDao;
import cn.itcast.test.entity.Person;
public class TestDaoImpl extends HibernateDaoSupport implements TestDao {
@Override
public void save(Person person) {
getHibernateTemplate().save(person);
}
@Override
public Person findPerson(Serializable id) {
return getHibernateTemplate().get(Person.class, id);
}
}


Service中
package cn.itcast.test.service.impl;


import java.io.Serializable;


import javax.annotation.Resource;


import org.springframework.stereotype.Service;


import cn.itcast.test.dao.TestDao;
import cn.itcast.test.entity.Person;
import cn.itcast.test.service.TestService;
@Service("testService")
public class TestServiceImpl implements TestService {

@Resource
TestDao testDao;


@Override
public void say() {
System.out.println("service saying hi.");
}


@Override
public void save(Person person) {
testDao.save(person);
int i = 1/0;
}


@Override
public Person findPerson(Serializable id) {
save(new Person("test"));
return testDao.findPerson(id);
}


}




1.1 資源文件分類
1、 將配置文件歸類到新建config文件夾;
2、 源代碼目錄按照功能模塊進行划分:cn.itcast.子系統.功能模塊.*
3、 Jsp放置到WEB-INF目錄下;
4、 其它: 
 
1.2 日志工具配置
在控制台會報出日志log4j沒有配置好配置文件的信息。
 


Slf4j 接口jar(slf4j-log4j12-1.6.1.jar)
log4j的jar包(com.springsource.org.apache.log4j-1.2.15),配置log4j.properties文件。
 


測試:
 
1.3 編寫基類BaseDao
 DAO基類中配備增刪改查的操作。
 


 


獲取泛型類型:
// 使用反射得到T的真實類型
ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 獲取當前new的對象的 泛型的父類 類型
this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 獲取第一個類型參數的真實類型
}
2 用戶管理
1.1 實現CRUD的步驟及用戶實體映射文件
1、 用戶實體類及映射文件:User.java 和 User.hbm.xml
2、 實現UserDao、UserDaoImpl,直接繼承BaseDao、BaseDaoImpl;
3、 編寫UserService、UserService類,里面包括baseDao中的基本方法;
4、 UserAction中要實現增刪改查,需要6個方法;我們約定需要跳轉到頁面的方法以UI結尾,如果addUI 則說明這是跳轉到添加頁面,需要對應一個addUI.jsp。在刪除、修改、添加完成后應該返回列表頁面,這時為了避免重復提交返回使用重定向。


配置user-spring.xml,並將其導入到applicationContext.xml中,然后在applicatoinContext.xml中設置所有業務dao的父類dao,為baseDao中的HibernateDaoSupport注入sessionFactory。


<!-- 所有dao的parent -->
<bean name="baseDao" abstract="true">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>


在user-spring.xml中的內容:
 
1.4 實現用戶管理的CRUD方法及顯示列表
在UserAction中至少需要有的6個方法:


listUI() --- 返回到列表頁面對應listUI.jsp
addUI() --- 返回到添加頁面對應addUI.jsp
add() --- 重定向到listUI
edit() --- 重定向到listUI
editUI() --- 返回到編輯頁面對應editUI.jsp
delete() --- 刪除用戶完后重定向到listUI


設置完action后,配置user-struts.xml文件,里面對應各個方法對應的頁面;最后將user-struts.xml包含到struts.xml文件中。




接下來引入美工設計好的頁面;將數據與頁面結合展示。
1.5 完成美工設計頁面顯示
將美工設計好的頁面復制到項目中:


將js、css、image、分別放置到WebRoot目錄下;其它的jsp對應復制。復制完成后針對jsp頁面填充動態數據。


對應大多數頁面樣式和jquery都是需要的,所以我們把公共樣式和jquery、struts標簽庫等信息抽出到一個header.jsp文件中,將此文件放入common公共文件目錄。


 


 
1.6 批量刪除
在用戶列表listUI.jsp中設置好復選框<input type="checkbox" name="selectedRow" value='<s:property value="id"/>'/> ,點擊操作欄中的刪除執行js腳本提交用戶列表表單到后台UserAction,在action中使用數組接收勾選的用戶id,然后在對該數組進行遍歷刪除。
 


Js腳本:
 
1.7 日期組件wdatepicker
導入WdataPicker文件包到項目的js文件夾下;


在用戶管理中的添加、編輯jsp頁面對生日表單項引入日期組件:
<script type="text/javascript" src="${basePath}js/datepicker/WdatePicker.js"></script>


用法:
<s:textfield id="birthday" name="user.birthday" readonly="true"
                             onfocus="WdatePicker({skin:'whyGreen', el:'birthday',dateFmt:'yyyy-MM-dd'})"/>


回顯時,注意設置好顯示格式;可以如下設置:
<s:textfield id="birthday" name="user.birthday" readonly="true"
                             onfocus="WdatePicker({skin:'whyGreen', el:'birthday',dateFmt:'yyyy-MM-dd'})">
                       <s:param name="value"><s:date name='user.birthday' format='yyyy-MM-dd' /></s:param>      
            </s:textfield>



注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com