Java 如何根据条件应用spring消息转换器?

Java 如何根据条件应用spring消息转换器?,java,spring,spring-mvc,jackson2,Java,Spring,Spring Mvc,Jackson2,我有一个响应为camelCase json值的控制器。现在我们正在用新版本重新编写代码,需要的响应是snake_案例 我添加了一个消息转换器,并修改了对象映射器来设置setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL\u CASE\u到带有下划线的\u LOWER\u CASE\u) 我已经向spring注册了这个转换器,它的工作情况与预期的一样。现在,我希望旧端点以camelCase的形式返回,以向后兼容我的消费者和snake_case

我有一个响应为camelCase json值的控制器。现在我们正在用新版本重新编写代码,需要的响应是snake_案例

我添加了一个消息转换器,并修改了对象映射器来设置
setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL\u CASE\u到带有下划线的\u LOWER\u CASE\u)

我已经向spring注册了这个转换器,它的工作情况与预期的一样。现在,我希望旧端点以camelCase的形式返回,以向后兼容我的消费者和snake_case的新端点

我曾尝试过在不将camelCase设置为Snake-case属性并向spring注册的情况下,再使用一个带有简单对象映射器的消息转换器。根据spring配置中声明的顺序,只应用一个消息转换器

我们有没有办法做到这一点?根据条件加载消息转换器

编辑

添加了我的spring配置文件


编辑2.0

myservlet.xml

自定义对象映射器

自定义属性命名策略

@组件
公共类CustomPropertyNamingStrategy扩展了PropertyNamingStrategy{
@自动连线
私有HttpServletRequest;
private final PropertyNamegstrategy legacyStrategy=PropertyNamegstrategy.LOWER_CASE;
private final PropertyNamingStrategy defaultStrategy=PropertyNamingStrategy.CAMEL\u CASE\u TO\u LOWER\u CASE\u,带下划线;
@凌驾
ConstructorParameter的公共字符串名称(MapperConfig配置,AnnotatedParameter ctorParam,String defaultName){
返回getStrategy().nameForConstructorParameter(配置、参数、默认名称);
}
@凌驾
公共字符串名称字段(MapperConfig配置,AnnotatedField字段,字符串默认名称){
返回getStrategy().nameForField(配置、字段、默认名称);
}
@凌驾
公共字符串名称遗忘方法(MapperConfig配置,AnnotatedMethod方法,字符串默认名称){
返回getStrategy().NameForferMethod(配置、方法、默认名称);
}
@凌驾
SetterMethod的公共字符串名称(MapperConfig配置、AnnotatedMethod方法、字符串defaultName){
返回getStrategy().nameForSetterMethod(配置、方法、默认名称);
}
私有财产名称策略getStrategy(){
if(isLegacyEndpoint(请求)){
回归策略;
}否则{
回报策略;
}
}
私有布尔isLegacyEndpoint(HttpServletRequest){
返回请求!=null&&request.getRequestURL()!=null&&request.getRequestURL().toString()包含(“/v3”);
}
}

我建议创建
属性名称策略的自定义实现,相应地使用其他两种策略,而不是使用两种不同的对象映射器:

public class AwesomePropertyNamingStrategy extends PropertyNamingStrategy {

  private PropertyNamingStrategy legacyStrategy  = PropertyNamingStrategy.LOWER_CASE;
  private PropertyNamingStrategy defaultStrategy  = PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES;

  @Override
  public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam, String defaultName) {
    return getStrategy().nameForConstructorParameter(config, ctorParam, defaultName);
  }

  // TODO: implement other nameForXXX methods

  private PropertyNamingStrategy getStrategy() {
    if (isLegacyEndpoint()) {
      return legacyStrategy;
    } else {
      return defaultStrategy;
    }
  }

  private boolean isLegacyEndpoint() {
    // TODO: get hold of the RequestContext or some other thead-local context 
    // that allows you to know it's an old or a new endpoint
    return false;
  }
}
public类AwesomePropertyNamingStrategy扩展了PropertyNamingStrategy{
private PropertyNamingStrategy legacyStrategy=PropertyNamingStrategy.LOWER_CASE;
private PropertyNamingStrategy defaultStrategy=PropertyNamingStrategy.CAMEL\u CASE\u TO\u LOWER\u CASE\u,带下划线;
@凌驾
ConstructorParameter的公共字符串名称(MapperConfig配置,AnnotatedParameter ctorParam,String defaultName){
返回getStrategy().nameForConstructorParameter(配置、参数、默认名称);
}
//TODO:为XXX方法实现其他名称
私有财产名称策略getStrategy(){
if(isLegacyEndpoint()){
回归策略;
}否则{
回报策略;
}
}
私有布尔值isLegacyEndpoint(){
//TODO:获取RequestContext或其他一些thead本地上下文
//这允许您知道它是旧端点还是新端点
返回false;
}
}
您应该想出一种在旧模式和新模式之间切换的方法:

  • 通过以某种方式访问请求上下文来使用端点URL
  • 如果旧端点使用不同的响应对象,请使用正在转换的对象的类来确定所有旧类上的遗留/正常或您自己的自定义
    @LegacyResponse
    注释

  • 好吧,经过多次尝试,什么都没用。最终定义了两个不同的servlet。一个没有任何版本,另一个有v1版本

    web.xml

            <servlet>
                <servlet-name>snake-case</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
    
            <servlet-mapping>
                <servlet-name>snake-case</servlet-name>
                <url-pattern>/v1</url-pattern>
            </servlet-mapping>
    
             <servlet>
                <servlet-name>camel-case</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
    
            <servlet-mapping>
                <servlet-name>camel-case</servlet-name>
                <url-pattern>/</url-pattern>
            </servlet-mapping>
    
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="com.tgt.promotions.api.serialize.DataJSONConverter">
                <constructor-arg ref="snakeCaseObjectMapper"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven> 
    
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="com.tgt.promotions.api.serialize.DataJSONConverter">
                <constructor-arg ref="objectMapper"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven> 
    
    
    蛇壳
    org.springframework.web.servlet.DispatcherServlet
    1.
    蛇壳
    /v1
    骆驼箱
    org.springframework.web.servlet.DispatcherServlet
    1.
    骆驼箱
    /
    
    相应地定义了两个servlet snake-case-servlet.xml和camel-case-servlet.xml

    snake-case-servlet.xml

            <servlet>
                <servlet-name>snake-case</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
    
            <servlet-mapping>
                <servlet-name>snake-case</servlet-name>
                <url-pattern>/v1</url-pattern>
            </servlet-mapping>
    
             <servlet>
                <servlet-name>camel-case</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
    
            <servlet-mapping>
                <servlet-name>camel-case</servlet-name>
                <url-pattern>/</url-pattern>
            </servlet-mapping>
    
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="com.tgt.promotions.api.serialize.DataJSONConverter">
                <constructor-arg ref="snakeCaseObjectMapper"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven> 
    
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="com.tgt.promotions.api.serialize.DataJSONConverter">
                <constructor-arg ref="objectMapper"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven> 
    
    
    
    camel-case-servlet.xml

            <servlet>
                <servlet-name>snake-case</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
    
            <servlet-mapping>
                <servlet-name>snake-case</servlet-name>
                <url-pattern>/v1</url-pattern>
            </servlet-mapping>
    
             <servlet>
                <servlet-name>camel-case</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
            </servlet>
    
            <servlet-mapping>
                <servlet-name>camel-case</servlet-name>
                <url-pattern>/</url-pattern>
            </servlet-mapping>
    
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="com.tgt.promotions.api.serialize.DataJSONConverter">
                <constructor-arg ref="snakeCaseObjectMapper"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven> 
    
        <mvc:annotation-driven>
            <mvc:message-converters register-defaults="true">
                <bean class="com.tgt.promotions.api.serialize.DataJSONConverter">
                <constructor-arg ref="objectMapper"/>
                </bean>
            </mvc:message-converters>
        </mvc:annotation-driven> 
    
    
    

    现在,对于使用/v1*的任何请求,将使用snakeCaseObjectMapper,对于其他请求,将使用默认对象映射器。

    请添加spring xml配置或更多支持代码。感谢您的回复。我试着照你的建议去做。我已经创建了一个消息转换器,并按照您的建议传递customObjectMapper和设置awesomePropertyName策略。但我得到的回应是小案件和蛇案策略的混合。我需要做些什么来解决这个问题吗?你能分享你提出的解决方案吗,特别是你区分传统和新的部分吗?我正在类中自动连接HttpServletRequest请求并加载AwesomePropertyNa