一次难忘的调试经历

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

@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(),让这个函数返回尽可能多的信息
结果

怎么会这样呢?我写了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好像不会接住吧,因此改为接一切异常!再加上一个finallytomcat

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页面

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

@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();
        }
    }

终于:

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

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

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

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

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

相关文章
相关标签/搜索