#java #spring #spring-boot #header #request-headers
#java #весна #spring-boot #заголовок #запрос-заголовки
Вопрос:
Есть ли какая-либо возможность добавить значение по умолчанию ко всем @RequestHeader
в spring boot?
@RequestHeader(value = "User-Accept-Language", defaultValue = "en-IN") String localeCd
Я копирую / вставляю во все API. Любая помощь, чтобы избежать дублирования кода!!
Комментарии:
1. Вы можете использовать фильтр
Ответ №1:
Я не нашел ничего уже сделанного для создания аннотации для добавления заголовка со значением, поэтому я сделал свой собственный. Вот код, очень простой, я сделал это с помощью spring AOP
- Я создал классы аннотаций
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ResponseHeader { public String key() default ""; public String value() default ""; }
и тот, который содержит массив аннотаций заголовков
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface ResponseHeaders { public ResponseHeader[] headers(); }
- Класс AOP для перехвата restControllers (вы можете настроить AOP для настройки собственного pointcut по своему усмотрению:
import YOUR_PACKAGE_ANNOTATION.ResponseHeaders; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletResponse; import java.util.List; /** * Aspect for inserting headers on the methods of the @RestController annotated classes */ @Aspect @Component public class ResponseHeadersAnnotation { /** * Pointcut for filtering just classes with @RestController annotation */ @Pointcut("@within(org.springframework.web.bind.annotation.RestController)") public void restControllerClass() { } /** * It adds the headers to the response of the method of the controller * * @param responseHeaders */ @After("restControllerClass() amp;amp; @annotation(responseHeaders)") public void addHeaders(final ResponseHeaders responseHeaders) { final HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse(); List.of(responseHeaders.headers()).forEach(responseHeader -> response.setHeader(responseHeader.key(), responseHeader.value())); } }
- Вот пример того, как его использовать в контроллере:
@GetMapping(value = {"/ServiceTicketCollection", "/ServiceRequestCollection"}) @ResponseHeaders(headers = { @ResponseHeader(key = "cookie1", value = "value1"), @ResponseHeader(key = "cookie2, value = "value2") }) public Object restControllerMethod() { ... }
Ответ №2:
Это пример того, как предоставить значение по умолчанию для заголовка с помощью spring WebFlux
@Component
public class CorrelationIdFilter implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
var correlationId = exchange.getRequest().getHeaders().getFirst(CORRELATION_ID_HEADER);
if (correlationId == null || correlationId.isEmpty()) {
correlationId = UUID.randomUUID().toString();
ServerHttpRequest mutatedRequest = exchange.getRequest()
.mutate()
.header(CORRELATION_ID_HEADER, correlationId)
.build();
exchange = exchange
.mutate()
.request(mutatedRequest)
.build();
}
exchange.getResponse().getHeaders().add(CORRELATION_ID_HEADER, correlationId);
return chain.filter(exchange);
}
}
И это для Spring web
@Component
public class CorrelationIdFilter implements Filter {
static final String CORRELATION_ID_HEADER = "X-Correlation-ID";
@Override
public void init(FilterConfig filterConfig) {
// empty
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String correlationId = httpRequest.getHeader(CORRELATION_ID_HEADER);
if (correlationId == null) {
correlationId = XidFactory.nextXid();
((HttpServletResponse) response).addHeader(CORRELATION_ID_HEADER, correlationId);
}
chain.doFilter(request, response);
}
@Override
public void destroy() {
// empty
}
}
Комментарии:
1. Лучше использовать OncePerRequestFilter и пропустить фильтрацию, если у вас уже есть заголовок
2. Я получаю
[org.springframework.web.bind.MissingRequestHeaderException: Missing request header 'User-Accept-Language' for method parameter of type String]
исключение3. Проверьте, выполняется ли фильтр. Если у вас есть эта ошибка, то, скорее всего, фильтр не выполняется. Также вы можете последовать совету @EugeneMakarenko и преобразовать этот фильтр в OncePerRequestFilter . Для этого все, что вам нужно сделать, это расширить свой фильтр из OncePerRequestFilter и реализовать метод doFilterInternal
4. неправильный пример, потому что вопрос касался заголовка запроса, а не ответа