Я попробовал ваш код и обнаружил некоторые ошибки в обработчике исключений, когда вы читали из InputStream
:
Writer writer = new StringWriter();
byte[] buffer = new byte[1024];
//Reader reader2 = new BufferedReader(new InputStreamReader(request.getInputStream()));
InputStream reader = request.getInputStream();
int n;
while ((n = reader.read(buffer)) != -1) {
writer.toString();
}
String retval = writer.toString();
retval = "";
Я заменил ваш код на этот:
BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()));
String line = "";
StringBuilder stringBuilder = new StringBuilder();
while ( (line=reader.readLine()) != null ) {
stringBuilder.append(line).append("\n");
}
String retval = stringBuilder.toString();
Тогда я могу читать из InputStream
в обработчике исключений, это работает!
Если вы все еще не можете прочитать из InputStream
, я предлагаю вам проверить, как вы отправляете XML-данные POST в тело запроса.
Вам следует учитывать, что вы можете использовать Inputstream
только один раз за запрос, поэтому я советую вам проверить, нет ли других вызовов getInputStream()
. Если вам нужно вызывать его два или более раз, вы должны написать пользовательский HttpServletRequestWrapper
, подобный этому, чтобы сделать копию тела запроса, чтобы вы могли читать его несколько раз.
UPDATE
Ваши комментарии помогли мне воспроизвести проблему. Вы используете аннотацию @RequestBody, поэтому верно, что вы не вызываете getInputStream()
, но Spring вызывает ее, чтобы получить тело запроса. Взгляните на класс org.springframework.web.bind.annotation.support.HandlerMethodInvoker
: если вы используете @RequestBody
, этот класс вызывает метод resolveRequestBody
и так далее ... наконец, вы больше не можете читать InputStream
из вашего ServletRequest
. Если вы все еще хотите использовать @RequestBody
и getInputStream()
в своем собственном методе, вам нужно обернуть запрос в пользовательский HttpServletRequestWrapper
, чтобы сделать копию тела запроса, чтобы вы могли вручную прочитать его несколько раз.
Это моя обертка:
public class CustomHttpServletRequestWrapper extends HttpServletRequestWrapper {
private static final Logger logger = Logger.getLogger(CustomHttpServletRequestWrapper.class);
private final String body;
public CustomHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
StringBuilder stringBuilder = new StringBuilder();
BufferedReader bufferedReader = null;
try {
InputStream inputStream = request.getInputStream();
if (inputStream != null) {
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line).append("\n");
}
} else {
stringBuilder.append("");
}
} catch (IOException ex) {
logger.error("Error reading the request body...");
} finally {
if (bufferedReader != null) {
try {
bufferedReader.close();
} catch (IOException ex) {
logger.error("Error closing bufferedReader...");
}
}
}
body = stringBuilder.toString();
}
@Override
public ServletInputStream getInputStream() throws IOException {
final StringReader reader = new StringReader(body);
ServletInputStream inputStream = new ServletInputStream() {
public int read() throws IOException {
return reader.read();
}
};
return inputStream;
}
}
Тогда вам нужно написать простое Filter
, чтобы обернуть запрос:
public class MyFilter implements Filter {
public void init(FilterConfig fc) throws ServletException {
}
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
chain.doFilter(new CustomHttpServletRequestWrapper((HttpServletRequest)request), response);
}
public void destroy() {
}
}
Наконец, вы должны настроить свой фильтр в файле web.xml:
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>test.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Вы можете использовать свой фильтр только для контроллеров, которые действительно в нем нуждаются, поэтому вам следует изменить шаблон URL в соответствии с вашими потребностями.
Если вам нужна эта функция только в одном контроллере, вы также можете сделать копию тела запроса в этом контроллере, когда получите его с помощью аннотации @RequestBody
.