Создание представления XML с помощью XStreamMarshaller Spring
Я использую Spring Framework 3.1 (с Hibernate), и я пытаюсь создать представление XML, как:
<user>
<iduser>1</iduser>
<email>bla@hello.com</email>
<firstName>bob</firstName>
</user>
из этого Java-класса:
@Entity public class User { @GenericGenerator(name = "table-hilo-generator", strategy = "org.hibernate.id.IncrementGenerator") @GeneratedValue(generator = "table-hilo-generator") @Id @Column(name = "iduser", unique = true, nullable = false) private int iduser; @NotBlank @NotNull @NotEmpty @Length(max = EMAIL_MAX_SIZE) @Column(name = "email", nullable = false) private String email; @NotBlank @NotNull @NotEmpty @Length(max = FIRST_NAME_MAX_SIZE) @Column(name = "firstName", nullable = false) private String firstName; }
мой servlet-conf.xml содержит это представление в ContentNegotiatingViewResolver:
<!-- XML View --> <bean class="org.springframework.web.servlet.view.xml.MarshallingView"> <constructor-arg> <bean class="org.springframework.oxm.xstream.XStreamMarshaller"> <property name="aliases"> <map> <entry key="user123" value="com.....entities.User" /> </map> </property> </bean> </constructor-arg> </bean>
Но я не понимаю, почему в результате получается странный xml с сотнями элементов, таких что:
<org.springframework.validation.BeanPropertyBindingResult> <nestedPath/> <nestedPathStack serialization="custom"> <unserializable-parents/> <vector> <default> <capacityIncrement>0</capacityIncrement> <elementCount>0</elementCount> <elementData> <null/> <null/> <null/> <null/> <null/> <null/> <null/> <null/> <null/> <null/> </elementData> </default> </vector> </nestedPathStack> <objectName>user</objectName> <messageCodesResolver class="org.springframework.validation.DefaultMessageCodesResolver"> <prefix/>
1-Вероятно, маршаллер слишком много играет с отражением, как я могу получить ожидаемый результат, который я хочу? ( 2-я заинтересован также в создании XML-файла со списком пользователей) Как я могу это сделать?
2 ответа
Как вы уже заметили, происходит то, что, поскольку вы не указали явный ключ модели, который нужно сериализовать, он сериализует первый ненулевой объект модели, который в этом случае будет BindingResult
(используется для хранения ошибок привязки / проверки в вашей модели). Есть несколько исправлений, которые вы можете сделать:
а. Укажите точный modelKey
для вашего представления о маршаллинге это должно сработать и установить модель для конкретного ключа модели:
<bean class="org.springframework.web.servlet.view.xml.MarshallingView">
<property name="marshaller">
...
</property>
<property name="modelKey" value="command"/>
</bean>
model.addAttribute("command", mymodel);
б. Лучшим решением, IMHO, может быть использование http-конвертеров в Spring, таким образом вы можете вернуть свой объект из метода сопоставленного запроса, аннотировать его @ResponseBody
а Spring позаботится о преобразовании объекта в проводное представление (xml или json и т. д.), вам просто нужно зарегистрировать правильный преобразователь:
@RequestMapping(...)
public @ResponseBody User myMethod(Model model){
return user;
}
<mvc:annotation-driven conversion-service="conversionService">
<mvc:message-converters register-defaults="false"> <!-- you may have to explicitly register other converters though-->
<bean class="org.springframework.http.converter.xml.MarshallingHttpMessageConverter">
<property name="marshaller">
<bean class="org.springframework.oxm.xstream.XStreamMarshaller"/>
</property>
</bean>
</mvc:message-converters>
У меня была та же ошибка с XStream, и она была решена путем применения следующего изменения:
Вместо того, чтобы добавить modelKey, вы можете добавить свойство "selectedClasses" к бину Marshaller:
<bean class="org.springframework.oxm.xstream.XStreamMarshaller">
<property name="autodetectAnnotations" value="true"/>
<property name="supportedClasses">
<list>
<value>com.rest.example.model.User</value>
</list>
</property>
</bean>
Во-вторых, класс User должен быть аннотирован псевдонимом XStream, в противном случае вы получите полное имя пакета в XML - например: <com.rest.example.model.User>
вместо <user>
- способ исправить это:
@XStreamAlias("user")
public class User {
...