Spring+Quartz实现定时从FTP服务器读取文件并存入Oracel数据库

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配置,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
<? 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 >

猜你喜欢

转载自yuanke.iteye.com/blog/2384743
今日推荐