如何在 Spring Boot REST 中默认执行最新版本的端点?
How to by default execute the latest version of endpoint in Spring Boot REST?
我正在使用自定义 Header 开发 Spring Boot v2.2。2.RELEASE 和 API 版本控制。默认情况下,我希望执行最新版本的端点。
下面的代码是 X-API-VERSION=2
。在执行端点之前,我需要检查映射,然后为自定义 Header 设置最新版本,然后执行它。
@GetMapping(value = "/student/header", headers = {"X-API-VERSION=1"})
public StudentV1 headerV1() {
return serviceImpl.headerV1();
}
@GetMapping(value = "/student/header", headers = {"X-API-VERSION=2"})
public StudentV1 headerV2() {
return serviceImpl.headerV2();
}
你可以添加没有header的默认方法,像这样:
@GetMapping(value = "/student/header")
public StudentV1 headerDefault() {
return headerV2();
}
或者只是从应该是当前的方法中删除 headers = {"X-API-VERSION=2"}
。
如果我答对了你的问题,你希望在没有 X-API-VERSION
header 的情况下发送的请求将自动路由到 headerV2()
方法
可以这样做:
从概念上讲,您需要一个在 Spring MVC Dispatch Servlet 之前执行的 Web 过滤器,并且您必须检查请求是否包含 header 以及是否不添加您认为应该是最新版本的 header 版本(来自配置或其他)。
这里需要注意的是,HttpServletRequest 不允许添加 Headers,因此您必须创建一个 HttpServletRequestWrapper 并在那里实现 header 添加的逻辑。
这是一个例子(我从this question那里借用了实现):
// The web filter
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
@Component
@Order(1)
public class LatestVersionFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if(req.getHeader("X-API-VERSION")== null) {
HeaderMapRequestWrapper wrappedRequest = new HeaderMapRequestWrapper(req);
wrappedRequest.addHeader("X-API-VERSION", resolveLastVersion());
filterChain.doFilter(wrappedRequest, servletResponse);
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
private String resolveLastVersion() {
// read from configuration or something
return "2";
}
}
请注意,请求已包装以添加 header,正如我所解释的:
class HeaderMapRequestWrapper extends HttpServletRequestWrapper {
/**
* construct a wrapper for this request
*
* @param request
*/
public HeaderMapRequestWrapper(HttpServletRequest request) {
super(request);
}
private Map<String, String> headerMap = new HashMap<String, String>();
/**
* add a header with given name and value
*
* @param name
* @param value
*/
public void addHeader(String name, String value) {
headerMap.put(name, value);
}
@Override
public String getHeader(String name) {
String headerValue = super.getHeader(name);
if (headerMap.containsKey(name)) {
headerValue = headerMap.get(name);
}
return headerValue;
}
/**
* get the Header names
*/
@Override
public Enumeration<String> getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
for (String name : headerMap.keySet()) {
names.add(name);
}
return Collections.enumeration(names);
}
@Override
public Enumeration<String> getHeaders(String name) {
List<String> values = Collections.list(super.getHeaders(name));
if (headerMap.containsKey(name)) {
values.add(headerMap.get(name));
}
return Collections.enumeration(values);
}
}
使用此实现(确保将 servlet 放在控制器或其他东西旁边的包中,以便 spring 引导将其识别为组件)您将看到:
- GET 与 header
X-API-VERSION=1
将被路由到 headerV1()
- GET 与 header
X-API-VERSION=2
将被路由到 headerV2()
- 没有
X-API-VERSION
的 GET header 将被路由到 headerV2()
我正在使用自定义 Header 开发 Spring Boot v2.2。2.RELEASE 和 API 版本控制。默认情况下,我希望执行最新版本的端点。
下面的代码是 X-API-VERSION=2
。在执行端点之前,我需要检查映射,然后为自定义 Header 设置最新版本,然后执行它。
@GetMapping(value = "/student/header", headers = {"X-API-VERSION=1"})
public StudentV1 headerV1() {
return serviceImpl.headerV1();
}
@GetMapping(value = "/student/header", headers = {"X-API-VERSION=2"})
public StudentV1 headerV2() {
return serviceImpl.headerV2();
}
你可以添加没有header的默认方法,像这样:
@GetMapping(value = "/student/header")
public StudentV1 headerDefault() {
return headerV2();
}
或者只是从应该是当前的方法中删除 headers = {"X-API-VERSION=2"}
。
如果我答对了你的问题,你希望在没有 X-API-VERSION
header 的情况下发送的请求将自动路由到 headerV2()
方法
可以这样做:
从概念上讲,您需要一个在 Spring MVC Dispatch Servlet 之前执行的 Web 过滤器,并且您必须检查请求是否包含 header 以及是否不添加您认为应该是最新版本的 header 版本(来自配置或其他)。
这里需要注意的是,HttpServletRequest 不允许添加 Headers,因此您必须创建一个 HttpServletRequestWrapper 并在那里实现 header 添加的逻辑。
这是一个例子(我从this question那里借用了实现):
// The web filter
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.IOException;
@Component
@Order(1)
public class LatestVersionFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
if(req.getHeader("X-API-VERSION")== null) {
HeaderMapRequestWrapper wrappedRequest = new HeaderMapRequestWrapper(req);
wrappedRequest.addHeader("X-API-VERSION", resolveLastVersion());
filterChain.doFilter(wrappedRequest, servletResponse);
} else {
filterChain.doFilter(servletRequest, servletResponse);
}
}
private String resolveLastVersion() {
// read from configuration or something
return "2";
}
}
请注意,请求已包装以添加 header,正如我所解释的:
class HeaderMapRequestWrapper extends HttpServletRequestWrapper {
/**
* construct a wrapper for this request
*
* @param request
*/
public HeaderMapRequestWrapper(HttpServletRequest request) {
super(request);
}
private Map<String, String> headerMap = new HashMap<String, String>();
/**
* add a header with given name and value
*
* @param name
* @param value
*/
public void addHeader(String name, String value) {
headerMap.put(name, value);
}
@Override
public String getHeader(String name) {
String headerValue = super.getHeader(name);
if (headerMap.containsKey(name)) {
headerValue = headerMap.get(name);
}
return headerValue;
}
/**
* get the Header names
*/
@Override
public Enumeration<String> getHeaderNames() {
List<String> names = Collections.list(super.getHeaderNames());
for (String name : headerMap.keySet()) {
names.add(name);
}
return Collections.enumeration(names);
}
@Override
public Enumeration<String> getHeaders(String name) {
List<String> values = Collections.list(super.getHeaders(name));
if (headerMap.containsKey(name)) {
values.add(headerMap.get(name));
}
return Collections.enumeration(values);
}
}
使用此实现(确保将 servlet 放在控制器或其他东西旁边的包中,以便 spring 引导将其识别为组件)您将看到:
- GET 与 header
X-API-VERSION=1
将被路由到headerV1()
- GET 与 header
X-API-VERSION=2
将被路由到headerV2()
- 没有
X-API-VERSION
的 GET header 将被路由到headerV2()