Maven简介

Maven简介

什么是Maven

Maven 的本质是一个项目管理工具,将项目开发和管理过程抽象成一个项目对象模型POM

如图蓝色部分为 Maven,其不包括外部其他部分,上部分为核心,下部分为各种插件。Maven 的作用如下

  • 项目构建: 提供标准的、跨平台的自动化项目构建方式
  • 依赖管理: 方便快捷的管理项目依赖的资源包,避免资源之间的版本冲突问题
  • 统一开发结构: 规定了 srcresourcetarget 等统一项目结构

Maven 是由 Java 语言编写的,同样采用了面向对象的思想

Maven安装

  1. 点击进入 Maven 官网进行下载 maven.apache.org/
  2. 解压文件到没有空格、没有中文的目录下
  3. 【可选】打开 maven目录/conf/settings.xml 配置文件,配置阿里镜像地址(配置到 <mirrors> 标签里)
xml 复制代码
<mirror>
    <id>alimaven</id>
    <name>aliyun maven</name>
    <url>https://maven.aliyun.com/repository/central/</url>
    <mirrorOf>central</mirrorOf>
</mirror>
  1. 【可选】配置环境变量:新建 MAVEN_HOME:Maven根目录,修改Path添加 %MAVEN_HOME%\bin (注意:Maven 依赖环境变量中有 JAVA_HOME),CMD输入 mvn -v 验证
  2. 【可选】因为Java默认的最大可用内存往往不够满足Maven运行需要,比如较大的项目时,使用Maven生成项目站点需要占用大量内存,可选配置 MAVEN_OPTS:-Xms128m -Xmx512m

注意 Maven 是由 Java 研发的,所以 Maven 依赖 Java

Maven概念

仓库概念:仓库用于存储资源(各种 Jar 包),其分为本地仓库远程仓库中央仓库

  • 本地仓库: 自己电脑上存储资源的仓库
  • 远程仓库: 也叫作 Maven 私服,部门/公司范围内储存资源的仓库
  • 中央仓库: Maven 团队维护的,维护所有资源的仓库

坐标概念:坐标用于描述仓库中资源的位置,其构成部分及说明如下:

  • gourpId:组织名,定义该 Maven 项目隶属组织,常是域名反写,如 org.example.demo
  • artifactId:项目名,定义该 Maven 项目名称
  • version:版本号,定义该 Maven 项目的版本号
  • packaging:定义项目的打包方式,如成果物类型 warjar,如组织项目的 pom 类型

Jar 包的获取会逐级搜索,如本地仓存在则直接使用本地仓,如不存在则到远程仓获取。以此类推

Maven使用

生命周期命令

命令 说明
mvn archetype:generate 创建 Maven 项目,可通过参数指定坐标等 可以使用骨架:常用7号 quickstart 普通项目,10号 webappWEB 项目
mvn clean 把已经编译好的项目的所有信息清除(target 文件夹)
mvn compile 自动导入 POM 中的依赖,并把核心代码部分编译后,放置在 target 目录下
mvn test 通过此命令可以执行 test 文件夹下的测试用的内容,实现项目测试(同时执行了 compile
mvn package Maven 项目进行打包,放置在 target 目录下(同时执行了 test
mvn install 将刚刚项目打完的包安装到本地仓库,由 maven 进行管理(同时执行了 package
mvn deploy 项目发布,将 maven 本地库中管理的资源发布到远程库中

POM文件结构

xml 复制代码
<!--当前项目的maven资源坐标-->
<groupId>org.example</groupId>
<artifactId>MVNDemo01</artifactId>
<version>1.0-SNAPSHOT</version>

<!--此项目在mvn package的过程中,要打成什么样的包,通常是jar或war,也可能是pom-->
<packaging>jar</packaging>

<!-- 项目相关信息 -->
<name>MVNDemo01</name>
<description>xxx</description>
<url>http://maven.apache.org</url>

<!-- 参数配置 -->
<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<!-- 依赖管理 -->
<dependencies>
    <dependency>
    </dependency>
</dependencies>

<!-- 依赖版本管理 -->
<dependencyManagement>
</dependencyManagement>

<!-- 项目构建 -->
<build>
    <plugins>
        <plugin>
        </plugin>
    </plugins>
</build>

依赖传递

依赖是可以传递的,很有可能会发生依赖传递冲突问题,其优先级如下:

  1. 路径优先: 当依赖中出现相同的资源时(可能版本号不同),层级越浅,优先级越高
  2. 声明优先: 当资源在相同层级被依赖时,配置顺序考前的覆盖配置顺序靠后的
  3. 特殊优先: 当在同 POM 文件中声明时,后配置的覆盖先配置的

处理依赖传递有如下两种标签:

  • 可选依赖: 控制引用该资源的项目无法看到该依赖
  • 排除依赖: 主动排除掉该资源中的指定依赖
xml 复制代码
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>springboot</artifactId>
    <version>1.1</version>
    <!-- 可选依赖(默认false,可传递) -->
    <optional>true</optional>
    <!-- 排除依赖 -->
    <exclusions>
        <exclusion>
            <groupId>org.springframework</groupId>
            <artifactId>bbb</artifactId>
        </exclusion>
    </exclusions>
</dependency>

依赖范围

依赖范围: 可以通过 <scope> 标签指定其依赖范围,其作用如下:

scope 编译 测试 打包 范例
compile(默认) Y Y Y log4j
test Y junit(仅测试使用)
provided Y Y 不传递 servlet-api(Tomcat中包含)
runtime Y jdbc(可防止编写时意外导入)
system Y Y 插件配置 includeSystemScope 依赖来自本地系统,需要配合标签 systemPath 使用
import 引入依赖项目,配合 <type>pom</type> 使用

依赖范围具有传递性,开发时根据实际情况使用

插件使用

插件的使用可以通过官网查询,不同插件有不同使用方式,根据文档说明进行操作。如下简单示例源码插件配置

xml 复制代码
<build>
    <plugins>
        <!-- 使用具体插件 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>2.1.3.RELEASE</version>
            <!-- 配置执行条件/位置:具体使用参考插件文档 -->
            <executions>
                <execution>
                    <!-- 操作目标,如下为主代码及test代码 -->
                    <goals>
                        <goal>jar</goal>
                        <goal>test-jar</goal>
                    </goals>
                    <!-- 插件执行阶段(生命周期哪个阶段) -->
                    <phase>generate-resources</phase>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

多模块管理

Model聚合

聚合 用于快速构建 Maven 工程,一次性构建多个项目/模块。如多个项目/模块依赖,执行命令时需要每一个工程都进行编译,打包,安装,测试,部署等生命周期的命令,一个一个去执行这些命令效率非常低

Maven 提供了聚合的配置,实现统一执行命令,实现方法:创建一个无代码聚合工程,并在 POM 中配置所有聚合的项目/模块

xml 复制代码
<!-- 打包类型为聚合 -->
<packaging>pom</packaging>
<!-- 配置模块名称 -->
<modules>
    <!-- 标签内部值为子模组pom.xml所在路径 -->
    <!-- 表示与自己同级的child1项目目录 -->
    <module>../child1</module>
    <!-- 表示为自己目录下child2项目目录 -->
    <module>child2</module>
  </modules>

只是聚合项目关心有什么模块,模块不需要知道被谁聚合了

Maven继承

Maven 项目提供继承 的特性,可以利用继承实现所有项目资源版本统一的问题。其继承的父类资源包括:

继承项 说明
groupId version 项目相关的内容。可以重写,默认父类的值
properties 父级工程在 properties 标签中定义的变量,子工程使用 ${} 使用
dependencies 相当于强制继承,子工程中一定被导入父工程该标签内的 Jar
dependencyManagement 常用的一种统一资源的继承方式,只会继承版本而不会强制让子工程依赖资源 子工程通过在 dependency 内添加 groupIdartifactId 即可,当然也可以重写 version 版本号
build pluginManagement 如上的一种统一资源的继承方式,其使用如上,不仅继承版本号,还会继承声明的使用方式

继承 的实现需要子项目声明父项目,注意 Maven单继承,其声明方式如下:

xml 复制代码
<!-- 定义工程的父工程 -->
<parent>
    <groupId>org.example.parent</groupId>
    <artifactId>demo-parent</artifactId>
    <version>1.0.0.RELEASE</version>
    <!-- 填写父工程的POM位置,省略不写视为在父工程内/父工程为远程项目,仓库获取 -->
    <relativePath>../parent/pom.xml</relativePath>
</parent>

只是子项目声明了父项目是谁,父项目不需要知道被谁继承了

属性管理

Maven 提供属性管理,其管理方式属性类型有:自定义属性内置属性Setting属性Java系统属性环境变量属性

xml 复制代码
<!-- 定义自定义属性 -->
<properties>
    <mybatis-plus.version>3.1.2</mybatis-plus.version>
    <druid.version>1.1.17</druid.version>
</properties>

<!-- 使用自定义属性 -->
<version>${druid.version}</version>

<!-- 内置属性:含 ${basedir} ${version} 等 -->

<!-- Setting属性:配置文件 setting.xml 中的标签属性,属于动态属性,如 ${settings.localRepository} 等 -->

<!-- Java系统属性、环境变量属性:通过命令 mvn help:system 可以获取到属性 -->

Maven 提供资源加载属性值功能,其为项目内的其他资源文件使用定义的自定义属性,调用方式相同 ${} 使用如下

xml 复制代码
<!-- 定义哪个文件夹下文件开启POM属性过滤功能,检测到 ${} 就替换属性 -->
<build>
    <resources>
        <resource>
            <directory>${project.basedir}/src/main/resources</directory>
            <filtreing>true<filtering>
        </resource>
    </resources>
</build>

版本管理含 RELEASESNAPSHOT,正式版、快照版
Maven 可以进行多环境配置参数,通过打包命令添加参数完成,可了解一下

Maven私服

Nexus】为常用私服,安装及使用绕道参考

常用插件使用

JDK版本

更改编译 Java 源码的 jdk 版本

xml 复制代码
<!-- 通过更改项目的 pom.xml,添加 java 编译插件 -->
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>utf-8</encoding>
            </configuration>
        </plugin>
    </plugins>
</build>

<!-- 或者在 properties 设置 jdk 版本 -->
<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
 </properties>

更改 Maven 默认JDK 版本,更改 Maven 目录下的 conf/settings.xml 文件,以后建立的项目源码编译都是指定的 jdk 版本

xml 复制代码
<profile>
    <id>jdk-1.8</id>
    <activation>
        <activeByDefault>true</activeByDefault>
        <jdk>1.8</jdk>
    </activation>
    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
    </properties>
</profile>

各种常用插件

xml 复制代码
<!-- Spring项目打包插件:可能和 appassembler-maven-plugin 不兼容 -->
<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

<!-- 测试插件:不写进行默认测试,这里配置了该插件跳过测试 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <skipTests>true</skipTests>
    </configuration>
</plugin>

<!-- 应用不部署到远程仓库中 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-deploy-plugin</artifactId>
    <configuration>
        <skip>true</skip>
    </configuration>
</plugin>

Appassembler打包

Appassembler 打包有三种核心打包方式,其中常用打包为可执行程序守护服务 方式。如下介绍最为常用的守护方式,该方式可生成资源后直接在服务器中运行为服务

Appassembler 打包方式的优点:

  1. 通过 wrapper 方式进行管理,直接运行 bin/ 下的可执行文件 start | stop | console | restart
  2. 分包管理 lib 依赖,其打包方式不会将所有依赖打包到一个可执行文件中,分包管理,方便更改部分 jar 包代码,进行部分更新
  3. 管理资源文件,可以通过设置,让程序首先使用 conf/ 文件夹下的资源/配置文件,当找不到时才找 jar 包内资源
  4. 当更新程序时,操作步骤更为简单:
  5. 把需要更新的 jar 包覆盖到 lib/
  6. 保证是否需要更新配置文件 conf/
  7. 运行可执行文件 xxx restart 重启服务
xml 复制代码
<!-- 使用说明: -->
<!-- 1. 修改对应的项目名称 -->
<!-- 2. 修改属性值,输出文件夹目录 -->
<!-- 3. 修改启动类,如下 mainClass 标签 -->

<!-- 配置项目名称及属性,后期配置使用 -->
<name>demo</name>
<properties>
    <appassembler.out.name>appassembler-out</appassembler.out.name>
</properties>

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>appassembler-maven-plugin</artifactId>
    <version>2.1.0</version>
    <!-- 配置插件启动时机 -->
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <goal>generate-daemons</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- 打包后生成的目录位置及各目录 -->
        <target>${project.build.directory}/${appassembler.out.name}</target>
        <binFolder>bin</binFolder>
        <logsDirectory>logs</logsDirectory>
        <repositoryName>lib</repositoryName>
        <!-- 为系统配置文件指定一个目录 -->
        <configurationDirectory>conf</configurationDirectory>
        <!-- 源代码中对应的系统配置文件的位置 -->
        <configurationSourceDirectory>src/main/resources</configurationSourceDirectory>
        <!-- 是否将配置文件包含到classpath -->
        <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
        <!-- 是否拷贝源代码中配置文件中的目录 -->
        <copyConfigurationDirectory>true</copyConfigurationDirectory>
        <!-- 依赖的lib包的目录格式,flat表示不分目录平铺到lib目录下 -->
        <repositoryLayout>flat</repositoryLayout>
        <daemons>
            <daemon>
                <!-- 基本信息配置:名称及启动类 -->
                <id>${project.name}</id>
                <mainClass>org.example.Starter</mainClass>
                <!-- JVM配置设置 -->
                <jvmSettings>
                    <maxStackSize>128</maxStackSize>
                    <extraArguments>
                        <extraArgument>-server</extraArgument>
                        <extraArgument>-XX:+AggressiveOpts</extraArgument>
                        <extraArgument>-Xmx1G</extraArgument>
                        <extraArgument>-XX:+HeapDumpOnOutOfMemoryError</extraArgument>
                    </extraArguments>
                </jvmSettings>
                <!-- 打包平台配置 -->
                <platforms>
                    <platform>jsw</platform>
                </platforms>
                <generatorConfigurations>
                    <generatorConfiguration>
                        <generator>jsw</generator>
                        <includes>
                            <!-- include>linux-x86-32</include -->
                            <!-- include>linux-ppc-64</include -->
                            <include>linux-x86-64</include>
                            <include>windows-x86-64</include>
                        </includes>
                        <configuration>
                            <!-- 手动添加一个系统启动时依赖的第一个classpath,这里通常写为配置文件的目录名,如果不配置,配置文件无法找到 -->
                            <property>
                                <name>configuration.directory.in.classpath.first</name>
                                <value>conf</value>
                            </property>
                            <!-- 依赖jar包位置 -->
                            <property>
                                <name>set.default.REPO_DIR</name>
                                <value>lib</value>
                            </property>
                            <!-- 日志文件位置 -->
                            <property>
                                <name>wrapper.logfile</name>
                                <value>logs/wrapper-${project.name}.log</value>
                            </property>
                            <!-- 日志文件格式:MB兆的方式格式 -->
                            <property>
                                <name>wrapper.logfile.format</name>
                                <value>M</value>
                            </property>
                            <!-- 日志文件最大值:10MB -->
                            <property>
                                <name>wrapper.logfile.maxsize</name>
                                <value>10m</value>
                            </property>
                            <!-- 日志文件最大分割值:5 -->
                            <property>
                                <name>wrapper.logfile.maxfiles</name>
                                <value>5</value>
                            </property>
                            <!-- 配置Windows服务:效果未检测 -->
                            <property>
                                <name>wrapper.ntservice.interactive</name>
                                <value>true</value>
                            </property>
                        </configuration>
                    </generatorConfiguration>
                </generatorConfigurations>
            </daemon>
        </daemons>
    </configuration>
</plugin>

该插件可能与 Spring Boot 打包插件冲突,如出现找不到主类清单错误,可选择注释掉 Spring Boot 打包插件(spring-boot-maven-plugin

Assembly打包

Assembly 打包是 Maven 提供的一种打包方式,可以输出自定义的包类型。如上输出守护服务 的资源后,可以再通过该插件进行打包输出

xml 复制代码
<!-- 集合打包插件 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-assembly-plugin</artifactId>
    <executions>
        <execution>
            <phase>package</phase>
            <goals>
                <!-- 只执行一次 -->
                <goal>single</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <!-- 描述文件所在位置 -->
        <descriptors>
            <descriptor>src/main/assembly/assembly-linux.xml</descriptor>
            <descriptor>src/main/assembly/assembly-win.xml</descriptor>
        </descriptors>
    </configuration>
</plugin>

描述文件用于描述输出文件,如下输出两个压缩文件(文件内容来自上个插件的输出结果)

xml 复制代码
<!-- src/main/assembly/assembly-linux.xml -->
<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>linux</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <formats>
        <format>tar.gz</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/bin</directory>
            <outputDirectory>${project.name}/bin</outputDirectory>
            <fileMode>0755</fileMode>
            <includes>
                <include>${project.name}</include>
                <include>wrapper-linux*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/lib</directory>
            <outputDirectory>${project.name}/lib</outputDirectory>
            <includes>
                <include>*.jar</include>
                <include>libwrapper-linux*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/conf</directory>
            <outputDirectory>${project.name}/conf</outputDirectory>
            <includes>
                <include>*.yml</include>
                <include>banner.txt</include>
                <include>wrapper.conf</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/logs</directory>
            <outputDirectory>${project.name}/logs</outputDirectory>
            <excludes>
                <exclude>**/*</exclude>
            </excludes>
        </fileSet>
    </fileSets>
</assembly>
xml 复制代码
<!-- src/main/assembly/assembly-win.xml -->
<assembly
    xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    <id>win</id>
    <includeBaseDirectory>false</includeBaseDirectory>
    <formats>
        <format>zip</format>
    </formats>
    <fileSets>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/bin</directory>
            <outputDirectory>${project.name}/bin</outputDirectory>
            <fileMode>0755</fileMode>
            <includes>
                <include>${project.name}</include>
                <include>wrapper-windows*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/lib</directory>
            <outputDirectory>${project.name}/lib</outputDirectory>
            <includes>
                <include>*.jar</include>
                <include>libwrapper-windows*</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/conf</directory>
            <outputDirectory>${project.name}/conf</outputDirectory>
            <includes>
                <include>*.yml</include>
                <include>banner.txt</include>
                <include>wrapper.conf</include>
            </includes>
        </fileSet>
        <fileSet>
            <directory>${project.build.directory}/${appassembler.out.name}/jsw/${project.name}/logs</directory>
            <outputDirectory>${project.name}/logs</outputDirectory>
            <excludes>
                <exclude>**/*</exclude>
            </excludes>
        </fileSet>
    </fileSets>
</assembly>

资源打包插件

Maven 项目默认资源在 src/main/resources 目录下,如果资源不在此目录下,需要添加 maven-resources-plugin 插件,并在 resource 中配置资源路径

xml 复制代码
<!-- 资源打包插件 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-resources-plugin</artifactId>
</plugin>

<!-- 配合 resources 插件添加资源目录 -->
<resources>
    <resource>
        <directory>src/main/resources</directory>
        <!-- 打开变量替换声明 -->
        <!-- filtering>true</filtering -->
    </resource>
    <resource>
        <directory>src/main/java</directory>
        <includes>
            <include>**/*.xml</include>
        </includes>
    </resource>
</resources>

Tomcat插件

下面介绍的是 tomcat7 插件在 pom.xml 文件中的配置,端口默认是 8080path 默认是项目名称(可以在 configuration 标签内进行修改)。执行命令 mvn tomact7:run 运行

xml 复制代码
<!-- 构建 -->
<build>
    <plugins>
        <!-- 添加tomcat服务器插件 -->
        <plugin>
            <groupId>org.apache.tomcat.maven</groupId>
            <artifactId>tomcat7-maven-plugin</artifactId>
            <version>2.1</version>
            <configuration>
                <!-- 配置tomcat端口 -->
                <port>8080</port>
                <!-- Web应用的访问路径
                <path>HelloWorld</path>
                -->
                <!-- 配置tomcat编码,解决GET乱码 -->
                <uriEncoding>UTF-8</uriEncoding>
            </configuration> 
        </plugin>
    </build>
</plugins>

使用技巧

清理小工具

Maven 本地仓库同步的时候会产生很多不存在的 Jar 包下载准备文件,可以通过该命令行脚本进行清理,保存到 .bat 文件中,在 windows 双击使用

bash 复制代码
set REPOSITORY_PATH=E:\MavenRepo
rem 正在搜索...
for /f "delims=" %%i in ('dir /b /s "%REPOSITORY_PATH%\*lastUpdated*"') do (
    del /s /q %%i
)
rem 搜索完毕
pause
相关推荐
NiNg_1_2342 小时前
SpringBoot整合SpringSecurity实现密码加密解密、登录认证退出功能
java·spring boot·后端
Chrikk3 小时前
Go-性能调优实战案例
开发语言·后端·golang
幼儿园老大*3 小时前
Go的环境搭建以及GoLand安装教程
开发语言·经验分享·后端·golang·go
canyuemanyue3 小时前
go语言连续监控事件并回调处理
开发语言·后端·golang
杜杜的man3 小时前
【go从零单排】go语言中的指针
开发语言·后端·golang
customer085 小时前
【开源免费】基于SpringBoot+Vue.JS周边产品销售网站(JAVA毕业设计)
java·vue.js·spring boot·后端·spring cloud·java-ee·开源
Yaml46 小时前
智能化健身房管理:Spring Boot与Vue的创新解决方案
前端·spring boot·后端·mysql·vue·健身房管理
小码编匠7 小时前
一款 C# 编写的神经网络计算图框架
后端·神经网络·c#