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

Spring RESTful中如何在@RestController执行后修改返回数据(基于指定语言转换字段值)

在Spring RestController返回后修改响应体(枚举值国际化)

嘿,这个需求用Spring提供的ResponseBodyAdvice就能轻松搞定!它可以让你在响应体被序列化到HTTP响应之前,对返回的数据做自定义修改,完美匹配你根据指定语言转换枚举字段值的场景。咱们一步步来实现:

1. 准备国际化资源文件

首先创建不同语言的消息配置文件,放在src/main/resources下:

  • messages_en.properties(英文):
gender.woman=Woman
gender.man=Man
gender.other=Other
  • messages_fr.properties(法语,对应你示例里的homme):
gender.woman=Femme
gender.man=Homme
gender.other=Autre

2. 配置Spring国际化

确保Spring能识别这些资源文件,你可以在配置类里添加:

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasenames("messages");
        messageSource.setDefaultEncoding("UTF-8");
        return messageSource;
    }

    @Bean
    public LocaleResolver localeResolver() {
        AcceptHeaderLocaleResolver resolver = new AcceptHeaderLocaleResolver();
        resolver.setDefaultLocale(Locale.ENGLISH);
        return resolver;
    }
}

这个配置会自动从请求头的Accept-Language里获取当前语言,默认用英文。

3. 实现ResponseBodyAdvice拦截并修改响应体

创建一个全局的响应处理器,实现ResponseBodyAdvice接口,专门处理User对象的gender字段转换:

@ControllerAdvice(basePackages = "com.yourpackage.controller") // 指定要拦截的控制器包
public class GlobalResponseAdvice implements ResponseBodyAdvice<Object> {

    @Autowired
    private MessageSource messageSource;

    @Override
    public boolean supports(MethodParameter returnType, Class<? extends HttpMessageConverter<?>> converterType) {
        // 只处理返回类型为User的请求
        return returnType.getParameterType().equals(User.class);
    }

    @Override
    public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
                                  Class<? extends HttpMessageConverter<?>> selectedConverterType,
                                  ServerHttpRequest request, ServerHttpResponse response) {
        if (body instanceof User user) {
            // 获取当前请求的Locale
            Locale locale = LocaleContextHolder.getLocale();
            // 根据枚举值获取国际化消息
            String genderKey = "gender." + user.getGender().name().toLowerCase();
            String localizedGender = messageSource.getMessage(genderKey, null, locale);
            
            // 建议新增显示字段而非修改原枚举字段,避免破坏原始数据
            user.setGenderDisplay(localizedGender);
            // 若不想修改User类,也可以返回封装后的DTO或Map对象
        }
        return body;
    }
}

补充:优化User类结构

在User类里新增一个专门用于显示的字段,既能保留原始枚举数据,又能返回国际化后的内容:

public class User {
    private String firstName;
    private String lastName;
    private Gender gender;
    private String genderDisplay; // 新增的国际化显示字段

    // getter、setter、构造方法等
}

如果想隐藏原始枚举字段,只需给gender字段加上@JsonIgnore注解,序列化时就不会返回它。

4. 测试效果

发送请求时在请求头带上Accept-Language: fr,比如:

GET /get/1 HTTP/1.1
Host: localhost:8080
Accept-Language: fr

返回的响应就会变成:

{
  "firstName": "john",
  "lastName": "doe",
  "genderDisplay": "Homme"
}

为什么选ResponseBodyAdvice?

  • 全局复用:不需要修改每个控制器的代码,适合多接口需要相同处理逻辑的场景;
  • 无侵入性:在响应序列化前执行,不会破坏原有业务逻辑;
  • 灵活控制:可以精准指定要拦截的控制器或返回类型,针对性强。

内容的提问来源于stack exchange,提问作者mehnet ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 10:12:35