Springboot 對返回結果ReturnValueHandler 處理實現原理與實現說明

若您想要自定義處理 Spring MVC 中方法的返回結果,您可以使用 HandlerMethodReturnValueHandler 接口進行實現。以下是一個示例:

首先,創建一個實現 HandlerMethodReturnValueHandler 接口的自定義返回結果處理器 CustomReturnValueHandler

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.io.IOException;
import java.lang.reflect.Method;

public class CustomReturnValueHandler implements HandlerMethodReturnValueHandler {

    private final HandlerMethodReturnValueHandler delegate;

    public CustomReturnValueHandler(HandlerMethodReturnValueHandler delegate) {
        this.delegate = delegate;
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        // 在這裏定義您要處理的返回類型條件
        // 此示例中,我們僅處理返回類型爲 long 的方法
        return returnType.getParameterType().equals(long.class);
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType,
                                  ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws IOException {
        // 在這裏進行返回結果的自定義處理邏輯
        // 此示例中,我們將 long 類型的返回結果轉換爲字符串,並進行輸出

        // 轉換爲字符串
        String convertedValue = String.valueOf(returnValue);

        // 獲取 HttpServletResponse
        ServletServerHttpResponse response = new ServletServerHttpResponse(webRequest.getNativeResponse(HttpServletResponse.class));

        // 設置響應內容類型和編碼
        response.getHeaders().setContentType(MediaType.TEXT_PLAIN);
        response.getHeaders().setCharacterEncoding("UTF-8");

        // 將轉換後的結果寫入響應
        response.getBody().write(convertedValue.getBytes("UTF-8"));
    }
}

在上述示例中,我們創建了一個 CustomReturnValueHandler 類,實現了 HandlerMethodReturnValueHandler 接口。在 supportsReturnType() 方法中,我們定義了要處理的返回類型條件,此示例中僅處理返回類型爲 long 的方法。

handleReturnValue() 方法中,我們進行了自定義的返回結果處理邏輯。這裏的示例是將返回結果轉換爲字符串,並將其寫入響應。

接下來,您需要在 Spring MVC 的配置中註冊自定義的返回結果處理器。可以通過實現 WebMvcConfigurer 接口來完成:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import java.util.ArrayList;
import java.util.List;

@Configuration
@EnableWebMvc
public class CustomWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 查找並替換默認的 RequestMappingHandlerAdapter
        for (HttpMessageConverter<?> converter : converters) {
            if (converter instanceof RequestMappingHandlerAdapter) {
                RequestMappingHandlerAdapter adapter = (RequestMappingHandlerAdapter) converter;
                List<HandlerMethodReturnValueHandler> handlers = new ArrayList<>(adapter.getReturnValueHandlers());
                replaceReturnValueHandler(handlers);
                adapter.setReturnValueHandlers(handlers);
                break;
            }
        }
    }

    private void replaceReturnValueHandler(List<HandlerMethodReturnValueHandler> handlers) {
        for (int i = 0; i < handlers.size(); i++) {
            HandlerMethodReturnValueHandler handler = handlers.get(i);
            if (handler.getClass().getSimpleName().equals("RequestResponseBodyMethodProcessor")) {
                handlers.set(i, new CustomReturnValueHandler(handler));
                break;
            }
        }
    }
}

在上述示例中,我們創建了一個 CustomWebMvcConfigurer 類,實現了 WebMvcConfigurer 接口,並重寫了 extendMessageConverters() 方法。在該方法中,我們查找並替換默認的 RequestMappingHandlerAdapter,將其中的 RequestResponseBodyMethodProcessor 替換爲自定義的 CustomReturnValueHandler

請確保將上述類正確配置到您的 Spring MVC 應用程序中,以便自定義處理方法的返回結果。在示例中,我們僅處理返回類型爲 long 的方法,並將返回結果轉換爲字符串進行輸出。您可以根據需要修改和擴展自定義的返回結果處理邏輯。

當您想要通過 WebMvcConfigureraddReturnValueHandlers 方法添加自定義的返回對象處理時,可以按照以下示例進行實現:

首先,創建一個實現 HandlerMethodReturnValueHandler 接口的自定義返回對象處理器 CustomReturnValueHandler,並在其中定義您的自定義處理邏輯:

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;

import java.io.IOException;

public class CustomReturnValueHandler implements HandlerMethodReturnValueHandler {

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        // 在這裏定義您要處理的返回類型條件
        // 例如,處理返回類型爲 YourCustomObject 的方法
        return returnType.getParameterType().equals(YourCustomObject.class);
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType,
                                  ModelAndViewContainer mavContainer, NativeWebRequest webRequest)
            throws IOException {
        // 在這裏進行返回對象的自定義處理邏輯
        // 例如,將返回對象轉換爲 JSON,並寫入響應

        // 將返回對象轉換爲 JSON 字符串
        String jsonString = convertToJson(returnValue);

        // 獲取 HttpServletResponse
        ServletServerHttpResponse response = new ServletServerHttpResponse(webRequest.getNativeResponse(HttpServletResponse.class));

        // 設置響應內容類型和編碼
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        response.getHeaders().setCharacterEncoding("UTF-8");

        // 將 JSON 字符串寫入響應
        response.getBody().write(jsonString.getBytes("UTF-8"));
    }

    private String convertToJson(Object object) {
        // 自定義將對象轉換爲 JSON 的邏輯
        // 例如,使用 Jackson ObjectMapper 進行轉換
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert object to JSON", e);
        }
    }
}

在上述示例中,我們創建了一個 CustomReturnValueHandler 類,實現了 HandlerMethodReturnValueHandler 接口。在 supportsReturnType() 方法中,我們定義了要處理的返回類型條件,例如 YourCustomObject 類型。在 handleReturnValue() 方法中,我們進行了自定義的返回對象處理邏輯,這裏的示例是將返回對象轉換爲 JSON 字符串,並寫入響應。

接下來,在您的 WebMvcConfigurer 配置類中,通過 addReturnValueHandlers() 方法添加自定義的返回對象處理器:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
@EnableWebMvc
public class CustomWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addReturnValueHandlers(List<HandlerMethodReturnValueHandler> returnValueHandlers) {
        // 添加自定義的返回對象處理器
        returnValueHandlers.add(new CustomReturnValueHandler());
    }
}

在上述示例中,我們創建了一個 CustomWebMvcConfigurer 類,實現了 WebMvcConfigurer 接口,並重寫了 addReturnValueHandlers() 方法。在該方法中,我們通過調用 returnValueHandlers.add(new CustomReturnValueHandler()) 將自定義的返回對象處理器 CustomReturnValueHandler 添加到返回對象處理器列表中。

請確保將上述類正確配置到您的 Spring MVC 應用程序中,以便添加自定義的返回對象處理器。在示例中,我們處理返回類型爲 YourCustomObject 的方法,並將返回對象轉換爲 JSON 字符串進行輸出。您可以根據需要修改和擴展自定義的返回對象處理邏輯。

如果您只想添加一個特定的返回結果處理器而不改變整個架構或替換其他默認的處理器,您可以使用WebMvcConfigurerconfigureMessageConverters方法,並添加自定義的HttpMessageConverter來處理返回結果。

以下是一個示例:

import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServletServerHttpResponse;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.IOException;
import java.util.List;

@Configuration
@EnableWebMvc
public class CustomWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        // 創建自定義的 HttpMessageConverter
        CustomHttpMessageConverter customConverter = new CustomHttpMessageConverter();

        // 添加到 converters 列表中
        converters.add(customConverter);
    }

    private static class CustomHttpMessageConverter implements HttpMessageConverter<Object> {

        @Override
        public boolean canRead(Class<?> clazz, MediaType mediaType) {
            // 在這裏定義是否支持讀取指定類型的對象
            return false; // 例如,不支持讀取操作
        }

        @Override
        public boolean canWrite(Class<?> clazz, MediaType mediaType) {
            // 在這裏定義是否支持寫入指定類型的對象
            // 該示例假設只處理返回類型爲 YourCustomObject 的對象
            return YourCustomObject.class.isAssignableFrom(clazz);
        }

        @Override
        public List<MediaType> getSupportedMediaTypes() {
            // 在這裏定義支持的媒體類型
            return List.of(MediaType.TEXT_PLAIN);
        }

        @Override
        public Object read(Class<?> clazz, HttpInputMessage inputMessage)
                throws IOException {
            // 在這裏實現讀取操作的邏輯
            throw new UnsupportedOperationException("Read operation not supported");
        }

        @Override
        public void write(Object object, MediaType contentType, HttpOutputMessage outputMessage)
                throws IOException {
            // 在這裏實現寫入操作的邏輯
            // 該示例假設將 YourCustomObject 寫入爲文本
            String text = object.toString();

            ServletServerHttpResponse response = (ServletServerHttpResponse) outputMessage;
            response.getServletResponse().setContentType(contentType.toString());
            response.getServletResponse().getWriter().write(text);
        }
    }
}

在上述示例中,我們創建了一個內部類 CustomHttpMessageConverter,實現了 HttpMessageConverter 接口。在該類中,我們定義了處理返回類型爲 YourCustomObject 的對象,並將其寫入響應的邏輯。此示例中,我們將其寫入爲純文本格式。

然後,我們在 CustomWebMvcConfigurer 類的 configureMessageConverters 方法中添加了自定義的 CustomHttpMessageConverter 實例到 converters 列表中。

請確保將上述類正確配置到您的 Spring MVC 應用程序中,以便添加自定義的返回結果處理器。在示例中,我們處理返回類型爲 YourCustomObject 的對象,並將其寫入爲文本。您可以根據需要修改和擴展自定義的返回結果處理邏輯。

確實,您可以使用攔截器來處理返回結果。通過實現HandlerInterceptor接口並重寫postHandle方法,您可以在請求處理完成後對返回結果進行自定義處理。以下是一個示例:

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class CustomInterceptor implements HandlerInterceptor {

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        // 在這裏對返回結果進行自定義處理
        // 例如,將返回對象轉換爲 JSON 並寫入響應

        // 獲取返回結果
        Object returnValue = modelAndView.getModel().get("returnValue");

        // 將返回對象轉換爲 JSON 字符串
        String jsonString = convertToJson(returnValue);

        // 設置響應內容類型和編碼
        response.setContentType("application/json");
        response.setCharacterEncoding("UTF-8");

        // 將 JSON 字符串寫入響應
        response.getWriter().write(jsonString);
    }

    private String convertToJson(Object object) {
        // 自定義將對象轉換爲 JSON 的邏輯
        // 例如,使用 Jackson ObjectMapper 進行轉換
        ObjectMapper objectMapper = new ObjectMapper();
        try {
            return objectMapper.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException("Failed to convert object to JSON", e);
        }
    }
}

在上述示例中,我們創建了一個名爲CustomInterceptor的攔截器,並實現了HandlerInterceptor接口。在postHandle方法中,我們可以獲取到返回結果,並對其進行自定義處理。在示例中,我們將返回對象轉換爲JSON字符串,並將其寫入響應。

然後,您可以將該攔截器配置到Spring MVC應用程序中。這可以通過添加以下配置類完成:

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CustomWebMvcConfigurer implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 註冊自定義攔截器
        registry.addInterceptor(new CustomInterceptor());
    }
}

在上述示例中,我們創建了一個名爲CustomWebMvcConfigurer的配置類,並實現了WebMvcConfigurer接口。在addInterceptors方法中,我們將自定義的攔截器CustomInterceptor添加到攔截器註冊表中。

請確保將上述類正確配置到您的Spring MVC應用程序中,以便添加自定義的返回結果處理邏輯。在示例中,我們在攔截器中處理返回結果,並將其轉換爲JSON字符串進行輸出。您可以根據需要修改和擴展自定義的返回結果處理邏輯。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章