#java #spring-boot #http #servlets
Вопрос:
Я пытаюсь регистрировать запросы и ответы с помощью пользовательского класса регистратора. Все это прекрасно работало, пока я не начал получать Http-запросы с типами «составные/данные».
С тех пор все отправленные типы «составных/данных» выдают ошибки и не работают должным образом.
Сначала я получил сообщение об ошибке: Не удалось обработать детали, так как не была предоставлена конфигурация из нескольких частей
Поэтому я попытался схватить эти конкретные составные ответы и управлять ими по-разному, но безрезультатно. Я убрал супер.doDispatcher(req, res) Я не уверен, что это правильный путь.
Вот мой класс логгера:
public class LoggableDispatcherServlet extends DispatcherServlet {
private final Log logger = LogFactory.getLog(getClass());
@Override
protected void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception {
if (!(request instanceof ContentCachingRequestWrapper)) {
request = new ContentCachingRequestWrapper(request);
}
if (!(response instanceof ContentCachingResponseWrapper)) {
response = new ContentCachingResponseWrapper(response);
}
HandlerExecutionChain handler = getHandler(request);
boolean mulipart = false;
try {
if (request.getContentType() != null amp;amp; request.getContentType().toLowerCase().contains("multipart/form-data")){
logger.info("MULTIPART FILE RECEIVED");
mulipart = true;
}else
super.doDispatch(request, response);
}catch(Exception e){
logger.error(e.getMessage(), e);
}finally {
if (mulipart){
response = new ContentCachingResponseWrapper(response);
log(request, null, handler);
updateResponse(response);
} else {
log(request, response, handler);
updateResponse(response);
}
}
}
private void log(HttpServletRequest requestToCache, HttpServletResponse responseToCache, HandlerExecutionChain handler) {
LogMessage log = new LogMessage();
log.setHttpMethod(requestToCache.getMethod());
log.setUrl(requestToCache.getRequestURI());
log.setClientIp(requestToCache.getRemoteAddr());
log.setJavaMethod(handler.toString());
if(responseToCache != null){
log.setHttpStatus(responseToCache.getStatus());
log.setResponse(getResponsePayload(responseToCache));
}
logger.info(log);
}
private String getResponsePayload(HttpServletResponse response) {
ContentCachingResponseWrapper wrapper = WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
if (wrapper != null) {
byte[] buf = wrapper.getContentAsByteArray();
if (buf.length > 0) {
int length = Math.min(buf.length, 5120);
try {
return new String(buf, 0, length, wrapper.getCharacterEncoding());
}
catch (UnsupportedEncodingException e) {
logger.error(e.getMessage(), e);
}
}
}
return "[unknown]";
}
private void updateResponse(HttpServletResponse response) throws IOException {
ContentCachingResponseWrapper responseWrapper =
WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
responseWrapper.copyBodyToResponse();
}
}
Он завершается ошибкой в части updateResponse(ответ), когда multipart = true. Я пытался отправлять разные ответы, я бы жил с отправкой даже пустого ответа, но он просто неправильно его обрабатывает, и класс не переходит к контроллеру, когда он состоит из нескольких частей.
Обновить:
Если я удалю класс регистратора, то запрос отправится прямо на контроллер, и он будет работать идеально.
Именно так инициализируются компоненты:
import com.altair.autoTester.logs.LoggableDispatcherServlet;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.DispatcherServlet;
@Configuration
public class LogsConfig {
@Bean
public ServletRegistrationBean dispatcherRegistration() {
return new ServletRegistrationBean(dispatcherServlet());
}
@Bean(name = DispatcherServletAutoConfiguration.DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)
public DispatcherServlet dispatcherServlet() {
return new LoggableDispatcherServlet();
}
Ответ №1:
У вас есть else
то, чего, вероятно, там быть не должно.
if (request.getContentType() != null amp;amp; request.getContentType().toLowerCase().contains("multipart/form-data")){
logger.info("MULTIPART FILE RECEIVED");
mulipart = true;
}else
super.doDispatch(request, response);
должно быть
if (request.getContentType() != null amp;amp; request.getContentType().toLowerCase().contains("multipart/form-data")){
logger.info("MULTIPART FILE RECEIVED");
mulipart = true;
}
super.doDispatch(request, response);
Комментарии:
1. Когда я исполню » супер. doDispatch(запрос, ответ)’ с составным содержимым я получаю ошибку, указанную выше: «Не удается обработать детали, поскольку конфигурация из нескольких частей не была предоставлена».
2. Работает ли ваш код при удалении сервлета ведения журнала?
3. Да, это работает. Он идет прямо к контроллеру и выполняет функции нормально, с помощью ServletDispatcher он даже не попадает на контроллер
4. Просто чтобы быть уверенным,
org.springframework.web.servlet.DispatcherServlet
мы ведь об этом говорим, верно? Создается ли он внутри контекста Spring (он же @Bean)?5. правильно, это класс, который я использую, и он инициализирован аннотацией @Bean. Я обновил ответ с помощью класса инициализации