国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

你不知道的SpringBoot與Vue部署解決方案

瀏覽:2日期:2022-11-04 09:07:59

前言

前段時(shí)間公司外網(wǎng)部署的演示環(huán)境全部轉(zhuǎn)到內(nèi)網(wǎng)環(huán)境中去,所有對(duì)外演示的環(huán)境都需要申請(qǐng)外網(wǎng)映射才能訪問(wèn)某個(gè)服務(wù)。我用一個(gè)外網(wǎng)地址 www.a.com 映射到一個(gè)內(nèi)網(wǎng)地址 http://ip:port ,然后在這個(gè)地址 http://ip:port 用 nginx 做代理轉(zhuǎn)發(fā)到各個(gè)組的項(xiàng)目 http://ipn:portn 上去,其中也遇到一些靜態(tài)資源 404,主要是是解決這個(gè) 404 問(wèn)題。

最近又做了一個(gè)項(xiàng)目,考慮到用戶(hù)的體驗(yàn),減少部署的復(fù)雜性,我想了一個(gè)辦法用 SpringBoot 做 web 服務(wù)器映射前端資源為 web 資源 。

條件允許或者對(duì)性能要求比較高,推薦是前后端分離部署,nginx 做 web 服務(wù)器,后端只提供接口服務(wù)

以前部署的項(xiàng)目 A 外網(wǎng)訪問(wèn)地址是 http://ip1:8080 ,外網(wǎng)映射后只能訪問(wèn) http://ip/app1 ,以前項(xiàng)目 B 外網(wǎng)訪問(wèn)地址是 http://ip1:8081 ,項(xiàng)目訪問(wèn)地址是 http://ip/app2 。這也算是一個(gè)不大不小的變動(dòng),但是切換之后遇到的第一個(gè)問(wèn)題就是靜態(tài)資源轉(zhuǎn)發(fā)導(dǎo)致 404 。

比如以前項(xiàng)目 A 訪問(wèn)地址是 http://ip1:8080 它是沒(méi)有上下文的。

而現(xiàn)在 A 的訪問(wèn)地址為 http://ip/app1 ,有一個(gè)上下文 app1 在這里,導(dǎo)致有一些資源 404。

比如說(shuō):原來(lái) http://ip1:8080 請(qǐng)求到了 index.html 資源,現(xiàn)在只能 http://ip/app1 請(qǐng)求到 index.html。

<!-- index.html --><!-- 原來(lái)部署環(huán)境寫(xiě)法 --><link href='http://www.cgvv.com.cn/index.css' rel='external nofollow' rel='external nofollow' rel='external nofollow' rel='stylesheet'>

以前訪問(wèn) index.css 地址是 http://ip1:8080/index.css ,但是現(xiàn)在變成訪問(wèn)了 http://ip/index.css 導(dǎo)致 404,實(shí)際 index.css 地址為 http://ip/app1/index.css

前端使用 vue 編寫(xiě),html 中的靜態(tài)資源路徑可以很好解決,修改 webpack 打包即可。

<!-- 原來(lái)部署環(huán)境寫(xiě)法 --><link href='http://www.cgvv.com.cn/index.css' rel='external nofollow' rel='external nofollow' rel='external nofollow' rel='stylesheet'><!-- 寫(xiě)成相對(duì)路徑 --><link href='http://www.cgvv.com.cn/bcjs/index.css' rel='external nofollow' rel='stylesheet'><!-- 結(jié)合 webpack 打包時(shí)進(jìn)行路徑補(bǔ)充 --><link href='http://www.cgvv.com.cn/bcjs/<%= BASE_URL %>index.css' rel='external nofollow' rel='stylesheet'>

但是項(xiàng)目中有一些組件的請(qǐng)求沒(méi)有辦法統(tǒng)一處理,只能改代碼。但我不想動(dòng)代碼,webpack 打包都不想動(dòng),基于這些需求想了一個(gè)辦法來(lái)解決。

本文內(nèi)容

Nginx 部署 vue 項(xiàng)目,怎么能友好處理靜態(tài)資源的丟失 SpringBoot 提供 web 服務(wù)器的功能映射 vue 項(xiàng)目為 web 資源,并處理 vue 路由轉(zhuǎn)發(fā) index.html 問(wèn)題。

演示代碼地址

Nginx 部署 Vue 項(xiàng)目

server { listen 8087; # 它的作用是不重定向地址,比如瀏覽器輸入 /app1 訪問(wèn),也可以訪問(wèn)到 /app1/ ,而瀏覽器地址是不改變的 /app1 。沒(méi)辦法,強(qiáng)迫癥 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/ 放部署的項(xiàng)目,比如 app 的項(xiàng)目資源放到 /Users/zhangpanqin/staic/app 下。 訪問(wèn)地址為 http://ip/8087/app

<!DOCTYPE html><html lang='en'><head> <!-- 也可以改成類(lèi)似的地址 BASE_URL 等于 vue.config.js 配置的 publicPath--> <link rel='icon' href='http://www.cgvv.com.cn/bcjs/<%= BASE_URL %>favicon.ico' rel='external nofollow' > <!-- 部署之后,訪問(wèn)不到 index.css --> <link href='http://www.cgvv.com.cn/index.css' rel='external nofollow' rel='external nofollow' rel='external nofollow' rel='stylesheet'></head></html>

為了可以在瀏覽器輸入 vue 的路由 /app/blog 也可以訪問(wèn)頁(yè)面,需要添加 vue-router 中的 base 屬性。

import Vue from ’vue’;import VueRouter from ’vue-router’;Vue.use(VueRouter);const routes = [ { path: ’/’, name: ’Home’, component: () => import(’@/views/Home.vue’), }, { path: ’/blog’, name: ’Blog’, component: () => import(’@/views/Blog.vue’), }, { // 匹配不到路由的時(shí)候跳轉(zhuǎn)到這里 path: ’*’, name: ’Error404’, component: () => import(’@/views/Error404.vue’), }];const router = new VueRouter({ // 主要是修改這里,可以根據(jù) vue mode 環(huán)境來(lái)取值。 // 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’, routes,});export default router;

你不知道的SpringBoot與Vue部署解決方案

http://localhost:8087/app/index.css 為 css 的真實(shí)地址。所以想辦法為這些不以 /app 開(kāi)頭的資源加上 /app 就可以了,想了想只有 cookie 能做到。

x_vue_path 記錄每個(gè)項(xiàng)目的路徑,然后靜態(tài)資源去這個(gè)路徑下尋找, $cookie_x_vue_path/$uri

下面這個(gè)配置使用了 try_files 內(nèi)部重定向資源,是不會(huì)在瀏覽器端發(fā)生重定向的。

# gzip ,緩存 和 epoll 優(yōu)化的都沒(méi)寫(xiě)server { listen 8087; # 它的作用是不重定向地址,比如瀏覽器輸入 /app1 訪問(wèn),也可以訪問(wèn)到 /app1/ ,而瀏覽器地址是不改變的 /app1 。沒(méi)辦法,強(qiáng)迫癥 location / { try_files $uri $uri/; } root /Users/zhangpanqin/staic/; # (.*) 匹配是哪個(gè)項(xiàng)目,比如說(shuō) app1 app2 等 location ~ /(.*)/.*/ { index index.html /index.html; add_header Set-Cookie 'x_vue_path=/$1;path=/;'; # /Users/zhangpanqin/staic/+/$1/index.html 可以到每個(gè)項(xiàng)目下 index.html try_files $uri $uri/ /$1/index.html @404router; } # 查找靜態(tài)資源,也可以在這里添加緩存。 location ~ (.css|js)$ { try_files $uri $cookie_x_vue_path/$uri @404router; } location @404router { return 404; }}

你不知道的SpringBoot與Vue部署解決方案

下面這個(gè)是重定向的配置

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)$ { # 匹配到 /app/index.css 的資源,直接訪問(wèn) rewrite ^($cookie_x_vue_path)/.* $uri break; # 訪問(wèn)的資源 /index.css 302 臨時(shí)重定向到 /app/index.css rewrite (.css|js)$ $cookie_x_vue_path$uri redirect; } location @404router { return 404; }}

你不知道的SpringBoot與Vue部署解決方案

根據(jù)這個(gè)思路就可以把所有的資源進(jìn)行轉(zhuǎn)發(fā)了,不用改業(yè)務(wù)代碼,只需給 vue-router 加上一個(gè) base 基礎(chǔ)路由。

SpringBoot 部署 Vue 項(xiàng)目

Nginx 走通了,SpringBoot 依葫蘆畫(huà)瓢就行了,還是 java 寫(xiě)的舒服,能 debug,哈哈。

SpringBoot 映射靜態(tài)資源

@Configurationpublic class VueWebConfig implements WebMvcConfigurer { /** * 映射的靜態(tài)資源路徑 * file:./static/ 路徑是相對(duì)于 user.dir 路徑,jar 包同級(jí)目錄下的 static */ private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {'file:./static/', 'classpath:/META-INF/resources/', 'classpath:/resources/', 'classpath:/static/', 'classpath:/public/'}; @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 添加靜態(tài)資源緩存 CacheControl cacheControl = CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic(); registry.addResourceHandler('/**').addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS).setCacheControl(cacheControl); } @Override public void addInterceptors(InterceptorRegistry registry) { // 配置要攔截的資源,主要用于 添加 cookie registry.addInterceptor(new VueCookieInterceptor()).addPathPatterns('/test/**'); } // vue 路由轉(zhuǎn)發(fā)使用的,也做 接口請(qǐng)求找不到的 @Bean public VueErrorController vueErrorController() { return new VueErrorController(new DefaultErrorAttributes()); }}

項(xiàng)目靜態(tài)資源路徑添加 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'; /** * 配置請(qǐng)求資源路徑 /test 下全部加上 cookie */ @Override 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); // 項(xiàng)目下的 url 都帶能帶上 cookie.setPath('/'); cookie.setHttpOnly(true); response.addCookie(cookie); } 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; }}

請(qǐng)求出現(xiàn)錯(cuò)誤做資源的轉(zhuǎn)發(fā)

訪問(wèn)錯(cuò)誤的跳轉(zhuǎn)要分清楚 接口請(qǐng)求和靜態(tài)資源的請(qǐng)求,通過(guò) accept 可以判斷。

@RequestMapping('/error')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) { super(defaultErrorAttributes); } @Override public String getErrorPath() { return '/error'; } @RequestMapping 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)) { response.setStatus(HttpStatus.OK.value()); String requestURI = attribute.toString(); // 訪問(wèn)的路徑?jīng)]有以 vue 部署的路徑結(jié)尾,補(bǔ)充上路徑轉(zhuǎn)發(fā)去訪問(wèn) if (!requestURI.startsWith(cookie)) {ModelAndView modelAndView = new ModelAndView();modelAndView.setStatus(HttpStatus.OK);// 靜態(tài)資源不想轉(zhuǎn)發(fā),重定向的話(huà),修改為 redirectString viewName = 'forward:' + cookie + requestURI;modelAndView.setViewName(viewName);return modelAndView; } } ModelAndView modelAndView = new ModelAndView(); modelAndView.setStatus(HttpStatus.OK); modelAndView.setViewName('forward:/test/index.html'); return modelAndView; } // 處理請(qǐng)求頭為 accept 為 application/json 的請(qǐng)求,就是接口請(qǐng)求返回json 數(shù)據(jù) @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); }

首頁(yè)跳轉(zhuǎn)

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

本文由 張攀欽的博客 www.mflyyou.cn/ 創(chuàng)作。 可自由轉(zhuǎn)載、引用,但需署名作者且注明文章出處。

到此這篇關(guān)于你不知道的SpringBoot與Vue部署解決方案的文章就介紹到這了,更多相關(guān)SpringBoot與Vue部署內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 日韩中文字幕网 | 成在线人视频免费视频 | 中国高清色视频www 中国黄色网址大全 | 亚洲黄色免费在线观看 | 亚洲国产欧美一区 | 国产欧美综合一区二区 | 黄色片三级网站 | 黄视频免费在线 | 国产的一级毛片完整 | 欧美性性性性性色大片免费的 | 久久精品免看国产 | 欧美一区精品 | 亚洲美女在线观看播放 | 久草在线免费播放 | 国产手机国产手机在线 | 特级毛片全部免费播放a一级 | 中文亚洲欧美 | 中文在线视频 | 日本精品久久久久中文字幕 1 | 国产三级三级三级三级 | 伊人狼人综合 | 国产日韩久久 | 亚洲aⅴ男人的天堂在线观看 | 俄罗斯三级毛片 | 在线免费一区二区 | 精品网址 | 欧洲成人免费视频 | 欧美精品人爱a欧美精品 | 最新最好看免费毛片基地 | 国产黄色a三级三级三级 | 日韩午夜在线观看 | 亚洲人成网站观看在线播放 | 欧美另类videosbestsex高清 | 波多野结衣一区在线观看 | 天天澡天天碰天天狠伊人五月 | 日本午夜人成免费视频 | 精品国产成人在线 | 欧美日韩精品一区二区三区 | 欧美成人香蕉网在线观看 | 欧美一级淫片a免费播放口aaa | a级毛片在线看日本 |