How to compare two URLs in java?

前端 未结 4 1242
逝去的感伤
逝去的感伤 2020-12-03 21:56

Here\'s a simple problem - given two urls, is there some built-in method, or an Apache library that decides whether they are (logically) equal?

For example, these tw

4条回答
  •  天命终不由人
    2020-12-03 22:14

    The following may work for you - it validates that 2 urls are equal, allows the parameters to be supplied in different orders, and allows a variety of options to be configured, that being:

    • Is the host case sensitive
    • Is the path case sensitive
    • Are query string parameters case sensitive
    • Are query string values case sensitive
    • Is the scheme case sensitive

    You can test it like so:

    class Main {
    
      public static void main(String[] args) 
      {
          UrlComparer urlComparer = new UrlComparer();
    
          expectResult(false, "key a case different", urlComparer.urlsMatch("//test.com?A=a&B=b", "//test.com?a=a&b=b"));
          expectResult(false, "key a case different", urlComparer.urlsMatch("https://WWW.TEST.COM?A=1&b=2", "https://www.test.com?b=2&a=1"));
          expectResult(false, "key a value different", urlComparer.urlsMatch("/test?a=2&A=A", "/test?a=A&a=2"));
          expectResult(false, "key a value different", urlComparer.urlsMatch("https://WWW.TEST.COM?A=a&b=2", "https://www.test.com?b=2&A=1"));
          expectResult(false, "null", urlComparer.urlsMatch("/test", null));
          expectResult(false, "null", urlComparer.urlsMatch(null, "/test"));
          expectResult(false, "port different", urlComparer.urlsMatch("//test.com:22?A=a&B=b", "//test.com:443?A=a&B=b"));
          expectResult(false, "port different", urlComparer.urlsMatch("https://WWW.TEST.COM:8443", "https://www.test.com"));
          expectResult(false, "protocol different", urlComparer.urlsMatch("http://WWW.TEST.COM:2121", "https://www.test.com:2121"));
          expectResult(false, "protocol different", urlComparer.urlsMatch("http://WWW.TEST.COM?A=a&b=2", "https://www.test.com?b=2&A=a"));
          expectResult(true, "both null", urlComparer.urlsMatch(null, null));
          expectResult(true, "host and scheme different case", urlComparer.urlsMatch("HTTPS://WWW.TEST.COM", "https://www.test.com"));
          expectResult(true, "host different case", urlComparer.urlsMatch("https://WWW.TEST.COM:443", "https://www.test.com"));
          expectResult(true, "identical urls", urlComparer.urlsMatch("//test.com:443?A=a&B=b", "//test.com:443?A=a&B=b"));
          expectResult(true, "identical urls", urlComparer.urlsMatch("/test?a=A&a=2", "/test?a=A&a=2"));
          expectResult(true, "identical urls", urlComparer.urlsMatch("https://www.test.com", "https://www.test.com"));
          expectResult(true, "parameter order changed", urlComparer.urlsMatch("https://www.test.com?a=1&b=2&c=522%2fMe", "https://www.test.com?c=522%2fMe&b=2&a=1"));
          expectResult(true, "parmeter order changed", urlComparer.urlsMatch("https://WWW.TEST.COM?a=1&b=2", "https://www.test.com?b=2&a=1"));
        }
    
        public static void expectResult(boolean expectedResult, String msg, boolean result)
        {
          if (expectedResult != result)
            throw new RuntimeException(msg);
        }
    }
    

    UrlComparer.java

    import java.net.URI;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Objects;
    import java.util.TreeMap;
    import org.apache.http.NameValuePair;
    import org.apache.http.client.utils.URLEncodedUtils;
    
    public class UrlComparer
    {
        private boolean hostIsCaseSensitive = false;
        private boolean pathIsCaseSensitive = true;
        private boolean queryStringKeysAreCaseSensitive = true;
        private boolean queryStringValuesAreCaseSensitive = false;
        private boolean schemeIsCaseSensitive = false;
    
        public boolean urlsMatch(String url1, String url2)
        {
            try
            {
                if (Objects.equals(url1, url2))
                    return true;
    
                URI uri1 = new URI(url1);
                URI uri2 = new URI(url2);
    
                // Compare Query String Parameters
                Map mapParams1 = getQueryStringParams(uri1);
                Map mapParams2 = getQueryStringParams(uri2);
                if (!mapsAreEqual(mapParams1, mapParams2, getQueryStringValuesAreCaseSensitive()))
                    return false;
    
                // Compare scheme (http or https)
                if (!stringsAreEqual(uri1.getScheme(), uri2.getScheme(), getSchemeIsCaseSensitive()))
                    return false;
    
                // Compare host
                if (!stringsAreEqual(uri1.getHost(), uri2.getHost(), getHostIsCaseSensitive()))
                    return false;
    
                // Compare path
                if (!stringsAreEqual(uri1.getPath(), uri2.getPath(), getPathIsCaseSensitive()))
                    return false;
    
                // Compare ports
                if (!portsAreEqual(uri1, uri2))
                    return false;
    
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }
    
        protected Map getQueryStringParams(URI uri)
        {
            Map result = getListAsMap(URLEncodedUtils.parse(uri, "UTF-8"), getQueryStringKeysAreCaseSensitive());
    
            return result;
        }
    
        protected boolean stringsAreEqual(String s1, String s2, boolean caseSensitive)
        {
            // Eliminate null cases
            if (s1 == null || s2 == null)
            {
                if (s1 == s2)
                    return true;
    
                return false;
            }
    
            if (caseSensitive)
            {
                return s1.equals(s2);
            }
    
            return s1.equalsIgnoreCase(s2);
        }
    
        protected boolean mapsAreEqual(Map map1, Map map2, boolean caseSensitiveValues)
        {
            for (Map.Entry entry : map1.entrySet())
            {
                String key = entry.getKey();
                String map1value = entry.getValue();
                String map2value = map2.get(key);
    
                if (!stringsAreEqual(map1value, map2value, caseSensitiveValues))
                    return false;
            }
            for (Map.Entry entry : map2.entrySet())
            {
                String key = entry.getKey();
                String map2value = entry.getValue();
                String map1value = map2.get(key);
    
                if (!stringsAreEqual(map1value, map2value, caseSensitiveValues))
                    return false;
            }
    
            return true;
        }
    
        protected boolean portsAreEqual(URI uri1, URI uri2)
        {
            int port1 = uri1.getPort();
            int port2 = uri2.getPort();
    
            if (port1 == port2)
                return true;
    
            if (port1 == -1)
            {
                String scheme1 = (uri1.getScheme() == null ? "http" : uri1.getScheme()).toLowerCase();
                port1 = scheme1.equals("http") ? 80 : 443;
            }
            if (port2 == -1)
            {
                String scheme2 = (uri2.getScheme() == null ? "http" : uri2.getScheme()).toLowerCase();
                port2 = scheme2.equals("http") ? 80 : 443;
            }
    
            boolean result = (port1 == port2);
    
            return result;
        }
    
        protected Map getListAsMap(List list, boolean caseSensitiveKeys)
        {
            Map result;
    
            if (caseSensitiveKeys)
            {
                result = new HashMap();
            }
            else
            {
                result = new TreeMap(String.CASE_INSENSITIVE_ORDER);
            }
    
            for (NameValuePair param : list)
            {
                if (caseSensitiveKeys)
                {
                    if (!result.containsKey(param.getName()))
                        result.put(param.getName(), param.getValue());
                }
                else
                {
                    result.put(param.getName(), param.getValue());
                }
            }
    
            return result;
        }
    
        public boolean getSchemeIsCaseSensitive()
        {
            return schemeIsCaseSensitive;
        }
    
        public void setSchemeIsCaseSensitive(boolean schemeIsCaseSensitive)
        {
            this.schemeIsCaseSensitive = schemeIsCaseSensitive;
        }
    
        public boolean getHostIsCaseSensitive()
        {
            return hostIsCaseSensitive;
        }
    
        public void setHostIsCaseSensitive(boolean hostIsCaseSensitive)
        {
            this.hostIsCaseSensitive = hostIsCaseSensitive;
        }
    
        public boolean getPathIsCaseSensitive()
        {
            return pathIsCaseSensitive;
        }
    
        public void setPathIsCaseSensitive(boolean pathIsCaseSensitive)
        {
            this.pathIsCaseSensitive = pathIsCaseSensitive;
        }
    
        public boolean getQueryStringKeysAreCaseSensitive()
        {
            return queryStringKeysAreCaseSensitive;
        }
    
        public void setQueryStringKeysAreCaseSensitive(boolean queryStringKeysAreCaseSensitive)
        {
            this.queryStringKeysAreCaseSensitive = queryStringKeysAreCaseSensitive;
        }
    
        public boolean getQueryStringValuesAreCaseSensitive()
        {
            return queryStringValuesAreCaseSensitive;
        }
    
        public void setQueryStringValuesAreCaseSensitive(boolean queryStringValuesAreCaseSensitive)
        {
            this.queryStringValuesAreCaseSensitive = queryStringValuesAreCaseSensitive;
        }
    
    }
    

提交回复
热议问题