package com.nstc.safe.action; import java.io.BufferedReader; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.SocketException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import org.apache.commons.codec.net.URLCodec; import org.apache.commons.el.parser.ParseException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import com.nstc.safe.Config; import com.nstc.safe.domain.SafeErrorFile; import com.nstc.safe.domain.SafeReport; import com.nstc.safe.server.CommonServer; import com.nstc.safe.server.SafeServer; import com.nstc.safe.server.ServerLocator; /** * <p> * Title:外管局錯誤文件查看 * </p> * * <p> * Description:外管局文件下載Action層 * </p> * * <p> * Company: 北京九恆星科技股份有限公司 * </p> * * @author zhangyongguang * * @since:2015年9月8日 09:48:34 * * @version 1.0 */ public class SAFE_U01_17 extends ActionSupport { private static final Log log = LogFactory.getLog(SAFE_U01_17.class); /** * 因爲Spring配置quartz在調用action的時候,對應server尚未注入到容器中, * 因此須要這個action中注入對應server,而且commonServer在spring配置文件中要找獲得對應bean, * 並在commonServer對應的bean中繼承事務控制tx * * commonServer的注入主要是針對work方法(定時任務方法)所用到的與後臺交互的代碼, * */ private CommonServer commonServer; public CommonServer getCommonServer() { return commonServer; } public void setCommonServer(CommonServer commonServer) { this.commonServer = commonServer; } /** * 查詢錯誤文件列表 */ public String execute(HttpServletRequest request) { String errPath = request.getParameter("errorPath"); String start = request.getParameter("startDate"); String end = request.getParameter("endDate"); // 用於下拉選擇框的值 List list = getLocator().getCommonServer().findAll(SafeErrorFile.class); // 列表數據 List list2 = getLocator().getCommonServer().findAll(errPath, start, end, SafeErrorFile.class); //把list放入request對象中,在前臺遍歷 request.setAttribute("list", list); request.setAttribute("list2", list2); return "page"; } /** * 查看XML文件內容,顯示在前臺的頁面上 * @author zhangyonggguang * @param request * @param list * @param id * */ public String viewXML(HttpServletRequest request) { //接收前臺傳來的文件ID String id = request.getParameter("errId"); SafeErrorFile sa = new SafeErrorFile(); //根據ID查詢對應的文件 sa = (SafeErrorFile) getLocator().getCommonServer().findById(id, SafeErrorFile.class); //把查詢的結果放入list集合中, List list = new ArrayList(); list.add(sa); //把list放入request對象中,在前臺遍歷 request.setAttribute("list", list); return "view"; } /** * 定時任務,定時讀取FTP服務器的文件,作入庫操做。 * @author zhangyongguang * @exception Exception * @date 2015-09-09 14:35:24 * @return page * */ public void work()throws Exception { System.out.println("自動任務執行"+new Date()); //執行查詢有多少個路徑須要讀取的方法,並存入set集合中,遍歷set集合,取出有幾個路徑 Set set=findPath(); Iterator it =set.iterator(); while(it.hasNext()){ //上傳路徑爲配置文件配置的文件路徑,與數據庫的發送文件加路徑組合而成, String st=it.next().toString(); System.out.println("SET的值爲"+st); listRemoteAllFiles(st); } } /** * @author zhangyongguang * @param 查詢FTP服務器有多少路徑須要讀取 * */ public Set findPath(){ SafeReport sa=new SafeReport(); //定義set集合,去除重複的路徑 Set set=new HashSet(); //查詢safeReport全部數據 List list=commonServer.findAll(SafeReport.class); for(int i=0;i<list.size();i++){ //把list中的數據強轉成safereport對象 sa=(SafeReport) list.get(i); //判斷sa.getRep_errmsg()裏的值是否爲空 if(sa.getRep_errmsg()!=null&&!sa.getRep_errmsg().equals("")){ //若是不爲空,則存儲到set集合中,若是有重複的值,則添加不進去 set.add(sa.getRep_errmsg().toString()); } } return set; } /** * @author zhangyongguang * @param 連接FTP服務器的工具類 * @param ftpHost FTP主機服務器 * @param ftpPassword FTP 登陸密碼 * @param ftpUserName FTP登陸用戶名 * @param ftpPort FTP端口 默認爲21 * @author zhangyongguang * @throws Exception */ public static FTPClient getFTPClient() throws Exception { String ip=Config.getProperty("IP"); int port=Integer.parseInt(Config.getProperty("PORT")); String username=Config.getProperty("USERNAME"); String password=Config.getProperty("PASSWORD"); String pa=Config.getProperty("PATH","utf-8"); //防止中文路徑亂碼的狀況 ,properties默認爲ISO-8859-1,若是存在用外部編輯器保存爲GBK格式的中文,須要轉換成GBK,不然路徑亂碼上傳失敗 String path=new String(pa.getBytes("ISO-8859-1"),"gbk"); //上傳路徑爲配置文件配置的文件路徑,與數據庫的發送文件加路徑組合而成, FTPClient ftpClient = null; try { ftpClient = new FTPClient(); ftpClient.connect(ip,port);// 鏈接FTP服務器 ftpClient.login(username,password);// 登錄FTP服務器 if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { log.info("未鏈接到FTP,用戶名或密碼錯誤。"); ftpClient.disconnect(); } else { log.info("FTP鏈接成功。"); } } catch (SocketException e) { e.printStackTrace(); log.info("FTP的IP地址可能錯誤,請正確配置。"); } catch (IOException e) { e.printStackTrace(); log.info("FTP的端口錯誤,請正確配置。"); } return ftpClient; } /** * @param 去服務器的FTP路徑下上讀取文件 * @param remotePath讀取的路徑 * @author zhangyongguang */ public void listRemoteAllFiles(String errPath) throws Exception{ String pa=Config.getProperty("PATH","utf-8"); //防止中文路徑亂碼的狀況 ,properties默認爲ISO-8859-1,若是存在用外部編輯器保存爲GBK格式的中文,須要轉換成GBK,不然路徑亂碼上傳失敗 String path=new String(pa.getBytes("ISO-8859-1"),"gbk"); String remotePath=path+errPath; FTPClient ftpClient=new FTPClient(); String fileInfo[]=new String[4]; ftpClient=SAFE_U01_17.getFTPClient();//初始化一個FTP客戶端,調用連接程序連接測試,IF成功,返回打開的連接 boolean s=ftpClient.changeWorkingDirectory(new String(remotePath.getBytes(),"ISO-8859-1"));// 轉移到FTP服務器目錄 if(s=true){ System.out.println("成功切換至:"+remotePath); } try { //讀取remotePath路徑下的全部文件放入數據中, FTPFile[] files = ftpClient.listFiles(); //若是files.length大於0,說明路徑下存在文件。 for (int i = 0; i < files.length; i++) { //判斷數組裏的值是文件仍是文件夾,若是是我文件打印輸出,若是是目錄,調用listRemoteAllFiles繼續判斷 if (files[i].isFile()) { //獲取文件名存入數據組 fileInfo[0]=files[i].getName(); //獲取文件日期存入數組 Date d=files[i].getTimestamp().getTime(); SimpleDateFormat st= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); fileInfo[1]=st.format(d); //獲取文件內容存入數組 fileInfo[2]=readFile(ftpClient, remotePath,files[i].getName()); //入庫操做 List list=commonServer.findByName(fileInfo[0].toString(),errPath, SafeErrorFile.class); if(list.size()<1) { SafeErrorFile safeErrorFile=new SafeErrorFile(); safeErrorFile.setError_name(fileInfo[0].toString()); safeErrorFile.setError_path(errPath); safeErrorFile.setError_info(fileInfo[2].toString()); safeErrorFile.setError_date(fileInfo[1].toString()); commonServer.save(safeErrorFile); } } else if (files[i].isDirectory()) { System.out.println("目錄"+files[i].getName()); //若是是文件夾,則與原來的路徑拼接起來,並在尾部加上/,,例如,原路徑爲:/,拼接後:/文件夾名字/. listRemoteAllFiles(remotePath + files[i].getName() + "/"); System.out.println("遍歷結束"); } } } catch (Exception e) { e.printStackTrace(); System.out.println("出異常了 "); } } /** * @param fileName * @return function:解析文件內容 * @throws ParseException * @throws IOException */ public String readFile(FTPClient ftpClient,String remotePath,String fileName) throws ParseException { InputStream ins = null; String str=null; try { // 從服務器上讀取指定的文件 ins = ftpClient.retrieveFileStream(fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int i; while ((i = ins.read()) != -1) { baos.write(i); } str = baos.toString(); if (ins != null) { ins.close(); } // 主動調用一次getReply()把接下來的226消費掉. 這樣作是能夠解決這個返回null問題 ftpClient.getReply(); } catch (IOException e) { e.printStackTrace(); } return str; } }
下面是spring配置,java
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <import resource="datasource.xml" /> <bean id="propertyConfigurer" class="com.nstc.safe.spring.PropertyConfigurer"> <property name="location"> <value>appContext.properties</value> </property> <property name="fileEncoding"> <value>GBK</value> </property> </bean> <!--hibernate事務 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> </bean> <!-- 基礎事務代理 --> <bean id="baseTxProxy" abstract="true" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref local="transactionManager" /> </property> <property name="transactionAttributes"> <props> <prop key="save*">PROPAGATION_REQUIRED,-Throwable</prop> <prop key="remove*"> PROPAGATION_REQUIRED,-Throwable </prop> <prop key="merge">PROPAGATION_REQUIRED,-Throwable</prop> <prop key="update"> PROPAGATION_REQUIRED,-Throwable </prop> <prop key="do*">PROPAGATION_REQUIRED,-Throwable</prop> </props> </property> </bean> <!-- sqlMapClient --> <bean id="sqlMapClient" class="com.nstc.safe.spring.NstcSqlMapClientFactoryBean"> <property name="configLocation"> <value>sql-map-config.xml</value> </property> </bean> <!-- Hibernate的sessionFactory工廠 --> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect"> org.hibernate.dialect.OracleDialect </prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.format_sql">false</prop> <prop key="hibernate.use_sql_comments">false</prop> <!-- 爲單向關聯(一對一, 多對一)的外鏈接抓取(outer join fetch)樹設置最大深度. 值爲0意味着將關閉默認的外鏈接抓取 --> <prop key="hibernate.max_fetch_depth">3</prop> <!-- 爲Hibernate關聯的批量抓取設置默認數量 --> <prop key="hibernate.default_batch_fetch_size">8</prop> <!-- 強制Hibernate按照被更新數據的主鍵,爲SQL更新排序。這麼作將減小在高併發系統中事務的死鎖。 --> <prop key="hibernate.order_updates">true</prop> <!-- session在事務完成後將被自動清洗(flush) --> <prop key="hibernate.transaction.flush_before_completion"> true </prop> <!-- Oracle限制那些經過JDBC驅動傳輸的字節數組的數目. 若是你但願使用二進值 (binary)或 可序列化的 (serializable)類型的大對象, 你應該開啓 hibernate.jdbc.use_streams_for_binary屬性. --> <prop key="hibernate.bytecode.use_reflection_optimizer"> true </prop> </props> </property> <property name="mappingResources"> <list> <value>com/nstc/safe/domain/SafeAccount.hbm.xml</value> <value>com/nstc/safe/domain/SafeAcntType.hbm.xml</value> <value>com/nstc/safe/domain/SafeBalanceChange.hbm.xml</value> <value>com/nstc/safe/domain/SafeBz.hbm.xml</value> <value>com/nstc/safe/domain/SafeCountry.hbm.xml</value> <value>com/nstc/safe/domain/SafeIncomeDetail.hbm.xml</value> <value>com/nstc/safe/domain/SafePayoutDetail.hbm.xml</value> <value>com/nstc/safe/domain/SafeTransact.hbm.xml</value> <value>com/nstc/safe/domain/SafeConfig.hbm.xml</value> <value>com/nstc/safe/domain/SafeApNumber.hbm.xml</value> <value>com/nstc/safe/domain/SafeExchangeRate.hbm.xml</value> <value>com/nstc/safe/domain/SafeTx.hbm.xml</value> <value>com/nstc/safe/domain/SafeTxLog.hbm.xml</value> <value>com/nstc/safe/domain/SafeRepRows.hbm.xml</value> <value>com/nstc/safe/domain/SafeGeneralCash.hbm.xml</value> <value>com/nstc/safe/domain/SafeListPrice.hbm.xml</value> <value>com/nstc/safe/domain/SafeBigAcnt.hbm.xml</value> <value>com/nstc/safe/domain/SafeMonthStat.hbm.xml</value> <value>com/nstc/safe/domain/SafeTenDayStat.hbm.xml</value> <value>com/nstc/safe/domain/SafeReportFile.hbm.xml</value> <value>com/nstc/safe/domain/SafeReport.hbm.xml</value> <value>com/nstc/safe/domain/CapitalSafeAccount.hbm.xml</value> <value>com/nstc/safe/domain/CapitalBalanceChange.hbm.xml</value> <value>com/nstc/safe/domain/SafeForReportFile.hbm.xml</value> <value>com/nstc/safe/domain/SafeAcntTypeZB.hbm.xml</value> <value>com/nstc/safe/domain/SafeErrorFile.hbm.xml</value> </list> </property> </bean> <!-- locator --> <bean name="safe.locator" class="com.nstc.safe.server.ServerLocator"> <property name="commonServer"> <ref local="commonServer" /> </property> <property name="safeServer"> <ref local="safeServer" /> </property> <property name="capitalServer"> <ref local="capitalServer" /> </property> </bean> <!-- daoFacade --> <bean id="daoFacade" class="com.nstc.safe.dao.DaoFacade" autowire="byName"> </bean> <bean id="baseDao" class="com.nstc.safe.dao.BaseDAO"> <property name="sessionFactory"> <ref local="sessionFactory" /> </property> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="sqlMapClient"> <ref local="sqlMapClient" /> </property> <property name="dbType"> <value>${dbType}</value> </property> </bean> <bean id="testDao" class="com.nstc.safe.dao.TestDAO" parent="baseDao"> </bean> <bean id="commonDao" class="com.nstc.safe.dao.CommonDAO" parent="baseDao"> </bean> <bean id="safeDao" class="com.nstc.safe.dao.SafeDAO" parent="baseDao"> </bean> <bean id="catitalDao" class="com.nstc.safe.dao.CapitalSafeDao" parent="baseDao"> </bean> <bean id="downloadDao" class="com.nstc.safe.dao.DownloadDAO" factory-method="getInstance"> <constructor-arg> <ref bean="dataSource" /> </constructor-arg> <constructor-arg> <ref bean="safe.sqlMapClient" /> </constructor-arg> </bean> <!-- baseServer --> <bean id="baseServer" class="com.nstc.safe.server.impl.BaseServerImpl"> <property name="daoFacade"> <ref local="daoFacade" /> </property> </bean> <bean id="commonServer" parent="baseTxProxy"> <property name="target"> <bean class="com.nstc.safe.server.impl.CommonServerImpl" parent="baseServer" /> </property> </bean> <bean id="safeServer" parent="baseTxProxy"> <property name="target"> <bean class="com.nstc.safe.server.impl.SafeServerImpl" parent="baseServer" autowire="byName" /> </property> </bean> <bean id="capitalServer" parent="baseTxProxy"> <property name="target"> <bean class="com.nstc.safe.server.impl.CapitalSafeServerImp" parent="baseServer" autowire="byName" /> </property> </bean> <bean id="safe.sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean"> <property name="configLocation"> <value>/WEB-INF/classes/sql-map-config.xml</value> </property> </bean> /bean> <!-- ==============================================定時讀取FTP服務器的錯誤文件========================================================= --> <!-- 定義一個定時任務 若是有須要定時的類,直接在list列表裏寫--> <bean class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> <property name="triggers"> <list> <ref bean="testTrigger"/> </list> </property> </bean> <!-- 定時器 --> <bean id="testTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean"> <property name="jobDetail" ref="testJobDetail"/> <property name="cronExpression"> <value>60/900 * * * * ?</value> </property><!-- 20秒後觸發,每隔3秒鐘觸發一次 --> </bean> <!-- 定時器對應bean--> <bean id="testJobDetail" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean"> <property name="targetObject" ref="testJob"/> <property name="targetMethod" value="work"/> <!--類對應執行的方法 --> <!-- 是否容許任務併發執行。當值爲false時,表示必須等到前一個線程處理完畢後纔再啓一個新的線程 --> <property name="concurrent" value="false"/> </bean> <!-- bean映射類 --> <bean id="testJob" class="com.nstc.safe.action.SAFE_U01_17" autowire="byName"> </bean><!-- <bean> <property name="" ref=""/> </bean> <bean name="safe.locator" class="com.nstc.safe.server.ServerLocator"> <property name="commonServer"> <ref local="commonServer" /> </property> <property name="safeServer"> <ref local="safeServer" /> </property> <property name="capitalServer"> <ref local="capitalServer" /> </property> </bean> ======================================================================= <property name="fixedService"> <bean class="com.nstc.wst3.server.DefaultFixedService" autowire="byName"> <property name="commonService"><ref local="commService"/></property> </bean> </property> <property name="workutil"><ref bean="workDayUtil" /></property> <property name="executorMap"> <map> <entry key="1"> <ref bean="txExecutor_3"/> </entry> </map> </property> --><!-- ======================================================================================================= --> </beans>