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

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

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

问题

  1. String myScheme = "https";
  2. String myHost = "www.theothercompany.com";
  3. String myPath = "/api/v1/things";
  4. java.net.URL computedFullUrl = null;
  5. String urlToStringValue = "";
  6. String urlToExternalFormValue = "";
  7. String urlToUriStringValue = "";
  8. try {
  9. computedFullUrl = new java.net.URL(myScheme, myHost, myPath);
  10. if (null != computedFullUrl) {
  11. urlToStringValue = computedFullUrl.toString();
  12. urlToExternalFormValue = computedFullUrl.toExternalForm();
  13. urlToUriStringValue = computedFullUrl.toURI().toString();
  14. }
  15. } catch (Exception ex) {
  16. String temp = ex.getMessage();
  17. ex.printStackTrace();
  18. }

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

  1. 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.

  1. String myscheme = "https";
  2. String basePath = "www.theothercompany.com";
  3. 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:

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

or

  1. 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.

  1. import org.springframework.http.HttpHeaders;
  2. import org.springframework.http.MediaType;
  3. import org.springframework.http.ResponseEntity;
  4. import org.springframework.web.reactive.function.client.WebClient;

and

  1. compile group: 'org.springframework.boot', name: 'spring-boot-starter-webflux', version: springBootVersion
  2. compile group: 'org.apache.commons', name: 'commons-lang3', version: commonsLangVersion
  3. compile 'org.projectreactor:reactor-spring:1.0.1.RELEASE'

APPEND

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

  1. String myScheme = "https";
  2. String myHost = "www.theothercompany.com";
  3. String myPath = "/api/v1/things";
  4. java.net.URL computedFullUrl = null;
  5. String urlToStringValue = "";
  6. String urlToExternalFormValue = "";
  7. String urlToUriStringValue = "";
  8. try {
  9. /* this works....or does not exception out */
  10. computedFullUrl = new java.net.URL(myScheme, myHost, myPath);
  11. if (null != computedFullUrl) {
  12. urlToStringValue = computedFullUrl.toString();
  13. urlToExternalFormValue = computedFullUrl.toExternalForm();
  14. urlToUriStringValue = computedFullUrl.toURI().toString();
  15. }
  16. } catch (Exception ex) {
  17. //throw new RuntimeException((ex));
  18. // temporary swallow
  19. String temp = ex.getMessage();
  20. ex.printStackTrace();
  21. }

So the above works.

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

  1. 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:

确定