J'ai un projet de démarrage de printemps. J'ai quelques xsds dans mon projet. J'ai généré les classes en utilisant maven-jaxb2-plugin. J'ai utilisé this tutorial pour faire fonctionner un exemple d'application d'amorçage printanier.
import org.kaushik.xsds.XOBJECT;
@SpringBootApplication
public class JaxbExample2Application {
public static void main(String[] args) {
//SpringApplication.run(JaxbExample2Application.class, args);
XOBJECT xObject = new XOBJECT('a',1,2);
try {
JAXBContext jc = JAXBContext.newInstance(User.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(xObject, System.out);
} catch (PropertyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (JAXBException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Mais ce qui me préoccupe, c’est que j’ai besoin de mapper toutes les classes jaxb du schéma. De plus, y at-il quelque chose au printemps que je peux utiliser pour me faciliter la tâche. J'ai examiné le projet Spring OXM mais le contexte de l'application était configuré en xml. Est-ce que la botte de printemps a tout ce que je peux utiliser hors de la boîte? Tous les exemples seront utiles.
Modifier
J'ai essayé la réponse de xerx593 et j'ai fait un test simple en utilisant la méthode principale
JaxbHelper jaxbHelper = new JaxbHelper();
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(XOBJECT.class);
jaxbHelper.setMarshaller(marshaller);
XOBJECT xOBJECT= (PurchaseOrder)jaxbHelper.load(new StreamSource(new FileInputStream("src/main/resources/PurchaseOrder.xml")));
System.out.println(xOBJECT.getShipTo().getName());
Cela a fonctionné parfaitement bien. Maintenant, j'ai juste besoin de le brancher avec une botte à ressort.
OXM est définitivement le droit pour vous!
Une configuration Java simple d'un Jaxb2Marshaller ressemblerait à ceci:
//...
import Java.util.HashMap;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
//...
@Configuration
public MyConfigClass {
@Bean
public Jaxb2Marshaller jaxb2Marshaller() {
Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setClassesToBeBound(new Class[]{
//all the classes the context needs to know about
org.kaushik.xsds.All.class,
org.kaushik.xsds.Of.class,
org.kaushik.xsds.Your.class,
org.kaushik.xsds.Classes.class
}); //"alternatively" setContextPath(<jaxb.context>),
marshaller.setMarshallerProperties(new HashMap<String, Object>() {{
put(javax.xml.bind.Marshaller.JAXB_FORMATTED_OUTPUT, true);
}});
return marshaller;
}
}
Dans votre classe Application/Service, vous pourriez aborder comme ceci:
import Java.io.InputStream;
import Java.io.StringWriter;
import javax.xml.bind.JAXBException;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
@Component
public MyMarshallerWrapper {
// you would rather:
@Autowired
private Jaxb2Marshaller marshaller;
// than:
// JAXBContext jc = JAXBContext.newInstance(User.class);
// Marshaller marshaller = jc.createMarshaller();
// marshalls one object (of your bound classes) into a String.
public <T> String marshallXml(final T obj) throws JAXBException {
StringWriter sw = new StringWriter();
Result result = new StreamResult(sw);
marshaller.marshal(obj, result);
return sw.toString();
}
// (tries to) unmarshall(s) an InputStream to the desired object.
@SuppressWarnings("unchecked")
public <T> T unmarshallXml(final InputStream xml) throws JAXBException {
return (T) marshaller.unmarshal(new StreamSource(xml));
}
}
Voir Jaxb2Marshaller-javadoc , et un Answer
Si vous voulez juste serializing/deserializing
bean avec XML. Je pense que jackson fasterxml
est un bon choix:
ObjectMapper xmlMapper = new XmlMapper();
String xml = xmlMapper.writeValueAsString(new Simple()); // serializing
Simple value = xmlMapper.readValue("<Simple><x>1</x><y>2</y></Simple>",
Simple.class); // deserializing
maven:
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
</dependency>
Spring BOOT est très intelligent et peut comprendre ce dont vous avez besoin avec un peu d'aide.
Pour que le tri/marshalling XML fonctionne, il suffit d'ajouter @XmlRootElement à la classe annotations et @XmlElement aux champs sans getter et la classe cible sera sérialisée/désérialisée automatiquement.
Voici l'exemple de DTO
package com.exmaple;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import Java.io.Serializable;
import Java.util.Date;
import Java.util.Random;
@AllArgsConstructor
@NoArgsConstructor
@ToString
@Setter
@XmlRootElement
public class Contact implements Serializable {
@XmlElement
private Long id;
@XmlElement
private int version;
@Getter private String firstName;
@XmlElement
private String lastName;
@XmlElement
private Date birthDate;
public static Contact randomContact() {
Random random = new Random();
return new Contact(random.nextLong(), random.nextInt(), "name-" + random.nextLong(), "surname-" + random.nextLong(), new Date());
}
}
Et le contrôleur:
package com.exmaple;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
@RequestMapping(value="/contact")
public class ContactController {
final Logger logger = LoggerFactory.getLogger(ContactController.class);
@RequestMapping("/random")
@ResponseBody
public Contact randomContact() {
return Contact.randomContact();
}
@RequestMapping(value = "/edit", method = RequestMethod.POST)
@ResponseBody
public Contact editContact(@RequestBody Contact contact) {
logger.info("Received contact: {}", contact);
contact.setFirstName(contact.getFirstName() + "-EDITED");
return contact;
}
}
Vous pouvez voir un exemple de code complet ici: https://github.com/sergpank/spring-boot-xml
Toutes les questions sont les bienvenues.
Vous pouvez utiliser StringSource
/StringResult
pour lire/lire le code source XML avec spring
@Autowired
Jaxb2Marshaller jaxb2Marshaller;
@Override
public Service parseXmlRequest(@NonNull String xmlRequest) {
return (Service) jaxb2Marshaller.unmarshal(new StringSource(xmlRequest));
}
@Override
public String prepareXmlResponse(@NonNull Service xmlResponse) {
StringResult stringResult = new StringResult();
jaxb2Marshaller.marshal(xmlResponse, stringResult);
return stringResult.toString();
}