reproduce project link : https://github.com/toohandsome/springdemo/
Spring Boot version: 2.7.1
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
demo:
@Autowired
private RestTemplate restTemplate;
@GetMapping("/runTest")
public String runTest() {
new Thread(new Runnable() {
@Override
public void run() {
for (; ; ) {
try {
HttpHeaders headers = new HttpHeaders();
MultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
map.add("name", "xiaoming");
map.add("age", "123456");
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
HttpEntity<MultiValueMap<String, Object>> param = new HttpEntity<>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity("http://127.0.0.1:8080/postTest", param, String.class);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
for (; ; ) {
try {
HashMap<String, String> objectObjectHashMap = new HashMap<>();
objectObjectHashMap.put("a", "1");
objectObjectHashMap.put("b", "1");
ResponseEntity<String> response = restTemplate.getForEntity("http://127.0.0.1:8080/getParams?a={a}&b={b}", String.class, objectObjectHashMap);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}).start();
return "run success";
}
@GetMapping("/getParams")
public String getParams(String a, int b) {
return "get success";
}
@PostMapping("/postTest")
public String postTest(HttpServletRequest request) {
String age1 = request.getParameter("age");
String name1 = request.getParameter("name");
new Thread(new Runnable() {
@Override
public void run() {
String age2 = request.getParameter("age");
String name2 = request.getParameter("name");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
age2 = request.getParameter("age");
name2 = request.getParameter("name");
}
}).start();
return "post success";
}
call runtest method with browser, it will get error msg like this:
java.lang.IllegalStateException: Optional int parameter 'b' is present but cannot be translated into a null value due to being declared as a primitive type. Consider declaring it as object wrapper for the corresponding primitive type
I found it was because
org.springframework.web.method.annotation.RequestParamMethodArgumentResolver#resolveName
return a null value.
Based on further analysis, i found
org.apache.tomcat.util.http.Parameters#handleQueryParameters
this method parsing parameters found didQueryParameters is true ,Tomcat thinks that the parameter has been resolved.
Can we handle it in this case?
When the RequestParamMethodArgumentResolver cannot get the parameters from the NativeWebRequest, try to get them from query string?
Comment From: toohandsome
If my proposal is feasible, I can submit a PR to fix this problem
Comment From: poutsma
If my proposal is feasible, I can submit a PR to fix this problem
For now, we'd rather have a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem, instead of snippets and screenshots.
Comment From: toohandsome
If my proposal is feasible, I can submit a PR to fix this problem
For now, we'd rather have a complete minimal sample (something that we can unzip or git clone, build, and deploy) that reproduces the problem, instead of snippets and screenshots.
https://github.com/toohandsome/springdemo/
Comment From: toohandsome
it's solved. use AsyncContext run Thread..
@PostMapping("/postTest")
public String postTest(HttpServletRequest request, HttpServletResponse response, String age, String name) {
AsyncContext asyncContext =
request.isAsyncStarted()
? request.getAsyncContext()
: request.startAsync(request, response);
asyncContext.start(new Runnable() {
@Override
public void run() {
String age2 = request.getParameter("age");
String name2 = request.getParameter("name");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
String age3 = request.getParameter("age");
String name3 = request.getParameter("name");
System.out.println("age1: " + age + " , name1: " + name + " , age2: " + age2 + " , name2: " + name2 + " , age3: " + age3 + " , name3: " + name3);
asyncContext.complete();
}
});
return "post success";
}
Comment From: zjunothing
Just pass value into the other thread,not pass in the whole request ...