Diferencia entre la compilación del alcance de Maven y la proporcionada para el embalaje JAR

260

¿Cuál es la diferencia entre el alcance de Maven compiley providedcuando el artefacto se construye como un JAR? Si fuera WAR, lo entendería: el artefacto se incluiría o no en WEB-INF / lib. Pero en el caso de un JAR no importa: las dependencias no están incluidas. Tienen que estar en classpath cuando su alcance es compileo provided. Sé que las provideddependencias no son transitivas, pero ¿es solo una diferencia?

emstol
fuente

Respuestas:

289

Del Doc Maven :

  • compilar

    Este es el alcance predeterminado, utilizado si no se especifica ninguno. Las dependencias de compilación están disponibles en todos los classpaths de un proyecto. Además, esas dependencias se propagan a proyectos dependientes.

  • previsto

    Esto es muy parecido a la compilación, pero indica que espera que el JDK o un contenedor proporcionen la dependencia en tiempo de ejecución. Por ejemplo, al crear una aplicación web para Java Enterprise Edition, establecería la dependencia de la API de Servlet y las API de Java EE relacionadas con el alcance proporcionado porque el contenedor web proporciona esas clases. Este alcance solo está disponible en el classpath de compilación y prueba, y no es transitivo.

Resumen:

  • las dependencias no son transitivas (como mencionaste)
  • el alcance provisto solo está disponible en el classpath de compilación y prueba, mientras que el alcance de compilación está disponible en todos los classpaths.
  • las dependencias proporcionadas no están empaquetadas
Jacob
fuente
55
Sí, lo sé. Pero reflexiono sobre la diferencia en los ámbitos en JAR packagingcontexto. Maven doc no lo menciona. Uso Maven por un tiempo, pero ya me he preguntado sobre eso :) Entonces parece que en JAR packagingcontexto, no hay ninguna diferencia entre compiley provided(excepto la transición de dependencia). Estoy en lo cierto?
emstol
3
@Jacob, ¿qué se entiende por "mientras que el alcance de compilación está disponible en todos los classpaths "?
Geek
1
Creo que "NO Transitivo" es la gran trampa aquí. Debido a que el infierno de la dependencia es algo que los desarrolladores enfrentan con mucha frecuencia y el alcance provisto evita que funcione y jugar con otras versiones es crucial.
Seetharamani Tmr
2
Creo que la diferencia está en la fase de envasado. Con la compilación, incluirá el jar en la guerra final o jar (como el jar ejecutable de arranque de primavera), y siempre que no se obtengan resultados. Debido a que el contenedor web puede proporcionar el jar proporcionado (como ponerlo en la carpeta ext lib), no está en el paquete war si no está dependiente de otros ámbitos, compilación y tiempo de ejecución.
Addo Zhang
1
@emstol Volviendo a su pregunta original, tiene razón en que, en el caso de JAR, las dependencias no están empaquetadas dentro del propio JAR. Pero en maven, un paquete JAR significa que desea que se use como biblioteca. Tan pronto como lo importe en algún otro proyecto de Maven, las dependencias transitivas se generarán si el alcance es compiley no lo será si el alcance es provided.
LeoLuz
291

Compilar significa que necesita el JAR para compilar y ejecutar la aplicación. Para una aplicación web, como ejemplo, el JAR se colocará en el directorio WEB-INF / lib.

Proporcionado significa que necesita el JAR para la compilación, pero en el tiempo de ejecución ya hay un JAR proporcionado por el entorno, por lo que no lo necesita empaquetado con su aplicación. Para una aplicación web, esto significa que el archivo JAR no se colocará en el directorio WEB-INF / lib.

Para una aplicación web, si el servidor de aplicaciones ya proporciona el JAR (o su funcionalidad), use "proporcionado" o use "compilar".

Aquí está la referencia.

Owen Cao
fuente
11
¿No estás respondiendo la pregunta del OP? ' ¿Qué diferencia hay en el uso de la compilación de alcance maven y se proporciona cuando el artefacto se construye como un JAR ? 'Tenga en cuenta que el autor declara explícitamente que conoce la diferencia cuando se empaqueta como guerra.
Alberto
¿Puedo usar provisto si estoy haciendo referencia a otro JAR implementado en el mismo servidor de aplicaciones?
Samy Omar
1
Para ser claros, una dependencia proporcionada no se agrega al classpath cuando mvn exec:javase ejecuta, pero sí una dependencia compilada.
Jamie
Hice esta pregunta: stackoverflow.com/questions/37360132/... El problema se resolvió cambiando el alcance de proporcionado a compilado. Pero no veo ninguna diferencia entre jar compilado con alcance "proporcionado" y jar compilado con alcance "compilar". ¿Podrías explicar por qué?
Pavel_K
22

Si planea generar un solo archivo JAR con todas sus dependencias (el típico xxxx-all.jar), entonces el alcance es importante, porque las clases dentro de este alcance no se incluirán en el JAR resultante.

Ver maven-assembly-plugin para más información

jfcorugedo
fuente
77
dependencia proporcionada ==> la dependencia NO se empaquetará.
Gab 是 好人
3
La confusión de OP se resuelve claramente cuando empaqueta maven-assembly-plugin, interesante que las respuestas más votadas no lo mencionen.
Henrique G. Abreu
No entiendo esta respuesta. Se parece más a un comentario.
reinierpost
11
  • compilar

Póngalo a disposición en la ruta de clase, no agregue esta dependencia al jar final si es un jar normal; pero agregue este jar al jar si el jar final es un jar individual (por ejemplo, jar ejecutable)

  • previsto

La dependencia estará disponible en el entorno de tiempo de ejecución, así que no agregue esta dependencia en ningún caso; incluso no en un solo jar (es decir, jar ejecutable, etc.)

Vijay
fuente
3

Para un archivo jar, la diferencia está en el classpath listado en el archivo MANIFEST.MF incluido en el jar si addClassPath se establece en verdadero en la configuración de maven-jar-plugin. las dependencias 'compilar' aparecerán en el manifiesto, las dependencias 'provistas' no lo harán.

Una de mis manías es que estas dos palabras deben tener el mismo tiempo. Ya sea compilado y proporcionado, o compilado y proporcionado.

Almiar
fuente
0

Cuando configura el alcance providedde Maven como , significa que cuando se ejecuta el complemento, la versión de dependencias real utilizada dependerá de la versión de Apache Maven que haya instalado.

Vishwa Ratna
fuente
0

Si el archivo jar es como el archivo jar ejecutable spring boot, el alcance de todas las dependencias debe compileincluir todos los archivos jar.

Pero si el archivo jar se usa en otros paquetes o aplicaciones, entonces no es necesario incluir todas las dependencias en el archivo jar porque estos paquetes o aplicaciones pueden proporcionar otras dependencias por sí mismos.

Ali
fuente