You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现类级@ResponseBody风格注解:使其作用于类中所有方法

Implement a Class-Level Annotation Like @ResponseBody

Great question! If you want to create a class-level annotation that automatically applies the @ResponseBody behavior to all methods in the annotated class, you can leverage Spring MVC's extension points to build this functionality. Here's a step-by-step guide:

Step 1: Define Your Custom Class-Level Annotation

First, create an annotation that targets classes and retains at runtime:

import java.lang.annotation.*;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface GlobalResponseBody {
}

Step 2: Customize the Return Value Handler

Spring uses RequestResponseBodyMethodProcessor to handle methods annotated with @ResponseBody. We'll extend this processor to check if the method's containing class has our @GlobalResponseBody annotation:

import org.springframework.core.MethodParameter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.mvc.method.annotation.RequestResponseBodyMethodProcessor;

import java.util.List;

public class GlobalResponseBodyReturnValueHandler extends RequestResponseBodyMethodProcessor {

    public GlobalResponseBodyReturnValueHandler(List<HttpMessageConverter<?>> converters) {
        super(converters);
    }

    public GlobalResponseBodyReturnValueHandler(List<HttpMessageConverter<?>> converters, List<Object> requestResponseBodyAdvice) {
        super(converters, null, requestResponseBodyAdvice);
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        // Check if the class has our custom annotation first
        Class<?> containingClass = returnType.getContainingClass();
        if (containingClass.isAnnotationPresent(GlobalResponseBody.class)) {
            return true;
        }
        // Fall back to the original logic (check for @ResponseBody on methods)
        return super.supportsReturnType(returnType);
    }
}

Step 3: Register the Custom Handler with Spring MVC

We need to add our custom handler to Spring's return value handler chain, ensuring it takes priority over the default processor. Use WebMvcConfigurer to configure this:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.List;

@Configuration
public class CustomWebMvcConfig implements WebMvcConfigurer {

    @Autowired
    private List<HttpMessageConverter<?>> messageConverters;

    @Autowired(required = false)
    private List<Object> requestResponseBodyAdvice;

    @Override
    public void configureReturnValueHandlers(List<HandlerMethodReturnValueHandler> handlers) {
        // Create our custom handler
        GlobalResponseBodyReturnValueHandler customHandler = 
            new GlobalResponseBodyReturnValueHandler(messageConverters, requestResponseBodyAdvice);
        // Add it to the front of the list to ensure it's checked first
        handlers.add(0, customHandler);
    }
}

Step 4: Use the Annotation

Now you can annotate any controller class with @GlobalResponseBody, and all its methods will automatically return serialized response bodies (just like using @ResponseBody on every method):

@Controller
@GlobalResponseBody
public class DemoController {

    // This method will return JSON (or configured format) without @ResponseBody
    @GetMapping("/demo")
    public DemoDto getDemo() {
        return new DemoDto("Hello", "World");
    }
}

How It Works

  • Our custom GlobalResponseBodyReturnValueHandler overrides supportsReturnType to check if the method's class has our annotation. If yes, it tells Spring to process the return value as a response body.
  • By adding our handler to the start of the handler list, we ensure our logic takes precedence over the default RequestResponseBodyMethodProcessor.
  • This approach aligns with Spring's native handling of @ResponseBody, so you get all the same features (like content negotiation, message converters, and ResponseBodyAdvice support).

内容的提问来源于stack exchange,提问作者sibo.wang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 04:11:25