我有一个简单的回声控制器
@RestController
public class EchoController {
@GetMapping(path = "/param", produces = MediaType.TEXT_PLAIN_VALUE)
String echoParam(@RequestParam("p") String paramValue) {
return paramValue;
}
@GetMapping(path = "/path-variable/{val}", produces = MediaType.TEXT_PLAIN_VALUE)
String echoPathVariable(@PathVariable("val") String val) {
return val;
}
}
Run Code Online (Sandbox Code Playgroud)
它的一种方法与它所呈现的参数的值相呼应;第二个对通过 URI 提供的值执行相同的操作。
我有以下测试:
@Autowired
private WebTestClient webTestClient;
@Test
public void rawPlus_inQueryParam() {
String value = "1+1";
String response = getValueEchoedThroughQueryParam(value);
assertThat(response, is(equalTo(value)));
}
@Test
public void urlencodedPlus_inQueryParam() {
String value = "1%2B1";
String response = getValueEchoedThroughQueryParam(value);
assertThat(response, is(equalTo(value)));
}
private String getValueEchoedThroughQueryParam(String value) {
return webTestClient.get()
.uri(builder -> {
return builder
.path("/param")
.queryParam("p", value)
.build();
})
.exchange()
.expectStatus().is2xxSuccessful()
.expectBody(String.class)
.returnResult()
.getResponseBody();
}
Run Code Online (Sandbox Code Playgroud)
这两个测试都只是通过查询参数发送一个字符串,读取响应并断言内容被正确回显。
第一次测试失败:
java.lang.AssertionError:
Expected: is "1+1"
but: was "1 1"
Run Code Online (Sandbox Code Playgroud)
第二次测试通过。
看起来在第二个测试中,WebTestClienturl 对值进行了编码(实际上,它只是对百分比字符进行了 url 编码),然后网络服务器对其进行了 url 解码,一切正常。但是,在第一次测试中,客户端确实没有URL编码,加上性格,但服务器做URL解码它,因此它得到一个空格字符。
这看起来是不一致的。我怀疑我可以做一些愚蠢的事情来导致它,因为一切都在默认模式下工作;实际上,我在这里展示的控制器几乎是应用程序唯一的代码(Application 类本身是默认的,生成后我没有接触它)。
只是为了比较:在 URI 中传递相同的数据时,一切正常。以下测试通过:
@Test
public void rawPlus_inPathVariable() {
String value = "1+1";
String response = getValueEchoedThroughPathVariable(value);
assertThat(response, is(equalTo(value)));
}
@Test
public void urlencodedPlus_inPathVariable() {
String value = "1%2B1";
String response = getValueEchoedThroughPathVariable(value);
assertThat(response, is(equalTo(value)));
}
private String getValueEchoedThroughPathVariable(String value) {
return webTestClient.get()
.uri("/path-variable/" + value)
.exchange()
.expectStatus().is2xxSuccessful()
.expectBody(String.class)
.returnResult()
.getResponseBody();
}
Run Code Online (Sandbox Code Playgroud)
问题是:
WebTestClient?如果我不手动对其进行 url 编码,它会由网络服务器进行 url 解码;如果我这样做,它会第二次进行 url 编码,因此服务器会(在 url 解码后)获得 url 解码的版本。Spring Boot 版本是2.1.4.RELEASE(撰写本文时的最新版本)。
POM如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.4.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>springboot-plus-in-query-string</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-plus-in-query-string</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Run Code Online (Sandbox Code Playgroud)
该项目在 GitHub 上可用:https : //github.com/rpuch/springboot-plus-in-query-string
只需运行测试 ( mvn clean test)。
小智 6
看到这个问题
理解这一点的关键是,不同程度的编码应用于 URI 模板与 URI 变量。换句话说:
http://example.com/a/{b}/c?q={q}&p={p}除了 URI 变量占位符之外,URI 模板就是一切。然而,您展示的代码片段只构建了一个没有任何变量的 URI 文字,因此无论使用哪种方法,级别编码都是相同的,只有非法字符。
所以它也必须是这样的:
.queryParam("foo", "{foo}").buildAndExpand(foo)
因此,我们的想法是使用类似的东西:
builder
.path("/param")
.queryParam("p", "{value}")
.build(value)
Run Code Online (Sandbox Code Playgroud)
获取编码的查询参数。
| 归档时间: |
|
| 查看次数: |
2258 次 |
| 最近记录: |