我们试图使用 gradle、xsd 和 xjc 生成 JAXB 类,JAXB 类应该有 XmlRootElement 注释,这样它就可以用于作为 Web 服务响应公开。我们 http://azagorneanu.blogspot.com/2011/09/configure-maven-to-generate-classes.html 关注此链接,它有很大帮助,但我们无法找到仅使用 gradle 的一个特定示例。因此,我们想出了几件事,我们将分享作为答案。
build.gradle应该看起来像下面这样
buildscript {
repositories {
mavenCentral()
jcenter()
}
dependencies {
classpath "net.saliman:gradle-cobertura-plugin:2.2.4"
classpath 'com.github.jacobono:gradle-jaxb-plugin:1.3.5'
}
}
apply plugin: 'com.github.jacobono.jaxb'
dependencies {
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.7'
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics-ant:0.6.5"
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics:0.6.4"
jaxb "org.jvnet.jaxb2_commons:jaxb2-basics-annotate:0.6.4"
}
configurations {
jaxb
}
task jaxb(){
description 'Converts xsds to classes'
def jaxbTargetDir = file("generated")
doLast {
jaxbTargetDir.mkdirs()
ant.taskdef(name: 'xjc', classname: 'org.jvnet.jaxb2_commons.xjc.XJC2Task', classpath: configurations.jaxb.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(destdir: '${jaxbTargetDir}', package: 'com.sample.jaxbclasses', schema:'generated/schema.xsd', binding:'generated/binding.xjb', extension:'true'){
arg(value: "-Xannotate")
}
}
}
schema.xsd
<xs:element name="user" type="user" />
<xs:element name="userList" type="userList" />
<xs:complexType name="user">
<xs:all>
<xs:element name="id" type="xs:long" minOccurs="0" />
<xs:element name="name" type="xs:string" />
<xs:element name="registrationDate" type="xs:dateTime" />
</xs:all>
</xs:complexType>
<xs:complexType name="userList">
<xs:sequence>
<xs:element name="user" type="user" minOccurs="0" maxOccurs="unbounded" />
</xs:sequence>
</xs:complexType>
</xs:schema>
绑定.xjb
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:annox="http://annox.dev.java.net"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<jaxb:globalBindings>
<!-- Use java.util.Calendar instead of javax.xml.datatype.XMLGregorianCalendar for xs:dateTime -->
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime"
parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime"
printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
<!-- Force all classes implements Serializable -->
<xjc:serializable uid="1" />
</jaxb:globalBindings>
<!-- Annotate the following classes with XmlRootElement -->
<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[@name='user']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="user" />
</annox:annotate>
</jaxb:bindings>
<jaxb:bindings node="xs:complexType[@name='userList']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="userList" />
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
下面的绑定.xjb也可以使用
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jxb:globalBindings>
<xjc:simple />
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>
现在你可以运行任务'jaxb',全部设置。干杯!
用户.java
//
// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.2.7
// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
// Any modifications to this file will be lost upon recompilation of the source schema.
// Generated on: 2017.01.26 at 11:59:18 AM EST
//
package com.sample.jaxbclasses;
import java.io.Serializable;
import java.util.Calendar;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
/**
* <p>Java class for user complex type.
*
* <p>The following schema fragment specifies the expected content contained within this class.
*
* <pre>
* <complexType name="user">
* <complexContent>
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
* <all>
* <element name="id" type="{http://www.w3.org/2001/XMLSchema}long" minOccurs="0"/>
* <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
* <element name="registrationDate" type="{http://www.w3.org/2001/XMLSchema}dateTime"/>
* </all>
* </restriction>
* </complexContent>
* </complexType>
* </pre>
*
*
*/
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "user", propOrder = {
})
@XmlRootElement(name = "user")
public class User
implements Serializable
{
private final static long serialVersionUID = 1L;
protected Long id;
@XmlElement(required = true)
protected String name;
@XmlElement(required = true, type = String.class)
@XmlJavaTypeAdapter(Adapter1 .class)
@XmlSchemaType(name = "dateTime")
protected Calendar registrationDate;
/**
* Gets the value of the id property.
*
* @return
* possible object is
* {@link Long }
*
*/
public Long getId() {
return id;
}
/**
* Sets the value of the id property.
*
* @param value
* allowed object is
* {@link Long }
*
*/
public void setId(Long value) {
this.id = value;
}
/**
* Gets the value of the name property.
*
* @return
* possible object is
* {@link String }
*
*/
public String getName() {
return name;
}
/**
* Sets the value of the name property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setName(String value) {
this.name = value;
}
/**
* Gets the value of the registrationDate property.
*
* @return
* possible object is
* {@link String }
*
*/
public Calendar getRegistrationDate() {
return registrationDate;
}
/**
* Sets the value of the registrationDate property.
*
* @param value
* allowed object is
* {@link String }
*
*/
public void setRegistrationDate(Calendar value) {
this.registrationDate = value;
}
}
撰写本文时,所有其他答案都已过时。
- 由于Java EE更名为Jakarta EE,JAXB现在由新的工件
jakarta.xml.bind:jakarta.xml.bind-api
提供。 - JAXB 运行时由
org.glassfish.jaxb:jaxb-runtime
给出
。 - XJC编译器由
org.glassfish.jaxb:jaxb-xjc
给出。
Jakarta XML Binding(以前称为 JAXB)参考实现。
XJC 选项。
综上所述,一个使用 Kotlin DSL 的完整工作示例:
val jaxb: Configuration by configurations.creating
val jaxbVersion: String by project
val schemaDir = "src/main/resources"
val xjcOutputDir = "$buildDir/generated/source/xjc/main"
dependencies {
jaxb("org.glassfish.jaxb:jaxb-xjc:$jaxbVersion")
implementation("jakarta.xml.bind:jakarta.xml.bind-api:$jaxbVersion")
runtimeOnly("org.glassfish.jaxb:jaxb-runtime:$jaxbVersion")
}
val createXjcOutputDir by tasks.register("createXjcOutputDir") {
doLast {
mkdir(xjcOutputDir)
}
}
val xjc by tasks.registering(JavaExec::class) {
// Directory needs to exist
dependsOn(createXjcOutputDir)
classpath = jaxb
mainClass.set("com.sun.tools.xjc.XJCFacade")
args = listOf(
"-d",
xjcOutputDir,
"-p",
project.group.toString(),
"-encoding",
"UTF-8",
"-no-header",
"-quiet",
schemaDir
)
}
tasks.withType<JavaCompile>().configureEach {
dependsOn(xjc)
}
sourceSets {
main {
java {
srcDirs(
files(xjcOutputDir) {
builtBy(xjc)
}
)
}
}
}
group 'com.example'
version '1.0-SNAPSHOT'
apply plugin: 'java'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
}
project.ext {
jaxbTargetDir = file("src/generated/java")
}
configurations {
xsd2java
}
dependencies {
xsd2java "com.sun.xml.bind:jaxb-xjc:2.2.6"
xsd2java "com.sun.xml.bind:jaxb-impl:2.2.6"
}
task xsd2java() {
doLast {
jaxbTargetDir.mkdirs()
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.xsd2java.asPath)
ant.jaxbTargetDir = jaxbTargetDir
ant.xjc(
destdir: '${jaxbTargetDir}',
package: 'com.example.request',
schema: 'src/main/resources/XMLreq.xsd'
)
ant.xjc(
destdir: '${jaxbTargetDir}',
package: 'com.example.response',
schema: 'src/main/resources/XMLres.xsd'
)
}
}
compileJava.dependsOn xsd2java
我的版本使用 gradle 原生功能来生成 jaxbclasses。
(可选)如果您的架构依赖于外部 xsd,请使用"Oasis 目录"技术在本地解析外部 XSD。此外,在这种情况下,禁用 XML 架构验证以防止验证错误。
或者,您可以使用自定义 jaxb 绑定来调整 jaxb类。(Jaxb-bindings.xjb)
基本上是一个gradle自定义任务,它调用Java VM中可用的XJCTask ant任务,在我的示例中库来自Java 8。任务名称为"生成源",需要根据您的架构位置进行调整。
configurations {
jaxb // Only for generation purpose
}
dependencies {
jaxb 'javax.xml.bind:jaxb-api:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-osgi:2.2.11'
}
task generateSources() {
doLast {
def jaxbTargetDir = file("$buildDir/generated/src/main/java")
if (!jaxbTargetDir.exists()) {
jaxbTargetDir.mkdirs()
}
ant.taskdef(name: 'xjc', classname: 'com.sun.tools.xjc.XJCTask', classpath: configurations.jaxb.asPath)
ant.xjc(
destdir: "${jaxbTargetDir}",
schema: "${projectDir}/src/main/resources/MySchema.xsd",
binding: "${projectDir}/src/main/resources/jaxb-bindings.xjb",
catalog: "${projectDir}/src/main/resources/catalog.xml",
removeOldOutput: 'yes', extension: 'true'
)
{
arg(line: '-nv -disableXmlSecurity')
}
}
}
如果您需要目录,请创建一个文件"catalog.xml",它可能如下所示:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog
PUBLIC "-//OASIS//DTD Entity Resolution XML Catalog V1.0//EN"
"http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/xenc-schema.xsd" uri="xenc-schema.xsd" />
<system systemId="http://www.w3.org/TR/xmlenc-core/xenc-schema.xsd" uri="xenc-schema.xsd" />
<system systemId="http://www.w3.org/TR/2002/REC-xmldsig-core-20020212/xmldsig-core-schema.xsd" uri="xmldsig-core-schema.xsd" />
</catalog>
对于 jaxbinding
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.1"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings>
<xjc:javaType
adapter="org.gazpachoquest.sample.JodaLocalDateTimeConverter"
name="org.joda.time.LocalDateTime" xmlType="xs:dateTime" />
</globalBindings>
</bindings>
如果除了 jaxb 生成之外,还需要包含要构建的这些类。您需要调整 gradle 源布局和依赖项。
apply plugin: 'java'
def generatedSourcesOutput = "$buildDir/generated/main/java"
sourceSets {
main {
java.srcDirs "$generatedSourcesOutput"
}
}
configurations {
jaxb
}
dependencies {
jaxb 'javax.xml.bind:jaxb-api:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-xjc:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-impl:2.2.11'
jaxb 'com.sun.xml.bind:jaxb-osgi:2.2.11'
compile 'com.sun.xml.bind:jaxb-xjc:2.2.11'
compile 'com.sun.xml.bind:jaxb-impl:2.2.11'
compile 'javax.xml.bind:jaxb-api:2.2.11'
}
compileJava {
dependsOn generateSources
}
就这样!
用于使用 gradle-jaxb-plugin 的 Gradle 配置
xjc 配置中注释掉的值是默认值 - 根据需要进行更改。
buildscript {
repositories gradle.repos
dependencies {
}
}
plugins {
id "org.openrepose.gradle.plugins.jaxb" version "2.5.0"
id 'groovy'
id 'java'
id "org.springframework.boot" version "2.1.2.RELEASE"
id 'checkstyle'
}
apply plugin: 'io.spring.dependency-management'
apply plugin: "org.openrepose.gradle.plugins.jaxb"
apply plugin: 'idea'
apply plugin: 'maven-publish'
repositories gradle.repos
configurations {
jaxb
codeq
compile.exclude module: "spring-boot-starter-tomcat"
}
jaxb {
xjc {
//taskClassname = 'com.sun.tools.xjc.XJC2Task'
//xsdDir = "${project.projectDir}/src/main/resources/schema"
generateEpisodeFiles = false
generatePackage = 'com.mycompany.mypackage'
destinationDir = "${buildDir}/generated/src/main/java"
args = ["-Xannotate"]
}
}
compileJava.dependsOn {
'xjc'
}
sourceSets {
main {
java {
srcDirs jaxb.xjc.destinationDir
}
resources {
srcDirs 'src/main/resources'
}
}
}
dependencyManagement {
imports {
mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudDependenciesVersion}"
}
}
dependencies {
// Jaxb dependencies
jaxb group: 'org.glassfish.jaxb', name: 'jaxb-xjc', version: jaxbxjcVersion
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.0.4'
jaxb 'org.slf4j:slf4j-log4j12:1.7.25'
implementation group: 'javax.xml.bind', name: 'jaxb-api', version: jaxbApiVersion
}
和 gradle.properties 文件
# JAXB Processing Properties
jaxbPluginVersion = 2.5.0
jaxbxjcVersion = 2.3.2
jaxbApiVersion = 2.3.1
并将其与Intellij链接,请将以下内容添加到您的build.gradle文件中
idea.module.iml {
whenMerged {
dependsOn jaxb
}
}
我一直在使用 Spring Boot 生成 SOAP Web 服务指南以供参考。这是 GitHub 中 build.gradle 文件的链接。
https://github.com/spring-guides/gs-producing-web-service/blob/master/complete/build.gradle
这是一个适用于Java 11/Gradle 6的解决方案。最近在我的一个项目上更新了构建系统后,我发现在 Gradle 中通过 Ant 任务使用 XJC 存在一些问题 - 这种方法只使用普通的 Gradle,没有 Ant。
更新:根据此问题,使用GlassFish实现可以避免Sun内部依赖项的问题
sourceSets {
generated {
java.srcDir "$generated_dir"
}
}
dependencies {
compile sourceSets.generated.output
// Generated code depends on the JAXB API, which is removed from base Java in JDK 11
compile "org.glassfish.jaxb:jaxb-runtime:2.3.3"
generatedCompile "org.glassfish.jaxb:jaxb-runtime:2.3.3"
}
// XJC tasks
// JAXB configuration holds classpath for running the JAXB XJC compiler
configurations {
jaxb
}
dependencies {
jaxb "org.glassfish.jaxb:jaxb-xjc:2.3.3"
}
// Cookie cutter function for defining multiple XJC tasks
// (not necessary if you only have a single task)!
def addXjcTask(taskName, schema, pkg, dest) {
// If you haven't already, create the generated output dir before running XJC or it will fail
file(dest).mkdirs()
// The main XJC task, calls XJCFacade which is the entry point of the XJC JAR
tasks.create(name: taskName, type: JavaExec) {
classpath configurations.jaxb
main 'com.sun.tools.xjc.XJCFacade'
// To explore available args, download the XJC JAR manually and run java -jar jaxb-xjc.jar --help
args schema, "-p", pkg, "-d", dest
}
// Add a dependency on the new task so it gets invoked
compileGeneratedJava.dependsOn tasks.getByName(taskName)
}
// Add all the XJC tasks you need
addXjcTask("xjcSchema1",
"path/to/schema1.xsd",
'com.example.generated.schema1',
"$generated_dir")
addXjcTask("xjcSchema2",
"path/to/schema2.xsd",
'com.example.generated.schema2',
"$generated_dir")
这就是我在Java 14和Gradle 6.7中的工作我的build.gradle文件看起来像这样:
buildscript {
repositories {
jcenter()
mavenCentral()
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'gradle.plugin.org.openrepose:gradle-jaxb-plugin:2.5.0'
}
}
apply plugin: 'org.openrepose.gradle.plugins.jaxb'
dependencies {
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics:1.11.1'
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics-ant:1.11.1'
jaxb 'org.jvnet.jaxb2_commons:jaxb2-basics-annotate:1.0.4'
jaxb 'org.slf4j:slf4j-log4j12:1.7.25'
jaxb 'org.glassfish.jaxb:jaxb-xjc:2.2.11'
jaxb 'org.glassfish.jaxb:jaxb-runtime:2.2.11'
jaxb 'javax.activation:activation:1.1.1'
}
jaxb {
println 'Starting JAXB XJC...'
xsdDir = "${projectDir}/src/main/resources/schemas/xsd"
xjc {
generateEpisodeFiles = false
destinationDir = "$buildDir/generated/sources/jaxb"
taskClassname = "org.jvnet.jaxb2_commons.xjc.XJC2Task"
generatePackage = "your.own.package.name"
args = ["-Xinheritance", "-Xannotate"]
}
}
// allow schemas with empty namespace
tasks.named("xsd-dependency-tree").configure {
outputs.upToDateWhen { false }
}
compileJava.dependsOn xjc