SpringMVC里通过ResponseBodyAdvice接口实现统一自定义返回逻辑

发布时间 2023-06-06 09:55:32作者: 夏威夷8080

这个org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice接口。

public interface ResponseBodyAdvice<T> {
  // 返回true代表走自定义逻辑
boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType);
  // 实现该方法完成自己的逻辑 @Nullable T beforeBodyWrite(@Nullable T body, MethodParameter returnType, MediaType selectedContentType, Class
<? extends HttpMessageConverter<?>> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response); }

举个简单的示例,我是统一在`/app`接口里加上cookie设置,为什么不在interceptor里做呢?因为在拦截器里设置cookie无效。

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import javax.servlet.http.Cookie;
import java.net.URI;

/**
 * @Author: 夏威夷8080
 * @Date: 1970/6/5 15:04
 */
@ControllerAdvice
@Slf4j
public class AppCookieAdvice implements ResponseBodyAdvice<Object> {
    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        return true;
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType,
                                  MediaType selectedContentType, Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest httpRequest,
                                  ServerHttpResponse httpResponse) {
        ServletServerHttpRequest request = (ServletServerHttpRequest) httpRequest;
        ServletServerHttpResponse response = (ServletServerHttpResponse)httpResponse;
        this.setTargetCookie(request, response);
        return body;
    }

    private void setTargetCookie(ServletServerHttpRequest request, ServletServerHttpResponse response) {
        URI uri = request.getURI();
        String url = uri.toString();
        log.info("Advice里获取的url:{}", url);

        if (StringUtils.isNotBlank(url) && url.contains("/app/")) {

            Cookie[] cookies = request.getServletRequest().getCookies();
            log.info("Advice里request里的的cookie={}", JSON.toJSONString(cookies));
            if (cookies != null && cookies.length > 0) {
                for (int i = 0; i < cookies.length; i++) {
                    Cookie ck = cookies[i];
                    // ...
                }
            }

            Cookie cookieNew = new Cookie('key', 'value');
            cookieNew.setPath("/");
            response.getServletResponse().addCookie(cookieNew);
            log.info("准备设置的cookie={}", JSON.toJSONString(cookieNew));
            
        }
    }
}