Я пытаюсь написать метод, который проверяет учетные данные пользователя, и если это правильный синтаксический анализ, отправленный JSON. Он работает нормально, но я не могу получить доступ к JSON. В моем коде есть команда InputStream inputStream = request.getInputStream();, которая должна читать JSON, но каждый раз возвращает org.apache.catalina.connector.CoyoteInputStream@3f1e9348. Взгляните на мой код:
@POST
@Path("auth")
@Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.TEXT_HTML)
public String controller(@Context HttpServletRequest request) {
String authorization = request.getHeader("Authorization");
if (authorization == null) {
authorization = request.getHeader("authorization");
}
String basicHeader = "basic";
if (authorization != null && authorization.toLowerCase().startsWith(basicHeader)) {
String base64Credentials = authorization.substring(basicHeader.length()).trim();
String credentials = new String(Base64.getDecoder().decode(base64Credentials),
Charset.forName("UTF-8"));
String[] values = credentials.split(":", 2);
}
try {
InputStream inputStream = request.getInputStream();
System.out.println(inputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
Когда я пытаюсь использовать request.getReader(), я получаю печально известное исключение IllegalStateException: getInputStream() has already been called for this request. См. Соответствующий фрагмент кода:
if ("POST".equalsIgnoreCase(request.getMethod()))
{
try {
String req = request.getReader().lines().collect(Collectors.joining(System.lineSeparator()));
} catch (IOException e) {
e.printStackTrace();
}
}
Я использую curl для отправки POST:
curl -u myusername:mypasswor -H "Content-Type: application/json"
-X POST -d '{"username":"xyz","password":"xyz"}' localhost




Вы можете получить содержимое тела, объявив параметр в своем методе:
public String controller(String body, @Context HttpServletRequest request)
Но вы также можете получить реализацию JAX-RS для десериализации этого JSON до вашего предполагаемого типа:
public String controller(MyExpectedType body, @Context HttpServletRequest request)
Это должно сработать, потому что вы объявили ожидаемый тип контента, если у вас есть подходящий поставщик (например, jackson-jaxrs ...).
Что касается ошибки входного потока: это, вероятно, связано с тем, что реализация JAXRS контейнера уже проанализировала запрос.
Но если бы вы обрабатывали его в обычном сценарии, например, в сервлете, вам все равно пришлось бы исправить то, как вы его читаете:
В документации для getInputStream указано:
Retrieves the body of the request as binary data using a ServletInputStream. Either this method or getReader() may be called to read the body, not both.
Это означает, что чтобы получить контент, отправленный вашим клиентом, в теле, вам нужно прочитать поток:
String body = request.getReader().lines()
.collect(Collectors.joining("\n"));
Вы также можете использовать API на основе Stream:
byte[] bytes = new byte[request.getContentLength()];
request.getInputStream().read(bytes);
String body = new String(bytes); //you may need to specify the character set
Фактический класс входного потока основан на реализации (предоставляется контейнером), поэтому вам не нужно беспокоиться о CoyoteInputStream.
Мой комментарий относился к вашему первому решению. Однако в вашем отредактированном ответе метод Stream-based API: работает нормально.
Отредактированный ответ :-)
Спасибо! MyExpectedType body - это та часть, которая мне понравилась, так как таким образом я получаю свой JSON.
Как я уже сказал, получается
java.lang.IllegalStateException: getInputStream() has already been called for this request.