SpringBoot项目打包结构分离

本文介绍如何通过maven-jar-plugin和maven-assembly-plugin插件优化SpringBoot应用的打包过程,实现依赖分离,便于部署更新。

说明

  1. 通常情况下,SpringBoot打包生成的fat jar太大了,所有的依赖jar包都放置到fat jar里,对于多模块的应用而言,任何的改动,都需要进行整体的打包发布上线,相对于war包中直接更新WEB-INF/lib下的jar而言,显得很繁琐,因此,可以考虑使用maven-jar-plugin + maven-assembly-plugin的方式,修改SpringBoot打包的结构,从而,方便进行依赖jar的改动。另一种方式是maven-jar-plugin + maven-dependency-plugin
  2. maven-assembly-plugin插件的配置分两部分-maven插件本身的配置(plugin的configuration)、插件的额外配置(打包描述文件pkg.xml)。
  3. maven-assembly-plugin的描述符配置官方文档
  4. maven-assembly-plugin作为maven插件的配置官方文档

pom.xml的build配置–maven插件本身的配置

<build>
  <finalName>${project.artifactId}</finalName>
  <plugins>
    <!-- 一定不要使用springboot的maven插件,否则用于执行的jar仍然是很大的,依赖jar包并不会被拆分出来 -->
    <!--<plugin>-->
      <!--<groupId>org.springframework.boot</groupId>-->
      <!--<artifactId>spring-boot-maven-plugin</artifactId>-->
    <!--</plugin>-->

    <!-- 不使用springboot的打包方式,引入jar插件 -->
    <plugin>
      <artifactId>maven-jar-plugin</artifactId>
      <configuration>
        <archive>
          <manifest>
            <mainClass>com.bjqs.test.deploy.ApiApp</mainClass><!-- 指定需要运行的main方法所在类 -->
            <classpathPrefix>lib</classpathPrefix><!-- 可以不是lib,需要与assembly的描述文件中(pkg.xml),依赖的存放位置一致即可 -->
            <addClasspath>true</addClasspath>
          </manifest>
        </archive>
      </configuration>
    </plugin>

    <!-- 引入assembly插件 -->
    <plugin>
      <artifactId>maven-assembly-plugin</artifactId>
      <configuration>
        <appendAssemblyId>false</appendAssemblyId>
        <descriptors>
          <descriptor>src/assembly/pkg.xml</descriptor><!-- 指定自定义打包结构的描述文件位置 -->
        </descriptors>
        <finalName>${project.build.finalName}</finalName><!-- 指定最终生成的jar包的名称 -->
        <encoding>UTF-8</encoding>
      </configuration>
      <executions>
        <execution>
          <id>assembly</id>
          <goals>
            <goal>single</goal>
          </goals>
          <phase>package</phase>
        </execution>

      </executions>
    </plugin>
  </plugins>
</build>

说明

maven-assembly-plugin插件配置自定义描述文件,文件名可以随便起,位置随意,只要在descriptor节点能正确指向这个文件即可。

打包描述文件pkg.xml的配置–assembly插件的额外配置

<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.6.0"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.6.0 http://maven.apache.org/xsd/assembly-2.6.0.xsd">

  <id>bin</id><!-- assembly的插件配置appendAssemblyId为true时,生成的jar会带这个'bin' -->
  <formats>
    <format>dir</format><!-- 打一个文件夹包,一般用于直接在开发电脑上运行 -->
    <format>zip</format><!-- zip压缩包,上传到服务器,需要unzip解压后才可以运行,内容跟dir一样-->
    <format>tgz</format><!-- tar.gz或tgz包,tar -zxf 解压 -->
  </formats>

  <includeBaseDirectory>true</includeBaseDirectory><!-- dir及压缩时是否包含基本目录 -->
  <baseDirectory>release</baseDirectory><!-- fileSets中的内容将输出到这个目录下 -->
  <fileSets><!-- 用于配置文件集,自定义打包结构的核心配置之一 -->
    <!-- 加载启停脚本 -->
    <fileSet>
      <useDefaultExcludes>true</useDefaultExcludes>
      <directory>${project.basedir}</directory>
      <outputDirectory>.</outputDirectory>
      <fileMode>0744</fileMode>
      <lineEnding>unix</lineEnding>
      <includes>
        <include>*.bat</include>
        <include>*.sh</include>
        <include>*.md</include>
        <include>*.txt</include>
      </includes>
      <filtered>true</filtered><!-- 启用过滤,则脚本中的部分${xxx}形式的表达式可以进行替换为实际值-->
    </fileSet>

    <!-- 加载配置到config --><!-- SpringBoot默认最高优先级是config下的配置 -->
    <fileSet>
      <useDefaultExcludes>true</useDefaultExcludes>
      <directory>${project.build.outputDirectory}</directory>
      <outputDirectory>config</outputDirectory>
      <lineEnding>unix</lineEnding>
      <includes>
        <include>*.yml</include>
        <include>*.xml</include>
        <include>*.txt</include>
      </includes>
    </fileSet>

    <!-- 加载打包的jar,这个jar包含了main方法,执行时,执行这个jar,由maven-jar-plugin打包生成的 -->
    <fileSet>
      <useDefaultExcludes>true</useDefaultExcludes>
      <directory>${project.build.directory}</directory>
      <outputDirectory>.</outputDirectory>
      <includes>
        <include>*.jar</include>
      </includes>
    </fileSet>
  </fileSets>

  <!-- 依赖的处理,自定义打包结构的核心配置之二 -->
  <dependencySets>
    <dependencySet>
      <outputDirectory>lib</outputDirectory><!-- 此处的文件夹路径与pom中maven-jar-plugin中classpath前缀一致即可,否则启动jar会提示ClassNotFound问题 -->
      <unpack>false</unpack><!-- 不要解压依赖jar -->
      <scope>runtime</scope><!-- 将runtime依赖复制到lib目录 -->
      <useProjectArtifact>false</useProjectArtifact><!-- 不将可执行jar复制到lib目录,默认是true -->
    </dependencySet>
  </dependencySets>

</assembly>

说明

编写好上述配置后,对工程项目或者可执行jar所在模块,执行mvn clean package或者mvn clean install等待执行完毕即可得到如下结果。

target:

├─classes
│
├─test-mgr                      			-- 最终的名称
│    └─release                  			-- 打包基础目录
│        ├─test-mgr.jar						-- 可执行jar
│        │
│        ├─config               			-- 配置存放目录
│        │   │
│        │   └─application.yml  			-- 配置文件
│        │
│        ├─lib								-- 依赖jar存放目录 
│        │   │
│        │   └─spring-boot-starter-web.jar  -- 依赖jar包
│        │
│        ├─start.sh							-- 启停脚本
│        │
│        └─README.MD						-- 说明文件
│
├─test-mgr.jar								-- mavenen-jar-plugin生成的可执行jar,包含main方法
│
├─test-mgr.zip								-- 内部是release目录的zip压缩包
│
└─test-mgr.tgz								-- 内部是release目录的tgz压缩包
<think>好的,我现在需要帮助用户了解SpringBoot与Vue构建前后端分离项目结构示例和最佳实践。首先,我得回忆一下前后端分离的基本概念。前后端分离意味着前端和后端各自独立开发,通过API进行通信。前端通常用Vue这样的框架,后端用SpringBoot提供RESTful API。 接下来,用户想要项目结构的示例和最佳实践。我需要整理出典型的目录结构。对于SpringBoot后端,常见的结构包括controller、service、mapper、entity等包。而Vue前端可能有src目录下包含components、router、store、api等文件夹。 然后,我需要参考用户提供的引用内容。引用[1]提到vue+springboot+mybatisplus+mysql的项目架构,可以直接扩展代码。引用[2]中的DemoApplication.java展示了SpringBoot的启动类,带有@MapperScan注解,说明使用了MyBatis Plus。引用[4]中的PersonController示例,展示了如何创建RESTful接口,使用@RestController和@RequestMapping。 需要注意前后端如何协作。引用[3]提到前端打包生成dist,后端可能需要配置静态资源处理或者使用Nginx代理。这在项目部署时很重要。 最佳实践方面,应该包括模块化开发、接口规范(如RESTful)、安全措施(JWT)、跨域处理、以及自动化构建部署。比如后端使用Spring Security进行鉴权,前端通过axios调用API,使用Vue Router管理路由。 用户可能还关心如何组织代码,比如后端的分层结构(Controller层处理请求,Service层业务逻辑,Mapper层数据库操作),前端的状态管理(Vuex)和API请求封装。此外,前后端分离项目的配置,如跨域问题的解决,可以通过后端配置CORS或Nginx反向代理。 还要考虑版本控制和项目管理,比如使用Git管理代码,前后端作为不同的仓库或子模块。测试方面,后端可以使用JUnit,前端用Jest或Cypress进行单元和E2E测试。 可能用户没有明确提到但需要注意的点包括环境配置(开发、测试、生产)、日志管理、异常处理、API文档(Swagger)等。这些都能提升项目的可维护性和协作效率。 最后,需要生成相关问题,可能涉及具体技术实现、常见问题解决、性能优化等,比如如何解决跨域问题,如何实现鉴权,如何优化前端打包体积等。确保问题覆盖用户可能遇到的后续疑问。</think>### SpringBoot与Vue前后端分离项目结构示例与最佳实践 #### 1. **项目整体结构** 前后端分离项目通常分为两个独立模块: - **后端(SpringBoot)**:提供RESTful API接口,处理业务逻辑和数据库交互 - **前端(Vue)**:负责UI展示和用户交互,通过axios等工具调用后端接口 #### 2. **后端(SpringBoot项目结构** ```bash src/main/java ├── com.example.demo │ ├── config # 配置类(跨域配置、安全配置等) │ ├── controller # 控制器层(API接口定义)[^4] │ ├── service # 服务层(业务逻辑实现) │ ├── mapper # 数据访问层(MyBatis Plus接口)[^2] │ ├── entity # 实体类(数据库表映射) │ └── DemoApplication.java # 启动类 resources/ ├── application.yml # 配置文件 └── static/ # 可放置前端打包后的dist文件[^3] ``` #### 3. **前端(Vue)项目结构** ```bash src/ ├── api/ # 后端接口封装 ├── assets/ # 静态资源 ├── components/ # 公共组件 ├── router/ # 路由配置 ├── store/ # Vuex状态管理 ├── views/ # 页面组件 └── main.js # 入口文件 ``` #### 4. **关键实践要点** 1. **接口规范**: - 使用RESTful风格设计API,例如: ```java @GetMapping("/users/{id}") public User getUser(@PathVariable Long id) { ... }[^4] ``` 2. **跨域处理**: ```java // SpringBoot配置类示例 @Configuration public class CorsConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:8080") // Vue开发服务器地址 .allowedMethods("*"); } } ``` 3. **安全控制**: - 推荐集成Spring Security实现JWT鉴权 - 前端在axios拦截器中添加token: ```javascript axios.interceptors.request.use(config => { config.headers.Authorization = localStorage.getItem('token') return config }) ``` 4. **构建部署**: - 前端执行`npm run build`生成dist目录 - 后端可通过Nginx代理或直接托管静态资源: ```nginx server { listen 80; location / { root /usr/share/nginx/html/dist; try_files $uri $uri/ /index.html; } location /api { proxy_pass http://backend-server:8080; } } ``` #### 5. **典型接口调用示例** 前端Vue组件调用接口: ```javascript // api/user.js export function getUsers() { return axios.get('/api/users') } // Vue组件 import { getUsers } from '@/api/user' export default { methods: { async loadData() { const res = await getUsers() this.users = res.data } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值