最近在公司项目需要做前端优化,项目是一个比老的项目,前端使用的是easyui后端用的是spring mvc。目前后端已经把代码迁移到spring-boot框架。但前端一直还是用的easyui,由于当前vue比较火爆,于是尝试用vue进行前端界面优化。本人之前有过使用vue的经验,这个任务就交到我身上了(我太难了。。)主流的使用vue的方式是使用前后端分离的方式,即后端用微服务架构,前端用nginx作为web服务器。但由于项目团队前端力量薄弱,所以我采用了一种维护成本较低的方式,即开发的时候使用前后端分离开发,但打包阶段把前端代码和后端代码整合到一个包中部署。这样无需额外再安装nginx服务,最后只需部署springboot的项目即可。
这里有两种方式,可以实现这个功能。在前端打包到后端工程之前,还需要把后端项目先配置好。SpringBoot对于前端UI是支持多种模板引擎的。但由于前端工程打包之后的文件是html文件,所以SpringBoot工程只能配置基于html文件的模板引擎,这里我使用官方推荐的thymeleaf模板引擎。
SpringBoot项目配置
通过官方网站初始化SpringBoot工程,在pom.xml中加入thymeleaf模板引擎依赖,同时还需要加入html5文件的非严格检查依赖,同时在application.yml中加入必要的配置,不然浏览器可能会报错,具体配置如下
<!-- thymeleaf模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- html5非严格检查 -->
<dependency>
<groupId>net.sourceforge.nekohtml</groupId>
<artifactId>nekohtml</artifactId>
<version>1.9.22</version>
</dependency>
application.xml的配置如下
server:
port: 8090
spring:
# templates 模板引擎配置
thymeleaf:
mode: LEGACYHTML5 # 不进未关闭标签检查,需配合nekohtml使用
encoding: UTF-8
cache: false # 关闭缓存
prefix: classpath:/templates/
suffix: .html
工程创建完成后,目录结构如下。其中resources下的templates就是前端代码的文件路径。下面还有一个static目录,这其实是vue打包完成后的文件目录。vue打包完成的文件名就叫static,这里是原封不动的放在了templates目录下。因此这里还需要一个额外的操作,不然前端可能无法访问static下的静态文件。
vue打包完成后是以static作为根路径去加载 js和css文件的,所以需要对static里面的文件做一次映射,把templates/static/目录映射成/static目录,对应的SpringBoot配置类如下
package com.lsj.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
@Configuration
@EnableWebMvc
@ComponentScan
public class InterceptorConfig implements WebMvcConfigurer {
/**
* 静态文件映射
* addResourceHandler指的是对外暴露的访问路径,addResourceLocations指的是文件放置的目录
* 映射之后,Controller返回到 html ,使用映射后的路径
* 如下将 static 下的静态文件映射到根路径下,
* 文件实际路径 /static/semantic/semantic.min.js 映射之后
* 在 html 中就可以通过 semantic/semantic.min.js 路径访问静态文件
*
* 也可映射绝对路径,例如下面注释,把D盘static中的静态文件,映射到项目根路径下
* */
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**").addResourceLocations(ResourceUtils.CLASSPATH_URL_PREFIX+"/templates/static/");
}
}
到这里后端工程准备完毕,下面用前端工程来搞点事情吧。把前端工程的代码整合到后端工程中,这里有两种方式,第一种简单粗暴但不适合自动化部署,第二种比较复杂些,但是可以通过maven一键打包。
方式一
前端开发好后将build构建好的dist下的文件拷贝到springboot的resources的static下。操作步骤:前端vue项目使用命令 npm run build 或者 cnpm run build 打包生成dist文件,在springboot项目中resources下建立static文件夹,将dist文件中的文件复制到static中,然后去application中跑起来boot项目,这样直接访问index.html就可以访问到页面(api接口请求地址自己根据情况打包时配置或者在生成的dist文件中config文件夹中的index.js中配置)
这是vue前端工程的目录结构,使用npm打包后会生成dist目录。我们需要把dist目前下的全部文件都拷贝到后端SpringBoot工程中resources目录的templates目前下。然后启动前端工程就可以了。这是最简单的方式,但是如果作为工程级的项目开发,并不推荐使用手工合并。下面是第二种方式
方式二
为了前后端代码分离开发,这里我创建了两个独立的工程,一个后端工程和一个前端工程,然后两个工程通过maven聚合组成一个工程。最终工程的目录结构如下
具体的pom.xml的配置如下
<!-- parent -->
<modules>
<module>vue-element-demo</module>
<module>spring-boot-demo</module>
</modules>
<!-- spring -->
<parent>
<groupId>com.lsj</groupId>
<artifactId>spring-vue-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
<!-- vue -->
<parent>
<groupId>com.lsj</groupId>
<artifactId>spring-vue-parent</artifactId>
<version>1.0-SNAPSHOT</version>
<relativePath>../</relativePath>
</parent>
然后在vue工程中就不再直接使用npm打包了,而是通过maven调用npm的打包命令。vue工程pom.xml的关键的配置
<plugins>
<!-- 调用npm命令插件 -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<!-- 先执行前端依赖下载 -->
<execution>
<id>exec-npm-install</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>npm</executable>
<arguments>
<argumnet>install</argumnet>
</arguments>
<workingDirectory>${basedir}</workingDirectory>
</configuration>
</execution>
<!-- npm打包 -->
<execution>
<id>exec-npm-run-build</id>
<phase>package</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>npm</executable>
<arguments>
<argumnet>run</argumnet>
<argumnet>build</argumnet>
</arguments>
<workingDirectory>${basedir}</workingDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
SpringBoot工程pom.xml关键配置
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<mainClass>com.lsj.StartApplication</mainClass>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- 把vue打包后的 dist目录下的所有文件拷贝到resource目录下 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resource.version}</version>
<executions>
<execution>
<id>copy-static</id>
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/main/resources/templates</outputDirectory>
<overwrite>true</overwrite>
<resources>
<resource>
<!-- 因为vue-cli打包目录在项目跟目录,所以从这里复制 -->
<directory>../vue-element-demo/dist</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
父工程中配置编译插件
<build>
<plugins>
<!--编译插件-->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven.compiler.version}</version>
<configuration>
<source>${java.source.version}</source>
<target>${java.target.version}</target>
<encoding>${file.encoding}</encoding>
</configuration>
</plugin>
</plugins>
</build>
最终只需要执行父工程的打包命令,即可将前后端整体打包成一个jar包。部署时只需部署这个jar包就行了