从Java使用NPM Registry

图片



NPM是JavaScript世界中唯一的软件包存储库。基本上,这里是那些可以在前端/浏览器中使用的JS库,但是还有一些服务器端库,不仅可以在node.js中使用。如果您是Java程序员,并且需要与NPM存储库集成,那么很可能会出现以下两种情况之一:



  • 您正在使用一种Java框架编写Web应用程序,并且客户端需要某些NPM软件包
  • 您有一个Java应用程序(例如,对于Android),该应用程序必须能够从NPM请求依赖项和资源/包本身


让我们看看如何用Java做到这一点。



Web应用程序的NPM资源



您有2个选择:



  • 将必要的NPM资源打包在WAR / JAR中
  • 使用CDN在运行时加载所需的资源


在WAR / JAR中打包NPM资源



首先,您需要了解有关WebJars之类的更多信息。它允许您“镜像” NPM(不仅是)软件包到Maven存储库。这样,您可以像使用Maven中的常规Java包一样使用NPM包。例如,为了在您的WAR中包含来自知名Boostrap的资源,只需将以下依赖项添加到pom.xml中就足够了:



<dependency>
    <groupId>org.webjars.npm</groupId>
    <artifactId>bootstrap</artifactId>
    <version>4.5.0</version>
</dependency>


WebJars反映了从NPM到Maven的软件包以及所有必需的依赖关系,因此通过按依赖关系连接一个JAR,将连接所有其他必需的软件包。

WebJars还为不同的Java框架提供了大量库,以便更轻松地处理打包和连接的资源。在文档中阅读更多内容



对于任何Java Backend开发人员而言,WebJars都是一个很好的工具。但是,还有更简便的选择:使用Maven插件从NPM打包所需的软件包。这可能是不完整的列表:



  • jnpm-maven-plugin
  • 前端行家插件
  • npm-maven-plugin


例如,要使用jnpm-maven-plugin包含所需版本的vue和vuex软件包请将以下行添加到pom.xml中:



<plugin>
    <groupId>org.orienteer.jnpm</groupId>
    <artifactId>jnpm-maven-plugin</artifactId>
    <version>1.0</version>
	<executions>
		<execution>
			<goals>
				<goal>install</goal>
			</goals>
			<configuration>
				<packages>
					<package>vue@2.6.11</package>
					<package>vuex@~3.4.0</package>
				</packages>
			</configuration>
		</execution>
	</executions>
</plugin>


您可以使用NPM表示法定义所需版本的范围:



  • 星号(* | X | x)-1. *等于> = 1.0.0&<2.0.0
  • 波浪号(〜)-〜1.5等于> = 1.5.0&<1.6.0
  • 连字符(-)-1.0-2.0等效于> = 1.0.0&<= 2.0.0
  • 脱字符号(^)-^ 0.2.3等于> = 0.2.3&<0.3.0
  • 部分范围-1等于1.X或> = 1.0.0&<2.0.0
  • 负数-!(1.x)等于<1.0.0&> = 2.0.0
  • 困难-〜1.3 | (1.4。*&!= 1.4.5)| 〜2


另外,您可以使用“包含”和“排除”指定要从软件包中包含哪些文件。例如,通常NPM软件包在/ dist目录中包含“已编译”文件。其他文件是源文件,在Java Web应用程序中不太可能需要或有用。要仅包含dist /目录的内容,只需将以下内容添加到该部分:



<includes>
  <include>dist/*</include>
</includes>


默认情况下,jnpm-maven-plugin将资源打包在与WebJars完全相同的路径中。这使得上面提到的WebJars库可以在不同的框架中使用,以访问资源。如果您需要任何其他特定的包装格式,请参阅文档



使用CDN



有许多具有NPM资源的公开可用CDN。最著名和最常用的:



  • 联合国儿童基金会
  • JSDELIVR


您还可以使用自己的CDN(例如,通过docker提出),甚至可以将CDN功能嵌入到Web应用程序中。例如,将以下servlet添加到web.xml以启用JNPM CDN。根据需要进行编辑:



<servlet>
  <servlet-name>CDNServlet</servlet-name>
  <servlet-class>org.orienteer.jnpm.cdn.CDNServlet</servlet-class>
</servlet>
<servlet-mapping>
  <servlet-name>CDNServlet</servlet-name>
  <url-pattern>/cdn/*</url-pattern>
</servlet-mapping>


下载NPM Servlet之后,资源将通过以下URL格式提供:http(s):// <域>:<端口> / <Web应用程序的路径> / cdn / <NPM软件包> / <文件的路径>。

例如:
本地主机:8080/cdn/vue@2.6.11/dist/vue.js




使用Java中的NPM REST API



当然,您可以直接使用NPM Registry REST API,例如通过Retrofit相应的文档将为您提供帮助但是,使用JNPM库更为方便,该库为该REST API等提供了Java包装器。



在pom.xml中包含JNPM Jar:



<dependency>
    <groupId>org.orienteer.jnpm</groupId>
    <artifactId>jnpm</artifactId>
    <version>1.0</version>
</dependency>


让我们初始化JNPM API:



JNPMService.configure(JNPMSettings.builder()
  .homeDirectory(Paths.get("/home/myuser/.jnpm")) //
  .downloadDirectory(Paths.get("/tmp")) //
  //   - . 
 	.build());


JNPM API提供了2个选项:同步API和通过RXJava的异步API。具体使用哪种取决于您:



JNPMService jnpmService = JNPMService.instance(); //Synchronous Java API
RxJNPMService rxJnpmService = JNPMService.instance().getRxService() //RXJava API


用法示例:



//   NPM 
System.out.println(JNPMService.instance().getRegistryInfo());
//       VUE
System.out.println(JNPMService.instance().getPackageInfo("vue").getLatest());
//   vue@2.6.11
System.out.println(JNPMService.instance().getVersionInfo("vue", "2.6.11").getDescription());
//      
System.out.println(JNPMService.instance().bestMatch("vue@<2").getVersionAsString());
//   vue@2.6.11    
VersionInfo vueVersion = JNPMService.instance().getVersionInfo("vue", "2.6.11");
vueVersion.downloadTarball().blockingAwait();
System.out.println(vueVersion.getLocalTarball().getAbsolutePath());
// "vue"     
System.out.println(JNPMService.instance().search("vue").getObjects().get(0).getSearchPackage().getDescription());
//       dev    vue 
//            NPM (node_modules/vue  ..)
JNPMService.instance().getRxService()
   .traverse(TraverseDirection.WIDER, TraversalRule.DEV_DEPENDENCIES, "vue")
   .subscribe(t -> {System.out.println(t); t.install(Paths.get("target", "readme"), InstallationStrategy.NPM);});


如果您有此处未描述的特定案例-请让我知道!



All Articles