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>
转载于:https://blog.51cto.com/yongguang/1693502