使用3个信息片段(方案、基本URL和后缀URL)构建URL/URI。

huangapple go评论87阅读模式
英文:

Build URL/URI with 3 pieces (scheme, baseurl and suffix url) of information

问题

String myScheme = "https";
String myHost = "www.theothercompany.com";
String myPath = "/api/v1/things";

java.net.URL computedFullUrl = null;
String urlToStringValue = "";
String urlToExternalFormValue = "";
String urlToUriStringValue = "";
try {
    computedFullUrl = new java.net.URL(myScheme, myHost, myPath);

    if (null != computedFullUrl) {
        urlToStringValue = computedFullUrl.toString();
        urlToExternalFormValue = computedFullUrl.toExternalForm();
        urlToUriStringValue = computedFullUrl.toURI().toString();
    }
} catch (Exception ex) {
    String temp = ex.getMessage();
    ex.printStackTrace();
}

The above code works and produces the following three converted full string values:

https://www.theothercompany.com/api/v1/things

The issue was not related to URI or URL. When reading values from a property file, the leading "/" was being stripped from "/api/v1/things". The value in the string was "api/v1/things", causing the problem.

英文:

I have 3 pieces of information that form a url/uri.

String myscheme = "https";
String basePath = "www.theothercompany.com";
String suffixPath = "/api/v1/things";

How do I "compose" a full URI or URL with (only) the three things above.

I've been through several constructors for :
https://docs.oracle.com/javase/8/docs/api/java/net/URI.html
and
https://docs.oracle.com/javase/8/docs/api/java/net/URL.html

like I tried this:

   URI x = new URI(myscheme , basePath , suffixPath);

or

   URI y = new URI(myscheme , basePath , suffixPath, "");

But I keep getting things like

httpswww.theothercompany.comapi/v1/things

obviously, removing "parts" like "://" and "/".

I don't have a port, or a ssp or a user or textfile...or other things I saw in the constructors of the 2 above oracle links.

I can't believe this is roadblocking me !!

Below are some other (already) pulled in packages. I do not want to add another one (like org.apache.http.client.utils.URIBuilder for example).....to bloat the dependencies.

import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.reactive.function.client.WebClient;

and

compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: springBootVersion

compile group: 'org.apache.commons', name: 'commons-lang3', version: commonsLangVersion

compile 'org.projectreactor:reactor-spring:1.0.1.RELEASE'

APPEND

Ok, as per suggested, I fixed my mislabelling of the 3 parts.

   String myScheme = "https";
    String myHost = "www.theothercompany.com";
    String myPath = "/api/v1/things";

    java.net.URL computedFullUrl = null;
    String urlToStringValue = "";
    String urlToExternalFormValue = "";
    String urlToUriStringValue = "";
    try {

        /* this works....or does not exception out */
        computedFullUrl = new java.net.URL(myScheme, myHost, myPath);

        if (null != computedFullUrl) {
            urlToStringValue = computedFullUrl.toString();
            urlToExternalFormValue = computedFullUrl.toExternalForm();
            urlToUriStringValue = computedFullUrl.toURI().toString();
        }
    } catch (Exception ex) {
        //throw new RuntimeException((ex));
        // temporary swallow
        String temp = ex.getMessage();
        ex.printStackTrace();
    }

So the above works.

I get (all three "convert back to a full string" values of) :

https://www.theothercompany.com/api/v1/things

I finally figured it out.

It had nothing to do with URI or URL.

When i read the values from a property file, the beginning "/" was being stripped from "/api/v1/things"

The value in the string was "api/v1/things". (no quotes of course). That was my issue.

I'll leave the question up so others can learn from my faux pas.

Gaaaaaa.

答案1

得分: 3

问题部分是由于没有使用正确的技术术语造成的:

  • www.theothercompany.com 是一个主机名,而不是“basePath”。
  • /api/v1/things 是一个路径,而不是“suffixPath”。

显然,你想构建一个分层的URI,但是你使用的其中一个构造函数,是设计用来构造一个不透明的URI,它期望的参数是schemessp(scheme特定部分)和fragment

构造函数的文档精确地描述了结果:

> 此构造函数首先使用给定的组件构建字符串形式的URI,过程如下:
> 1. 最初,结果字符串为空。
> 2. 如果给定了方案(scheme),则将其附加到结果字符串,后跟冒号字符(:)。
> 3. 如果给定了特定于方案的部分(ssp),则将其附加。任何不是合法URI字符的字符都会被引用
> 4. 最后,如果给定了片段(fragment),则会附加一个井号字符(#)到字符串,后跟片段。任何不是合法URI字符的字符都会被引用。

导致了 https:www.theothercompany.com#/api/v1/things

因为你想构建一个由schemehostpath组成的分层URI,第二个构造函数才是正确的选择:

> #### public URI​(String scheme, String host, String path, String fragment)
> 从给定的组件构造一个分层URI。

因此,使用 new URI(myscheme , basePath , suffixPath, "") 将得到 https://www.theothercompany.com/api/v1/things#

当你将其更改为 new URI(myscheme , basePath , suffixPath, null),你将得到 https://www.theothercompany.com/api/v1/things

这说明了为什么命名工厂方法优于重载的构造函数,因为两个构造函数之间仅有一个参数不同的语义差异并不是很直观。


¹ 或者通过手动指定语法元素来构造分层URI,这很少需要

英文:

The problem is partially caused by not using the correct technical terms:

  • www.theothercompany.com is a host name, not a “basePath”.
  • /api/v1/things is the path, not a “suffixPath”

Obviously, you want to construct a hierarchical URI, but one of the constructors you use, is designed to construct an opaque URI¹, expecting the arguments scheme, ssp (scheme specific part), and fragment.

The constructor’s documentation precisely describes the outcome:

> This constructor first builds a URI in string form using the given components as follows:
> 1. Initially, the result string is empty.
> 2. If a scheme is given then it is appended to the result, followed by a colon character (':').
> 3. If a scheme-specific part is given then it is appended. Any character that is not a legal URI character is quoted.
> 4. Finally, if a fragment is given then a hash character ('#') is appended to the string, followed by the fragment. Any character that is not a legal URI character is quoted.

leading to https:www.theothercompany.com#/api/v1/things.

Since you want to construct a hierarchical URI composed of scheme, host, and path, the second constructor is the right one:

> #### public URI​(String scheme, String host, String path, String fragment)
> Constructs a hierarchical URI from the given components.

So using new URI(myscheme , basePath , suffixPath, "") leads to https://www.theothercompany.com/api/v1/things#.

When you change it to new URI(myscheme , basePath , suffixPath, null), you’ll get https://www.theothercompany.com/api/v1/things.

This demonstrates why named factories are preferable over overloaded constructors, as such a semantic difference between two constructors only differing by one parameter, is not very intuitive.


¹ or to construct a hierarchical URI by specifying the syntactical elements manually, which is rarely needed

huangapple
  • 本文由 发表于 2020年8月28日 09:25:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/63626194.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定