一次难忘的调试经历

正在编一个网站,在本地编好之后打包成war远程部署到tomcat。在本地一切正常,但是一传到服务器上去就不行了。
我这个网站程序会访问一个网页,去那个网页上爬取点东西,要想爬取就必须需要data.txt提供令牌。
初步锁定bug所在区间,编一个小程序测试一下

    @RequestMapping("haha")
    @ResponseBody
    String debug() {
        try {
            return Util.debug("SY1606604", "xxxxxx", HttpClients.createDefault());
        } catch (IOException e) {
            e.printStackTrace(); 
        }  
        return "error";
    }

出错的那段代码原来是Util.login(username,password,client)
我把出错的那段代码重写,写成一个函数叫做Util.debug(),让这个函数返回尽量多的信息
结果
695653-20170121121544656-1796905893.png
怎么会这样呢?我写了ResponseBody了呀,返回不得是个字符串吗?不会跳到“error”页面的呀。
那我就多返回一点数据:

   @RequestMapping("haha")
    @ResponseBody
    String debug() {
        StringBuilder builder = new StringBuilder();
        try {
            builder.append(Util.debug("SY1606604", "xxxxx", HttpClients.createDefault()));
        } catch (IOException e) {
            builder.append(e.getMessage());
            builder.append(e.getCause().toString());
            builder.append(e.toString());
            builder.append("不可能出错呀");
           
        } 
         return "error";
    }

访问haha页面,结果发现还是上面那种情况,一点都没变啊!
为什么呀?
原来是错中有错,在catch中再次抛出了异常!我又没写finally,结果这个Servlet就向容器抛出异常,结果就跳转到error页面去了!
还有,如果是运行时异常,catch IOException好像不会接住吧,所以改成接一切异常!再加上一个finally

        StringBuilder builder = new StringBuilder();
        try {
            builder.append(Util.debug("SY1606604", "xxxxx", HttpClients.createDefault()));
        } catch (Exception e) {
            builder.append(e.getMessage());
            builder.append(e.getCause().toString());
            builder.append(e.toString());
            builder.append("不可能出错呀");
        } finally {
            return builder.toString();
        }

结果页面中一个字都没有,ctrl+u查看网页源代码,也是空空如也。这tm都是咋回事啊?
要知道上面每一次试错都需要进行

  • maven package打包
  • 打开tomcat manager页面,undeploy旧的war
  • 选择新的war,点击deploy
  • 等待上传结束,刷新haha页面

每次至少两分钟。
我怒了,我打印了这么多东西为啥一个字都没有?
重定向,接受一切打印!!!!!!!!

    @RequestMapping("haha")
    @ResponseBody
    String debug() {
        StringBuilder builder = new StringBuilder();
        builder.append("百思不得其解");
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        PrintStream stream = new PrintStream(out);
        try {
            System.setErr(stream);
            System.setOut(stream);
            builder.append(Util.debug("SY1606604", "xxxxx", HttpClients.createDefault()));
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            builder.append(out.toString());
            return builder.toString();
        }
    }

终于:
695653-20170121123417406-105910309.png
终于看到了日志,梦寐以求的日志,终于知道自己错在哪里?当我看到找不到data.txt文件这句话时,我差点哭出来,好艰难。
珍惜日志,哪有那么多条件去让你调试、跟踪,根本不可能。连部署都是这么艰难,就像ACM题一样,只告诉你对错bool值,不告诉你错在哪里,这是最令人疯狂的。
仿佛有一个声音不停地在耳边呼喊:“你不行的”,我一直追问:“为什么不行?我哪里不行?”这个声音仿佛在嘲笑:“你为什么不行,我不说”。这就像是彻底的否定。
不断地向别人展示别人无法更改的错误,是一种邪恶。它只是为了指出错误而指出错误,只是无理由的告诉你你不行。这让人如堕深渊。
别人有错误,如果以让其改正为目的,则是善意;如果只是一次简单的评判,则是中意;如果是指出别人错误彰显自己的明智或者羞辱别人,那这就是恶意。

回到上文,这里的错误是找不到data.txt,代码中是这么写的:

OutputStream cout = Files.newOutputStream(Paths.get("src/main/resources/checkcode.jpg"));

路径有问题,因为一旦部署到服务器,就没有这种路径了!应该去掉src/main/resources/这个前缀,因为在maven打包时自动把resources目录下的东西打包到classpath路径中了。更好的解决方法是:使用classPath而不要使用操作系统的文件路径

回头观望,我发现了一种调试程序的手段。
定义一个拦截器,在进行处理请求之前,重定向输出流、错误流或者日志到一个内存流,在请求处理的最后,如果发现错误,则打印这个流。这样就能清楚知道自己错在哪里了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值