`
yuanke
  • 浏览: 70036 次
  • 性别: Icon_minigender_2
  • 来自: 临沂
社区版块
存档分类
最新评论

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>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics