У нас есть приложение SpringBoot, и мы используем Джерси для аудита входящих HTTP-запросов.
Мы внедрили фильтр Jersey ContainerRequestFilter для получения входящего HttpServletRequest и использовали метод getParameterMap() HttpServletRequest для извлечения данных запроса и формы и помещения их в наш аудит.
Это соответствует javadoc для getParameterMap():
Параметры запроса — это дополнительная информация, отправляемая вместе с запросом. Для сервлетов HTTP параметры содержатся в строке запроса или опубликованных данных формы.
И вот документация, относящаяся к фильтру:
После обновления SpringBoot мы обнаружили, что getParameterMap() больше не возвращает данные формы, но по-прежнему возвращает данные запроса.
Мы обнаружили, что SpringBoot 2.1 — последняя версия, поддерживающая наш код. В SpringBoot 2.2 версия Jersey была обновлена до 2.29, но при просмотре примечаний к выпуску мы не видим ничего, связанного с этим.
Что изменилось? Что нам нужно изменить для поддержки SpringBoot 2.2 / Jersey 2.29?
Вот упрощенная версия нашего кода:
JerseyRequestFilter – наш фильтр
import javax.annotation.Priority;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.Priorities;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ResourceInfo;
import javax.ws.rs.core.Context;
import javax.ws.rs.ext.Provider;
...
@Provider
@Priority(Priorities.AUTHORIZATION)
public class JerseyRequestFilter implements ContainerRequestFilter {
@Context
private ResourceInfo resourceInfo;
@Context
private HttpServletRequest httpRequest;
...
public void filter(ContainerRequestContext context) throws IOException {
...
requestData = new RequestInterceptorModel(context, httpRequest, resourceInfo);
...
}
...
}
RequestInterceptorModel — карта не заполняется данными формы, только данными запроса
import lombok.Data;
import org.glassfish.jersey.server.ContainerRequest;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ResourceInfo;
...
@Data
public class RequestInterceptorModel {
private Map<String, String[]> parameterMap;
...
public RequestInterceptorModel(ContainerRequestContext context, HttpServletRequest httpRequest, ResourceInfo resourceInfo) throws AuthorizationException, IOException {
...
setParameterMap(httpRequest.getParameterMap());
...
}
...
}
JerseyConfig — наша конфигурация
import com.xyz.service.APIService;
import io.swagger.jaxrs.config.BeanConfig;
import io.swagger.jaxrs.listing.ApiListingResource;
import io.swagger.jaxrs.listing.SwaggerSerializers;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.wadl.internal.WadlResource;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
...
@Component
public class JerseyConfig extends ResourceConfig {
...
public JerseyConfig() {
this.register(APIService.class);
...
// Access through /<Jersey's servlet path>/application.wadl
this.register(WadlResource.class);
this.register(AuthFilter.class);
this.register(JerseyRequestFilter.class);
this.register(JerseyResponseFilter.class);
this.register(ExceptionHandler.class);
this.register(ClientAbortExceptionWriterInterceptor.class);
}
@PostConstruct
public void init()
this.configureSwagger();
}
private void configureSwagger() {
...
}
}
Полный пример
Вот шаги для воссоздания с нашим типовым проектом:
- скачать исходники с гитхаба здесь:
git clone https://github.com/fei0x/so-jerseyBodyIssue
- перейдите в каталог проекта с файлом pom.xml
- запустить проект с помощью:
mvn -Prun
- в новом терминале выполните следующую команду curl, чтобы протестировать веб-службу
curl -X POST \ http://localhost:8012/api/jerseyBody/ping \ -H 'content-type: application/x-www-form-urlencoded' \ -d param=Test%20String
- в логе вы увидите параметры формы
- остановить запущенный проект, ctrl-C
- обновить родительскую версию pom до более новой версии SpringBoot
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.15.RELEASE</version>
to
<groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.2.9.RELEASE</version>
- снова запустите проект:
mvn -Prun
- снова вызовите вызов curl:
curl -X POST \ http://localhost:8012/api/jerseyBody/ping \ -H 'content-type: application/x-www-form-urlencoded' \ -d param=Test%20String
- На этот раз в журнале будут отсутствовать параметры формы