美文网首页
Java URL类踩坑指南(一)

Java URL类踩坑指南(一)

作者: java部落 | 来源:发表于2017-11-28 21:54 被阅读0次

    背景介绍

    最近再做一个RSS阅读工具给自己用,其中一个环节是从服务器端获取一个包含了RSS源列表的json文件,再根据这个json文件下载、解析RSS内容。核心代码如下:

    class PresenterImpl(val context: Context, val activity: MainActivity) : IPresenter {
        private val URL_API = "https://vimerzhao.github.io/others/rssreader/RSS.json"
    
        override fun getRssResource(): RssSource {
            val gson = GsonBuilder().create()
            return gson.fromJson(getFromNet(URL_API), RssSource::class.java)
        }
    
        private fun getFromNet(url: String): String {
            val result = URL(url).readText()
            return result
        }
    
        ......
    }
    

    之前一直执行地很好,直到前两天我购买了一个vimerzhao.top的域名,并将原来的域名vimerzhao.github.io重定向到了vimerzhao.top。这个工具就无法使用了,但在浏览器输入URL_API却能得到数据:

    image

    那为什么URL.readText()没有拿到数据呢?

    不支持重定向

    可以通过下面代码测试:

    import java.net.*;
    import java.io.*;
    
    public class TestRedirect {
        public static void main(String args[]) {
            try {
                URL url1 = new URL("https://vimerzhao.github.io/others/rssreader/RSS.json");
                URL url2 = new URL("http://vimerzhao.top/others/rssreader/RSS.json");
                read(url1);
                System.out.println("=--------------------------------=");
                read(url2);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public static void read(URL url) {
            try {
                BufferedReader in = new BufferedReader(
                        new InputStreamReader(url.openStream()));
    
                String inputLine;
                while ((inputLine = in.readLine()) != null) {
                    System.out.println(inputLine);
                }
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    

    得到结果如下:

    <html>
    <head><title>301 Moved Permanently</title></head>
    <body bgcolor="white">
    <center><h1>301 Moved Permanently</h1></center>
    <hr><center>nginx</center>
    </body>
    </html>
    =--------------------------------=
    {"theme":"tech","author":"zhaoyu","email":"dutzhaoyu@gmail.com","version":"0.01","contents":[{"category":"综合版块","websites":[{"tag":"门户网站","url":["http://geek.csdn.net/admin/news_service/rss","http://blog.jobbole.com/feed/","http://feed.cnblogs.com/blog/sitehome/rss","https://segmentfault.com/feeds","http://www.codeceo.com/article/category/pick/feed"]},{"tag":"知名社区","url":["https://stackoverflow.com/feeds","https://www.v2ex.com/index.xml"]},{"tag":"官方博客","url":["https://www.blog.google/rss/","https://blog.jetbrains.com/feed/"]},{"tag":"个人博客-行业","url":["http://feed.williamlong.info/","https://www.liaoxuefeng.com/feed/articles"]},{"tag":"个人博客-学术","url":["http://www.norvig.com/rss-feed.xml"]}]},{"category":"编程语言","websites":[{"tag":"Kotlin","url":["https://kotliner.cn/api/rss/latest"]},{"tag":"Python","url":["https://www.python.org/dev/peps/peps.rss/"]},{"tag":"Java","url":["http://www.codeceo.com/article/category/develop/java/feed"]}]},{"category":"行业动态","websites":[{"tag":"Android","url":["http://www.codeceo.com/article/category/develop/android/feed"]}]},{"category":"乱七八遭","websites":[{"tag":"Linux-综合","url":["https://linux.cn/rss.xml","http://www.linuxidc.com/rssFeed.aspx","http://www.codeceo.com/article/tag/linux/feed"]},{"tag":"Linux-发行版","url":["https://blog.linuxmint.com/?feed=rss2","https://manjaro.github.io/feed.xml"]}]}]}
    

    HTTP返回码301,即发生了重定向。可在浏览器上这个过程太快以至于我们看不到这个301界面的出现。这里需要说明的是URL.readText()是Kotlin中一个扩展函数,本质还是调用了URL类的openStream方法,部分源码如下:

    .....
    /**
     * Reads the entire content of this URL as a String using UTF-8 or the specified [charset].
     *
     * This method is not recommended on huge files.
     *
     * @param charset a character set to use.
     * @return a string with this URL entire content.
     */
    @kotlin.internal.InlineOnly
    public inline fun URL.readText(charset: Charset = Charsets.UTF_8): String = readBytes().toString(charset)
    
    /**
     * Reads the entire content of the URL as byte array.
     *
     * This method is not recommended on huge files.
     *
     * @return a byte array with this URL entire content.
     */
    public fun URL.readBytes(): ByteArray = openStream().use { it.readBytes() }
    

    所以上面的测试代码即说明了URL.readText()失败的原因。
    不过URL不支持重定向是否合理?为什么不支持?还有待探究。

    欢迎加入学习交流群569772982,大家一起学习交流。

    相关文章

      网友评论

          本文标题:Java URL类踩坑指南(一)

          本文链接:https://www.haomeiwen.com/subject/yahybxtx.html