Spring boot and Vue deployment solutions you don't know

Eternal clouds 2020-11-09 12:33:12
spring boot vue deployment solutions


Some time ago, the demonstration environment of the company's external network deployment was all transferred to the Intranet environment , All external demonstration environments need to apply for external network mapping to access a certain service . I use an Internet address www.a.com Mapping to an intranet address http://ip:port, And then at this address http://ip:port use nginx Acting as a proxy to forward items to groups http://ipn:portn Up , There are also some static resources 404, The main thing is to solve this problem 404 problem .

I've done another project recently , Considering the user experience , Reduce the complexity of deployment , I thought of a way to use SpringBoot do web Server mapping front-end resources are web resources .

<font color=red> Conditions permit or require high performance , It is recommended that the front and rear end be deployed separately ,nginx do web The server , The back end only provides interface services </font>

Previously deployed projects A The Internet access address is http://ip1:8080, After mapping, you can only access http://ip/app1 , Previous projects B The Internet access address is http://ip1:8081 , The project address is http://ip/app2 . This is not a small change , But the first problem after switching is that static resource forwarding leads to 404.

For example, previous projects A The address is http://ip1:8080 It has no context .

And now A The address of is http://ip/app1 , There is a context app1 ad locum , It leads to some resources 404.

for instance : original http://ip1:8080 Request arrived. index.html resources , Now we can only http://ip/app1 Ask to index.html.

<!-- index.html -->
<!-- The original deployment environment is written in -->
<link href="/index.css" rel="stylesheet">

Previously visited index.css The address is http://ip1:8080/index.css , But now it's an interview http://ip/index.css Lead to 404, actual index.css The address is http://ip/app1/index.css

Front end use vue To write ,html The static resource path in can be well solved , modify webpack Just pack it .

<!-- The original deployment environment is written in -->
<link href="/index.css" rel="stylesheet">
<!-- Write it as a relative path -->
<link href="./index.css" rel="stylesheet">
<!-- combination webpack Path supplement when packing -->
<link href="<%= BASE_URL %>index.css" rel="stylesheet">

However, there are some component requests in the project that cannot be handled uniformly , You can only change the code . But I don't want to move code ,webpack I don't want to move the package , Based on these needs, I think of a way to solve .

The content of this article is

  • Nginx Deploy vue project , How to handle the loss of static resources in a friendly way
  • SpringBoot Provide web Function mapping of the server vue The project is web resources , And deal with vue Routing and forwarding index.html problem .

Demo code address


Nginx Deploy Vue project

server {
listen 8087;
# Its function is not to redirect addresses , For example, browser input /app1 visit , You can also visit /app1/ , And the browser address doesn't change /app1 . Can't , Obsessive compulsive disorder 
location / {
try_files $uri $uri/;
root /Users/zhangpanqin/staic/;
location ~ /(.*)/ {
index index.html /index.html;
try_files $uri $uri/ /$1/index.html;

/Users/zhangpanqin/staic/ Put deployed projects , such as app Project resources are put into /Users/zhangpanqin/staic/app Next . The visiting address is http://ip/8087/app

<!DOCTYPE html>
<html lang="en">
<!-- It can also be changed to a similar address BASE_URL be equal to vue.config.js Configured publicPath-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- After deployment , Can't access index.css -->
<link href="/index.css" rel="stylesheet">

In order to be able to enter vue The routing /app/blog You can also visit the page , Need to add vue-router Medium base attribute .

import Vue from 'vue';
import VueRouter from 'vue-router';
const routes = [
path: '/',
name: 'Home',
component: () => import('@/views/Home.vue'),
path: '/blog',
name: 'Blog',
component: () => import('@/views/Blog.vue'),
// Jump here when the route cannot be matched 
path: '*',
name: 'Error404',
component: () => import('@/views/Error404.vue'),
const router = new VueRouter({
// It's mainly to modify here , According to vue mode Environment .
// https://cli.vuejs.org/zh/guide/mode-and-env.html
// https://router.vuejs.org/zh/api/#base
base: process.env.VUE_APP_DEPLOY_PATH,
mode: 'history',
export default router;

<img src="http://oss.mflyyou.cn/blog/20200727234702.png?author=zhangpanqin" alt="image-20200727234702928" style="zoom: 25%;" />

http://localhost:8087/app/index.css by css The real address of . So try to find a way not to /app Resources at the beginning plus /app That's all right. , After thinking about it, only cookie Can do .

x_vue_path Record the path of each project , Then static resources go to this path to find ,$cookie_x_vue_path/$uri

The following configuration uses try_files Internal redirection resources , There will be no redirection on on the browser side .

# gzip , cache and epoll None of the optimized ones have been written 
server {
listen 8087;
# Its function is not to redirect addresses , For example, browser input /app1 visit , You can also visit /app1/ , And the browser address doesn't change /app1 . Can't , Obsessive compulsive disorder 
location / {
try_files $uri $uri/;
root /Users/zhangpanqin/staic/;
# (.*) Which item is the match , for instance app1 app2 etc. 
location ~ /(.*)/.*/ {
index index.html /index.html;
add_header Set-Cookie "x_vue_path=/$1;path=/;";
# /Users/zhangpanqin/staic/+/$1/index.html You can go to each project index.html
try_files $uri $uri/ /$1/index.html @404router;
# Find static resources , You can also add a cache here .
location ~ (.css|js)$ {
try_files $uri $cookie_x_vue_path/$uri @404router;
location @404router {
return 404;


Here is the redirection configuration

server {
listen 8087;
root /Users/zhangpanqin/staic/;
location ~ /(.*)/.*/? {
index index.html /index.html;
add_header Set-Cookie "x_vue_path=/$1;path=/;";
try_files $uri $uri/ /$1/index.html @404router;
location ~ (.css|js)$ {
# Match to /app/index.css Resources for , Direct access 
rewrite ^($cookie_x_vue_path)/.* $uri break;
# Resources accessed /index.css 302 Temporarily redirect to /app/index.css
rewrite (.css|js)$ $cookie_x_vue_path$uri redirect;
location @404router {
return 404;


According to this idea, all resources can be forwarded , Don't change the business code , Just give vue-router Add a base Basic routing .

SpringBoot Deploy Vue project

Nginx It's working ,SpringBoot Just follow the gourd and draw the gourd , still java It's comfortable to write , can debug, ha-ha .

SpringBoot Mapping static resources

public class VueWebConfig implements WebMvcConfigurer {
* Mapped static resource path
* file:./static/ Path is relative to user.dir route ,jar Package under the same level directory static
private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {"file:./static/", "classpath:/META-INF/resources/",
"classpath:/resources/", "classpath:/static/", "classpath:/public/"};
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// Add static resource cache 
CacheControl cacheControl = CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic();
public void addInterceptors(InterceptorRegistry registry) {
// Configure the resources to intercept , It is mainly used for add to cookie 
registry.addInterceptor(new VueCookieInterceptor()).addPathPatterns("/test/**");
// vue Routing forwarding uses , Also do Interface request not found 
public VueErrorController vueErrorController() {
return new VueErrorController(new DefaultErrorAttributes());

Project static resource path add cookie

public class VueCookieInterceptor implements HandlerInterceptor {
public static final String VUE_HTML_COOKIE_NAME = "x_vue_path";
public static final String VUE_HTML_COOKIE_VALUE = "/test";
* Configure the request resource path /test Add all the following cookie
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
final Cookie cookieByName = getCookieByName(request, VUE_HTML_COOKIE_NAME);
if (Objects.isNull(cookieByName)) {
final Cookie cookie = new Cookie(VUE_HTML_COOKIE_NAME, VUE_HTML_COOKIE_VALUE);
// Under the project of url You can take it with you 
return true;
public static Cookie getCookieByName(HttpServletRequest httpServletRequest, String cookieName) {
final Cookie[] cookies = httpServletRequest.getCookies();
if (Objects.isNull(cookieName) || Objects.isNull(cookies)) {
return null;
for (Cookie cookie : cookies) {
final String name = cookie.getName();
if (Objects.equals(cookieName, name)) {
return cookie;
return null;

Request error to forward resources

The wrong jump should be clearly distinguished Interface requests and static resource requests , adopt accept Can be judged .

public class VueErrorController extends AbstractErrorController {
private static final String ONLINE_SAIL = VUE_HTML_COOKIE_NAME;
private static final String ERROR_BEFORE_PATH = "javax.servlet.error.request_uri";
public VueErrorController(DefaultErrorAttributes defaultErrorAttributes) {
public String getErrorPath() {
return "/error";
public ModelAndView errorHtml(HttpServletRequest httpServletRequest, HttpServletResponse response, @CookieValue(name = ONLINE_SAIL, required = false, defaultValue = "") String cookie) {
final Object attribute = httpServletRequest.getAttribute(ERROR_BEFORE_PATH);
if (cookie.length() > 0 && Objects.nonNull(attribute)) {
String requestURI = attribute.toString();
// The access path is not to vue End of deployment path , Add path forwarding to access 
if (!requestURI.startsWith(cookie)) {
ModelAndView modelAndView = new ModelAndView();
// Static resources don't want to forward , Redirect words , It is amended as follows redirect
String viewName = "forward:" + cookie + requestURI;
return modelAndView;
ModelAndView modelAndView = new ModelAndView();
return modelAndView;
// The processing request header is accept by application/json Request , The interface request returns json data 
@RequestMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
HttpStatus status = getStatus(request);
if (status == HttpStatus.NO_CONTENT) {
return new ResponseEntity<>(status);
final Map<String, Object> errorAttributes = getErrorAttributes(request, true);
return new ResponseEntity<>(errorAttributes, status);

Home page Jump

public class IndexController {
@RequestMapping(value = {"/test", "/test"})
public String index() {
return "forward:/test/index.html";

This paper is written by Zhang Panqin's blog http://www.mflyyou.cn/ A literary creation . Reprint freely 、 quote , But you need to sign the author and indicate the source of the article .

For example, the official account of WeChat , Please add the author's official account number 2 . WeChat official account name :Mflyyou

本文为[Eternal clouds]所创,转载请带上原文链接,感谢

  1. [front end -- JavaScript] knowledge point (IV) -- memory leakage in the project (I)
  2. This mechanism in JS
  3. Vue 3.0 source code learning 1 --- rendering process of components
  4. Learning the realization of canvas and simple drawing
  5. gin里获取http请求过来的参数
  6. vue3的新特性
  7. Get the parameters from HTTP request in gin
  8. New features of vue3
  9. vue-cli 引入腾讯地图(最新 api,rocketmq原理面试
  10. Vue 学习笔记(3,免费Java高级工程师学习资源
  11. Vue 学习笔记(2,Java编程视频教程
  12. Vue cli introduces Tencent maps (the latest API, rocketmq)
  13. Vue learning notes (3, free Java senior engineer learning resources)
  14. Vue learning notes (2, Java programming video tutorial)
  15. 【Vue】—props属性
  16. 【Vue】—创建组件
  17. [Vue] - props attribute
  18. [Vue] - create component
  19. 浅谈vue响应式原理及发布订阅模式和观察者模式
  20. On Vue responsive principle, publish subscribe mode and observer mode
  21. 浅谈vue响应式原理及发布订阅模式和观察者模式
  22. On Vue responsive principle, publish subscribe mode and observer mode
  23. Xiaobai can understand it. It only takes 4 steps to solve the problem of Vue keep alive cache component
  24. Publish, subscribe and observer of design patterns
  25. Summary of common content added in ES6 + (II)
  26. No.8 Vue element admin learning (III) vuex learning and login method analysis
  27. Write a mini webpack project construction tool
  28. Shopping cart (front-end static page preparation)
  29. Introduction to the fluent platform
  30. Webpack5 cache
  31. The difference between drop-down box select option and datalist
  32. CSS review (III)
  33. Node.js学习笔记【七】
  34. Node.js learning notes [VII]
  35. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  36. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  37. 【JQuery框架,Java编程教程视频下载
  38. [jQuery framework, Java programming tutorial video download
  39. Vue Router根据后台数据加载不同的组件(思考-&gt;实现-&gt;不止于实现)
  40. Vue router loads different components according to background data (thinking - & gt; Implementation - & gt; (more than implementation)
  41. 【Vue,阿里P8大佬亲自教你
  42. 【Vue基础知识总结 5,字节跳动算法工程师面试经验
  43. [Vue, Ali P8 teaches you personally
  44. [Vue basic knowledge summary 5. Interview experience of byte beating Algorithm Engineer
  45. 【问题记录】- 谷歌浏览器 Html生成PDF
  46. [problem record] - PDF generated by Google browser HTML
  47. 【问题记录】- 谷歌浏览器 Html生成PDF
  48. [problem record] - PDF generated by Google browser HTML
  49. 【JavaScript】查漏补缺 —数组中reduce()方法
  50. [JavaScript] leak checking and defect filling - reduce() method in array
  51. 【重识 HTML (3),350道Java面试真题分享
  52. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  53. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  54. [re recognize HTML (3) and share 350 real Java interview questions
  55. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  56. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  57. 【重识 HTML ,nginx面试题阿里
  58. 【重识 HTML (4),ELK原来这么简单
  59. [re recognize HTML, nginx interview questions]
  60. [re recognize HTML (4). Elk is so simple