В моем проекте весенней загрузки я использую шаблоны бесплатных маркеров для образцов форм. Мне нужно было добавить фильтр, чтобы читать полезные данные и делать что-то еще. Я знаю, если вы читаете полезную нагрузку в фильтре, вам нужно сбросить тело запроса. Потому что это можно прочитать один раз. Так как я столкнулся с этой проблемой раньше, я знал, что я должен был использовать обертку. Я ожидал решить мою проблему, как и раньше. Однако в контроллере все поля во входных объектах являются нулевыми.
Чего мне здесь не хватает?
Мой фильтр:
public class KfsInMsgFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
final HttpServletResponse response = (HttpServletResponse) servletResponse;
Map<String, String[]> extraParams = new TreeMap<String, String[]>();
WrappedRequest wrappedRequest = new WrappedRequest(request, extraParams);
String body = IOUtils.toString(new BufferedReader(new InputStreamReader(wrappedRequest.getInputStream(), Constants.UTF_8)));
// doing some stuff using body
// ....
// resetting payload
wrappedRequest.resetStream(body.getBytes(Constants.UTF_8));
...
}
}
Класс WrappedRequest:
@Slf4j
public class WrappedRequest extends HttpServletRequestWrapper {
private final Map<String, String[]> modifiableParameters;
private ResettableServletInputStream servletStream;
private byte[] rawData;
private HttpServletRequest request;
private String payload;
/**
* Create a new request wrapper that will merge additional parameters into
* the request object without prematurely reading parameters from the
* original request.
*
* @param request
* @param additionalParams
*/
public WrappedRequest(final HttpServletRequest request,
final Map<String, String[]> additionalParams) {
super(request);
this.request = request;
this.modifiableParameters = new TreeMap<String, String[]>();
this.modifiableParameters.putAll(additionalParams);
this.servletStream = new ResettableServletInputStream();
}
/**
* @param newRawData
*/
public void resetStream(byte[] newRawData) {
servletStream.stream = new ByteArrayInputStream(newRawData);
}
/**
* @return
* @throws IOException
*/
@Override
public ServletInputStream getInputStream() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return servletStream;
}
/**
* @return
* @throws IOException
*/
@Override
public BufferedReader getReader() throws IOException {
if (rawData == null) {
rawData = IOUtils.toByteArray(this.request.getReader());
servletStream.stream = new ByteArrayInputStream(rawData);
}
return new BufferedReader(new InputStreamReader(servletStream, Constants.UTF_8));
}
/**
* @return
*/
private String getBodyAsString() {
StringBuffer buff = new StringBuffer();
buff.append(" BODY_DATA START [ ");
char[] charArr = new char[getContentLength()];
try {
BufferedReader reader = new BufferedReader(getReader());
reader.read(charArr, 0, charArr.length);
reader.close();
} catch (IOException e) {
log.error("", e);
}
buff.append(charArr);
buff.append(" ] BODY_DATA END ");
return buff.toString();
}
/**
* @return
*/
public String getPayload() {
return payload;
}
/**
* @param payload
*/
public void setPayload(String payload) {
this.payload = payload;
}
private static class ResettableServletInputStream extends ServletInputStream {
private InputStream stream;
@Override
public int read() throws IOException {
return stream.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener readListener) {
}
}
}
Тело, которое я ожидал получить в контроллере :
Что я получаю:
@PostMapping(value = "/edit")
public String editPlatform(EditInfo editInfo, Model model) {
Optional<Platform> p = platformService.findById(editInfo.getId());
List<SafeCustodyOffice> officeList = safeCustodyOfficeService.getAll();
if (p.isPresent()) {
model.addAttribute("platform", p.get());
model.addAttribute("offices", officeList);
return "platform-edit";
} else {
throw new KfsException(ErrorCodes.KFS19);
}
}
Важно Редактировать:
Я обнаружил кое-что интересное и дал мне подсказки о проблеме. Это может иметь больше смысла для всех, кроме меня.
Я вижу, что тип содержимого ввода изменяет результат следующим образом:
Есть ли обходной путь, чтобы комбинация строки 5 работала так же, как строка 3?