问题描述
有类似这么个代码:FTPClient fc = new FTPClient();try {fc.connect("127.0.0.1");} catch (SocketException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}//略去其他在我程序中有类似大量这种try、catch出现,而且每次都要判断一下,如果没有异常就返回true,如果有异常就返回false,同时大多是这种fc.connect("127.0.0.1"),返回的是void类型的,本来想写个方法如:public static boolean xxx(void obj){里面是try、catch和判断},然后调用如:Test.xxx(fc.connect("127.0.0.1")),然后如果连接成功则返回true,失败则返回false,最后我再根据结果做相应业务处理。但是参数类型是不能为void的,那么该如何是好啊?如果每次都是try、catch及大量boolean判断,整个代码将相当冗余及逻辑混乱。 问题补充:大家可能没明白我的意思,都怪我,应该贴出全部代码的。其要求如下:1、都要捕获异常,以便将来日志记录(坑爹的要求。。。还没完成)2、connection连接失败,则再连3次,失败则结束,返回false,成功则继续3、登录失败,处理异常并断开连接,成功继续4、在服务端找不到要下载的文件,处理异常,并且关闭连接返回重新连接3次(坑爹的要求。。。还没完成),3次后还不行则返回false,正常则下好结束,关闭代码如下:package com.jftt.util;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.OutputStream;import java.net.SocketException;import org.apache.commons.net.ftp.FTPClient;import org.apache.commons.net.ftp.FTPFile;import org.apache.commons.net.ftp.FTPReply;public class DownLoadUtil {/** * Description: 从FTP服务器下载文件 * @author hebin * @param url FTP服务器hostname * @param port FTP服务器端口 * @param connectionTimes 连接次数 * @param timeOut 等待时间 * @param username FTP登录账号 * @param password FTP登录密码 * @param remotePath FTP服务器上的相对路径 * @param fileName 要下载的文件名 * @param localPath 下载后保存到本地的路径 * @return success */public static boolean downFile(String url,int port,int connectionTimes,int timeOut,String username,String password,String remotePath,String fileName, String localPath){//初始化,默认连接成功boolean success = true; //创建ftp客户端FTPClient ftp = new FTPClient();//定义失败后的连接次数为3for (int i = 0; i < connectionTimes; i++) {try {//通过url和端口号连接ftp服务器ftp.connect(url, port);System.out.println("连接成功");success = true; i = connectionTimes + 1;//成功连接则跳出for循环,失败则继续执行for循环break;} catch (SocketException e) {e.printStackTrace();System.out.println("连接失败");} catch (IOException e) {e.printStackTrace();System.out.println("连接失败");}try {//10秒未连上则中断连接Thread.sleep(timeOut);} catch (InterruptedException e) {success=false;e.printStackTrace();}}try {ftp.login(username, password);System.out.println("登录成功");success = true; } catch (IOException e) {e.printStackTrace();System.out.println("登录失败");success = false;try {ftp.logout();ftp.disconnect();} catch (IOException e1) {System.out.println("关闭失败");e1.printStackTrace();}}int reply = 0; reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { try {ftp.disconnect();success = true;} catch (IOException e) {e.printStackTrace();success = false;} return success; } try {ftp.changeWorkingDirectory(remotePath);} catch (IOException e) {e.printStackTrace();}FTPFile[] fs;try {fs = ftp.listFiles();for(FTPFile ff:fs){ String path = remotePath + HandleFileNameUtil.handleFileName(fileName);//判断是否是主服务器文件路径if(ff.getName().equals(path)){ //经过处理后的文件名File localFile = new File(localPath+"/"+HandleFileNameUtil.handleFileName(fileName)); OutputStream is = new FileOutputStream(localFile); ftp.retrieveFile(ff.getName(),is); is.close();ftp.logout();ftp.disconnect();success = true;break;}else{success = false;} } } catch (IOException e) {System.out.println("文件不存在");e.printStackTrace();success = false; }return success; }}
解决方案
其实楼上都说的是异常处理办法,给你一段代码:public class DownLoadUtil {public static FTPClient open(String url, int port, int connectionTimes, int timeOut, String username, String password) throws IOException {FTPClient ftp = new FTPClient();ftp.setConnectTimeout(timeOut);for (int i = 1;; i++) {try {ftp.connect(url, port);ftp.login(username, password);return ftp;} catch (IOException e) {if (i >= connectionTimes) throw e;}}}public static void close(FTPClient ftp) {if (ftp != null) {try {ftp.disconnect();} catch (IOException e) {}}}public static void downFile(String url, int port, int connectionTimes, int timeOut, String username,String password, String remotePath, String fileName, String localPath) throws IOException {FTPClient ftp = null;try {ftp = open(url, port, connectionTimes, timeOut, username, password);ftp.changeWorkingDirectory(remotePath);FTPFile[] fs = ftp.listFiles();for (FTPFile ff : fs) {String path = remotePath + HandleFileNameUtil.handleFileName(fileName);// 判断是否是主服务器文件路径if (ff.getName().equals(path)) {// 经过处理后的文件名File localFile = new File(localPath + "/" + HandleFileNameUtil.handleFileName(fileName));try (OutputStream is = new FileOutputStream(localFile)) {ftp.retrieveFile(ff.getName(), is);}}}} finally {close(ftp);}}}
解决方案二:
可以把异常抛出去,在上一层调用时,统一处理这样做就是不知道具体是那个处理上抛出了异常,提示信息不好打...
解决方案三:
如果你使用的是JDK7,可以考如下建议:1)如果确实应该捕获这些异常,并且两个异常处理方式都是相同的,可以使用Java7新加入的语法来处理: catch(SocketException|IOException e) { //处理代码 }2)其实实际使用的过程中应该还有另外一个问题,就是需要处理的finally块, 比如 catch(SocketException|IOException e) { //处理代码 } finally { if(client!=null) { client.close(); } } 这个可以使你FTPClient实现AutoCloseable接口,这样就省去finally里面的麻烦了(finally里面的代码不做的话,有可能会造成连接泄露)。这个也是Java7里面的功能。
解决方案四:
你这异常抓的一点意义都没有 你可能天天看着后台或者天天看着日志去吗出现异常要么自行处理掉 要么 抛给上层调用者针对用户操作层抛出的异常 那么必须给予用户提示
解决方案五:
(1)如果出现SocketException,IOException的时候处理都是e.printStackTrace(),那应该就不用分开捕获了异常,没有实际意义;(2)Test.xxx(fc.connect("127.0.0.1")),这样写同样需要捕获异常,是不是可以考虑把fc.connect("127.0.0.1")放到Test.xxx方法的声明里,出现异常返回false,无异常返回true;(3)常是否异往上抛可能决定于你对fc.coct("127.0.nne0.1")的错误处理机制,如果出现这种错误不需要继续运行后续代码,那么可以考虑直接向上抛出,如果向上抛出的异常类型对你的业务逻辑没有意义的话可以在Test.xxx方法中把异常转换为RuntimeException,可能方法的签名会简洁清晰一点。
解决方案六:
public static boolean connect(FTPClient fc, String ip) throws Exception{ fc.connect("127.0.0.1"); 交给要调用的地方处理,如果调用的地方,连接都出了异常,就直接不用调用别的方法了
解决方案七:
如果不想太多catch语句块,你可以向上层抛,然后在最外层根据Exception的种类,进行不同的处理。
解决方案八:
把上面的代码段放到一个方法中,如:public static boolean connect(FTPClient fc, String ip) { try {fc.connect("127.0.0.1"); return true; } catch (SocketException e) {e.printStackTrace(); } catch (IOException e) {e.printStackTrace(); } catch (NullPointerException npe) { npe.printStackTrace(); } return false;}上面代码块的缺点就是不知道发生了何种异常。建议你自定义一个异常类,然后设置异常编码,把上面可能发生的异常定义成相应的编码,然后抛到上层
解决方案:
异常上抛