我有一个Spring服务,它基于数据库中的数据填充一个通用对象,目标是让用户向web服务传递一个参数,以指示他们希望输出的格式。根据他们的输入,我们将使用正确的JSONSerializer给他们想要的东西。
我已经按照如下方式设置了我的webservice,在我的spring servlet.xml中,我已经将我们公司的ObjectMapper设置为mvc:消息转换器使用,我还在RestController上设置了它,以便它可以调整ObjectMapper来注册序列化程序。看起来是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd">
<mvc:annotation-driven>
<mvc:message-converters register-defaults="true">
<bean
class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
</mvc:message-converters>
</mvc:annotation-driven>
<bean id="endpoint" class="org.company.Controller">
<property name="objectMapper" ref="jacksonObjectMapper" />
</bean>
<bean id="jacksonObjectMapper" class="org.company.CompanyObjectMapper" />
</beans>控制器如下所示:
@RestController
public class Controller {
private ObjectMapper objectMapper;
@RequestMapping(...)
public GenericObject getObject(@PathVariables ...) {
//Get Object from database, just creating an object for example
GenericObject object = new GenericObject();
//Based on the user input we will pick out
//a Serializer that extends JsonSerializer<GenericObject>
BaseSerializer serializer = getSerializer();
//Create a simpleModule and use it to register our serializer
SimpleModule module = new SimpleModule();
module.addSerializer(GenericObject.class, serializer);
//get module and register the serializer
ObjectMapper mapper = getObjectMapper();
mapper.registerModule(module);
return object;
}
public ObjectMapper getObjectMapper() {
return objectMapper;
}
public void setObjectMapper(ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
}问题是,当我发布我的webapp时,第一个查询工作正常,如果我指定了format=format1,我将在format1中获得输出。然而,在那之后,我只能接收format1。我可以指定format=format2,但仍然可以在format1中获得输出。我认为问题在于,ObjectMapper仍然将第一个查询中的模块注册到它。我已经读到,我可以通过每次创建一个新的ObjectMapper来避免这个问题,但是我不知道如何设置它在它输出JSON时被使用。
有人能帮我想出一个解决方案,在我每次运行代码并将该ObjectMapper设置为Spring服务时创建一个新的ObjectMapper,还是帮助我在设置最新的所需序列化程序之前“注销”在对象映射程序上注册的任何模块?
发布于 2015-10-26 18:09:02
一个想法可以是创建并配置启动时需要的所有映射器,作为spring。
然后创建默认的对象映射程序,它将作为其他对象映射器的调度程序(或者作为备用对象映射程序),并且它可能知道当前的http请求。您可以在此对象映射器中注册所有映射器,将此映射器注册为spring中的默认映射器。
可能是这样的:
public class RequestAwareObjectMapper extends ObjectMapper{
private Map<String, ObjectMapper > mappers = new HashMap<>();
@Override
public String writeValueAsString(Object value) throws JsonProcessingException{
HttpServletRequest req = null;//get request from spring context, if any, this is a managed spring bean it wont be a prorblem
String param = null; // read the param from the query
ObjectMapper mapper = mappers.get(param);
if(mapper == null){
mapper = this;
}
return mapper.writeValueAsString(value);
}
public void registerMapper(String key, ObjectMapper mapper){...}
} 这样,您不会通过引用对象映射器来污染您的控制器,您可以继续使用@ResponseBody (感谢@RestController)。
我确信,在弹簧流中集成类似的解决方案,有一种更干净的方法可以实现同样的结果,现在无法看到更好的结果。
发布于 2015-10-26 17:45:34
创建您的customObjectMapper类并使用@Autowire注释自动将其连接到控制器。然后,您可以创建不同的方法来创建不同的格式化对象。
还可以将序列化器作为参数发送。
public class CustomObjectMapper extends ObjectMapper {
public CustomObjectMapper() {
super();
super.setSerializationInclusion(JsonInclude.Include.ALWAYS);
super.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
..... etc.....
super.setDateFormat(df);
}
public byte[] generateJsonFormat1(Object value, BaseSerializer serializer) throws IOException, JsonGenerationException, JsonMappingException {
Hibernate4Module hm = new Hibernate4Module();
hm.configure(Hibernate4Module.Feature.USE_TRANSIENT_ANNOTATION, false);
hm.configure(Hibernate4Module.Feature.FORCE_LAZY_LOADING, false);
.....
.....
hm.addSerializer(Object.class, serializer);
return super.registerModule(hm).writeValueAsBytes(value);
}
public byte[] generateJsonFormat2(Object value, BaseSerializer serialiser) throws IOException, JsonGe nerationException, JsonMappingException {
SimpleModule sm = new SimpleModule();
sm.addSerializer(Object.class, serialiser);
return super.registerModule(hm).writeValueAsBytes(value);
}
}上面的代码是我自己应用程序中的一个片段。我希望它能给出这个想法。
https://stackoverflow.com/questions/33309557
复制相似问题