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配置,
<?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>
本文出自 “听雨盼永恒” 博客,请务必保留此出处http://yongguang.blog.51cto.com/9153118/1693502
Spring+Quartz实现定时从FTP服务器读取文件并存入Oracel数据库
原文地址:http://yongguang.blog.51cto.com/9153118/1693502