Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/.htaccess/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jersey 如何强制URIBuilder.path(…)对参数进行编码,如“0”广告;?这种方法不需要';不要总是正确地用百分比编码参数_Jersey_Jax Rs_Jersey 1.0 - Fatal编程技术网

Jersey 如何强制URIBuilder.path(…)对参数进行编码,如“0”广告;?这种方法不需要';不要总是正确地用百分比编码参数

Jersey 如何强制URIBuilder.path(…)对参数进行编码,如“0”广告;?这种方法不需要';不要总是正确地用百分比编码参数,jersey,jax-rs,jersey-1.0,Jersey,Jax Rs,Jersey 1.0,如何强制URIBuilder.path(…)对参数进行编码,如%AD” URIBuilder的path、replacePath和segment方法并不总是正确地对参数进行百分比编码 当参数包含字符“%”后接两个字符,共同构成URL编码字符时,“%”不编码为“%25” 比如说 URI uri = UriBuilder.fromUri("https://dummy.com").queryParam("param", "%AD"); String test = uri.build().toString

如何强制
URIBuilder.path(…)
对参数进行编码,如
%AD”

URIBuilder
path
replacePath
segment
方法并不总是正确地对参数进行百分比编码

当参数包含字符“%”后接两个字符,共同构成URL编码字符时,“%”不编码为“%25”

比如说

URI uri = UriBuilder.fromUri("https://dummy.com").queryParam("param", "%AD");
String test = uri.build().toString();
“测试”是“”
但它应该是“”(字符“%”编码为“%25”)

当“%”后面的两个字符是十六进制时,方法
UriBuilderImpl.queryParam(…)
的行为如下。也就是说,方法“com.sun.jersey.api.uri.UriComponent.isHexCharacter(char)”对于“%”后面的字符返回true

我认为UriBuilderImpl的行为是正确的,因为我猜它试图不编码已经编码的参数。但在我的场景中,我永远不会尝试使用已经编码的参数创建URL

我该怎么办?

我的Web应用程序使用Jersey,在许多地方,我使用类UriBuilder构建URI,或者调用
UriInfo
对象的方法
getBaseUriBuilder

每次调用方法
queryParam
replaceQueryParam
segment
时,我都可以将“%”替换为“%25”。但我正在寻找一个不那么麻烦的解决方案

如何制作Jersey以返回我自己的UriBuilder实现?

我考虑创建一个扩展UriBuilderImpl的类,该类重写这些方法,并在调用
super.queryParam(…)
或其他任何方法之前执行替换

调用
UriBuilder.fromURL(…)
、UriInfo.getBaseUriBuilder(…)等时,有没有办法让Jersey返回我自己的UriBuilder而不是UriBuilderImpl

查看方法
RuntimeDelegate
,我考虑扩展
RuntimeDelegateImpl
。我的实现将覆盖方法
createUriBuilder(…)
,该方法将返回我自己的
UriBuilder
,而不是
UriBuilderImpl
。 然后,我将添加文件
META-INF/services/javax.ws.rs.ext.RuntimeDelegate
,并在其中添加我的
RuntimeDelegateImpl
的完整类名

问题是jersey-bundle.jar已经包含一个指向
com.sun.jersey.server.impl.provider.RuntimeDelegateImpl
META-INF/services/javax.ws.rs.ext.RuntimeDelegate
,因此容器加载该文件而不是我的
javax.ws.rs.ext.RuntimeDelegate
。因此,它不会加载我的
RuntimeDelegate
实现

是否可以提供我自己的
RuntimeDelegate
实现


我应该采取不同的方法吗?

看看下面的例子是否有用。下面链接的线程对可用函数及其不同输出进行了广泛讨论

以下是:

  • UriBuilder.fromUri(“http://localhost:8080queryParam(“name”,“{value}”).build(“%20”)
  • UriBuilder.fromUri(“http://localhost:8080queryParam(“name”,“{value}”).buildFromEncoded(“%20”)
  • UriBuilder.fromUri(“http://localhost:8080replaceQuery(“name={value}).build(“%20”);
  • UriBuilder.fromUri(“http://localhost:8080replaceQuery(“name={value}).buildFromEncoded(“%20”)
  • 将输出:

  • http://localhost:8080?name=%2520
  • http://localhost:8080?name=%20
  • http://localhost:8080?name=%2520
  • http://localhost:8080?name=%20
  • 通过

    另外,下面的示例显示了如何获得您想要的内容

    URI模板在URI的大多数组件中都是允许的,但它们的值 仅限于特定组件。例如

    UriBuilder.fromPath("{arg1}").build("foo#bar");
    
    将导致对“#”进行编码,从而生成的URI “foo%23bar”。要创建URI“foo#bar”,请使用

    相反。URI模板名称和分隔符从不进行编码,而是进行编码 值在构建URI时进行编码。模板参数正则 在构建URI时忽略表达式,即不进行验证 表演

    UriBuilder 这可以通过泽西岛的帮助或直接通过Java实现:

    UriBuilder.fromUri("https://dummy.com")
            .queryParam("param",
                    UriComponent.encode("%AD",
                        UriComponent.Type.QUERY_PARAM_SPACE_ENCODED))
            .build();
    
    这导致:

    https://dummy.com/?param=%25AD
    
    https://dummy.com/?param=%25AD
    
    或:

    将导致:

    https://dummy.com/?param=%25AD
    
    https://dummy.com/?param=%25AD
    
    对于更复杂的示例(即在查询参数中编码JSON),这种方法也是可能的。假设您有一个类似JSON的
    {“Entity”:{“foo”:“foo”,“bar”:“bar”}
    。使用
    UriComponent
    编码时,查询参数的结果如下所示:

    https://dummy.com/?param=%7B%22Entity%22:%7B%22foo%22:%22foo%22,%22bar%22:%22bar%22%7D%7D
    
    [...]
    import javax.ws.rs.core.UriBuilder;
    import javax.ws.rs.ext.RuntimeDelegate;
    
    import com.sun.jersey.api.uri.UriBuilderImpl;
    import com.sun.ws.rs.ext.RuntimeDelegateImpl;
    // or for jersey2:
    // import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
    // import org.glassfish.jersey.internal.RuntimeDelegateImpl;
    
    public class SomeBaseClass {
    
        [...]
    
        // this is the lengthier custom implementation of UriBuilder
        // replace this with your own according to your needs
        public static class AlwaysPercentEncodingUriBuilder extends UriBuilderImpl {
    
            @Override
            public UriBuilder queryParam(String name, Object... values) {
                Object[] encValues = new Object[values.length];
                for (int i=0; i<values.length; i++) {
                    String value = values[i].toString(); // TODO: better null check here, like in base class
                    encValues[i] = percentEncode(value);
                }
                return super.queryParam(name, encValues);
            }
    
            private String percentEncode(String value) {
                StringBuilder sb = null;
                for (int i=0;  i < value.length(); i++) {
                    char c = value.charAt(i);
                    // if this condition is is true, the base class will not encode the percent
                    if (c == '%' 
                        && i + 2 < value.length()
                        && isHexCharacter(value.charAt(i + 1)) 
                        && isHexCharacter(value.charAt(i + 2))) {
                        if (sb == null) {
                            sb = new StringBuilder(value.substring(0, i));
                        }
                        sb.append("%25");
                    } else {
                        if (sb != null) sb.append(c);
                    }
                }
                return (sb != null) ? sb.toString() : value;
            }
    
            // in jersey2 one can call public UriComponent.isHexCharacter
            // but in jersey1 we need to provide this on our own
            private static boolean isHexCharacter(char c) {
                return ('0' <= c && c <= '9')
                    || ('A' <=c && c <= 'F')
                    || ('a' <=c && c <= 'f');
            }
        }
    
        // here starts the code to hook up the implementation
        public static class AlwaysPercentEncodingRuntimeDelegateImpl extends RuntimeDelegateImpl {
            @Override
            public UriBuilder createUriBuilder() {
                return new AlwaysPercentEncodingUriBuilder();
            }
        }
    
        static {
            RuntimeDelegate myDelegate = new AlwaysPercentEncodingRuntimeDelegateImpl();
            RuntimeDelegate.setInstance(myDelegate);
        }
    
    }
    
    类似这样的JSON甚至可以通过
    @QueryParam
    注入到资源字段/方法参数中(请参阅)



    你用哪种运动衫?在标签中,您提到了Jersey 2,但在
    RuntimeDelegate
    部分,您使用的是Jersey 1的东西。

    可以在启动时手动覆盖Jersey中的默认行为,例如使用调用
    RuntimeDelegate.setInstance(yourRuntimeDelegateImpl)
    的静态帮助程序

    因此,如果您希望有一个UriBuilder对百分比进行编码,即使它们看起来像是已编码序列的一部分,这将类似于:

    https://dummy.com/?param=%7B%22Entity%22:%7B%22foo%22:%22foo%22,%22bar%22:%22bar%22%7D%7D
    
    [...]
    import javax.ws.rs.core.UriBuilder;
    import javax.ws.rs.ext.RuntimeDelegate;
    
    import com.sun.jersey.api.uri.UriBuilderImpl;
    import com.sun.ws.rs.ext.RuntimeDelegateImpl;
    // or for jersey2:
    // import org.glassfish.jersey.uri.internal.JerseyUriBuilder;
    // import org.glassfish.jersey.internal.RuntimeDelegateImpl;
    
    public class SomeBaseClass {
    
        [...]
    
        // this is the lengthier custom implementation of UriBuilder
        // replace this with your own according to your needs
        public static class AlwaysPercentEncodingUriBuilder extends UriBuilderImpl {
    
            @Override
            public UriBuilder queryParam(String name, Object... values) {
                Object[] encValues = new Object[values.length];
                for (int i=0; i<values.length; i++) {
                    String value = values[i].toString(); // TODO: better null check here, like in base class
                    encValues[i] = percentEncode(value);
                }
                return super.queryParam(name, encValues);
            }
    
            private String percentEncode(String value) {
                StringBuilder sb = null;
                for (int i=0;  i < value.length(); i++) {
                    char c = value.charAt(i);
                    // if this condition is is true, the base class will not encode the percent
                    if (c == '%' 
                        && i + 2 < value.length()
                        && isHexCharacter(value.charAt(i + 1)) 
                        && isHexCharacter(value.charAt(i + 2))) {
                        if (sb == null) {
                            sb = new StringBuilder(value.substring(0, i));
                        }
                        sb.append("%25");
                    } else {
                        if (sb != null) sb.append(c);
                    }
                }
                return (sb != null) ? sb.toString() : value;
            }
    
            // in jersey2 one can call public UriComponent.isHexCharacter
            // but in jersey1 we need to provide this on our own
            private static boolean isHexCharacter(char c) {
                return ('0' <= c && c <= '9')
                    || ('A' <=c && c <= 'F')
                    || ('a' <=c && c <= 'f');
            }
        }
    
        // here starts the code to hook up the implementation
        public static class AlwaysPercentEncodingRuntimeDelegateImpl extends RuntimeDelegateImpl {
            @Override
            public UriBuilder createUriBuilder() {
                return new AlwaysPercentEncodingUriBuilder();
            }
        }
    
        static {
            RuntimeDelegate myDelegate = new AlwaysPercentEncodingRuntimeDelegateImpl();
            RuntimeDelegate.setInstance(myDelegate);
        }
    
    }
    
    […]
    导入javax.ws.rs.core.UriBuilder;
    导入javax.ws.rs.ext.RuntimeDelegate;
    导入com.sun.jersey.api.uri.UriBuilderImpl;
    导入com.sun.ws.rs.ext.RuntimeDelegateImpl;
    //或运动衫2:
    //导入org.glassfish.jersey.uri.internal.JerseyUriBuilder;
    //导入org.glassfish.jersey.internal.RuntimeDelegateImpl;
    公共类SomeBaseClass{
    [...]
    //这是UriBuilder更长的自定义实现
    //更换