How to by default execute the latest version of endpoint in Spring Boot REST?

不羁的心 提交于 2020-02-23 07:14:39

问题


I'm developing Spring Boot v2.2.2.RELEASE and API versioning using Custom Header. By default I want latest version of endpoint to be executed.

Here in below code its X-API-VERSION=2. Before executing the endpoint I need to check mapping and then set the latest version in for the Custom Header and then execute it.

@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();
}

回答1:


If I got your question right, you want that the request sent without X-API-VERSION header will automatically be routed to headerV2() method

This can be done:

Conceptually you'll need a Web Filter that gets executed before the Spring MVC Dispatch Servlet and you'll have to check whether the request contains a header and if it doesn't add a header of the version that you think should be the latest one (from configuration or something).

One caveat here is that the HttpServletRequest doesn't allow adding Headers so you'll have to create a HttpServletRequestWrapper and implement the logic of header addition there.

Here is an example (I've borrowed the implementation from 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";
    }
}

Note that the request is wrapped to add the header as I've explained:

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);
        }

    }

With this implementation (make sure you put the servlet in the package next to controller or something so that the spring boot will recognize it as a component) you'll see:

  1. GET with header X-API-VERSION=1 will be routed to headerV1()
  2. GET with header X-API-VERSION=2 will be routed to headerV2()
  3. GET without X-API-VERSION header will be routed to headerV2()



回答2:


You can add default method without header, like that:

@GetMapping(value = "/student/header")
public StudentV1 headerDefault() {
    return headerV2();
}

Or just remove headers = {"X-API-VERSION=2"} from method that should be current.



来源:https://stackoverflow.com/questions/60144816/how-to-by-default-execute-the-latest-version-of-endpoint-in-spring-boot-rest

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!