Spring Boot配置Gson序列化如何按请求指定版本适配@Since/@Until
动态配置Gson版本适配请求属性的Spring Boot实现
你可以通过自定义GsonHttpMessageConverter实现动态版本控制,无需手动返回String类型。核心思路是让Spring的消息转换器在序列化时,从当前请求上下文获取版本号,创建对应版本的Gson实例完成序列化。
1. 自定义版本化Gson消息转换器
继承Spring默认的GsonHttpMessageConverter,重写序列化方法,动态获取请求中的版本号并生成对应Gson实例:
import com.google.gson.Gson; import com.google.gson.GsonBuilder; import org.springframework.http.HttpOutputMessage; import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; import java.io.IOException; import java.lang.reflect.Type; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; public class VersionedGsonHttpMessageConverter extends GsonHttpMessageConverter { // 缓存不同版本的Gson实例,避免重复创建浪费资源 private final Map<Double, Gson> gsonCache = new ConcurrentHashMap<>(); // 基础Gson配置,统一设置全局序列化规则 private final GsonBuilder baseGsonBuilder = new GsonBuilder() .serializeNulls() .setDateFormat("yyyy-MM-dd HH:mm:ss"); @Override protected void writeInternal(Object object, Type type, HttpOutputMessage outputMessage) throws IOException { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attributes != null) { String versionStr = attributes.getAttribute("version", 0); // 从RequestScope获取version属性 if (versionStr != null) { try { double version = Double.parseDouble(versionStr); // 缓存中不存在则创建对应版本的Gson实例 Gson versionedGson = gsonCache.computeIfAbsent(version, v -> baseGsonBuilder.setVersion(v).create()); // 执行序列化并写入响应 String json = versionedGson.toJson(object, type); outputMessage.getBody().write(json.getBytes(getDefaultCharset())); return; } catch (NumberFormatException e) { // 版本格式错误时, fallback到默认逻辑 } } } // 无有效版本时,使用默认Gson配置序列化 super.writeInternal(object, type, outputMessage); } }
2. 替换Spring默认的Gson转换器
在WebMvc配置类中注册自定义转换器,替换掉Spring自带的GsonHttpMessageConverter:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.json.GsonHttpMessageConverter; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import java.util.List; @Configuration public class WebMvcConfig implements WebMvcConfigurer { @Bean public GsonHttpMessageConverter versionedGsonHttpMessageConverter() { return new VersionedGsonHttpMessageConverter(); } @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { // 移除默认的Gson转换器 converters.removeIf(converter -> converter instanceof GsonHttpMessageConverter); // 添加自定义版本化转换器 converters.add(versionedGsonHttpMessageConverter()); } }
3. 确保请求属性version被正确设置
需要确保version属性在请求到达控制器之前存入请求上下文,比如通过拦截器从请求参数、Header等位置获取并设置:
import org.springframework.web.servlet.HandlerInterceptor; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; public class VersionInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 示例:从请求参数中获取version,可根据实际需求改为Header或其他来源 String version = request.getParameter("version"); if (version != null) { request.setAttribute("version", version); } return true; } }
然后在WebMvc配置类中注册拦截器:
@Configuration public class WebMvcConfig implements WebMvcConfigurer { // ... 之前的转换器配置 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new VersionInterceptor()); } }
控制器使用方式
现在你的控制器可以直接返回User对象,转换器会自动根据请求中的version属性选择对应版本的Gson进行序列化:
@GetMapping("/users/{id}") public User getUserById(@PathVariable("id") String id, @RequestAttribute(value = "version", required = false) String version) { User user = userRepository.getUserById(id); // 无需手动序列化,直接返回对象即可 return user; }
内容的提问来源于stack exchange,提问作者Felipe Quecole
相关产品推荐
相关产品推荐

