당신 이 모 르 는 SpringBoot 와 Vue 배치 솔 루 션
12711 단어 SpringBootVue배치 하 다.
얼마 전에 회사 의 외부 네트워크 에 배 치 된 프레젠테이션 환경 은 모두 내부 네트워크 환경 으로 옮 겨 갔 고 모든 대외 프레젠테이션 환경 은 외부 네트워크 맵 을 신청 해 야 특정한 서 비 스 를 방문 할 수 있 었 다.나 는 하나의 외부 네트워크 주소
www.a.com
로 내부 네트워크 주소http://ip:port
를 매 핑 한 다음 에 이 주소http://ip:port
에서 nginx 를 대리 로 각 그룹의 프로젝트http://ipn:portn
에 전달 했다.그 중에서 도 정적 자원 404 를 만 났 는데 주로 이 404 문 제 를 해결 했다.최근 에 또 하나의 프로젝트 를 만 들 었 습 니 다.사용자 의 체험 을 고려 하여 배치 의 복잡성 을 줄 이 고 SpringBoot 로 웹 서버 에 전단 자원 을 웹 자원 으로 매 핑 하 는 방법 을 생각 했 습 니 다.
조건 이 허용 되 거나 성능 에 대한 요구 가 높 습 니 다.전후 단 분리 배치,nginx 는 웹 서버 를 하고 백 엔 드 는 인터페이스 서비스 만 제공 하 는 것 을 추천 합 니 다.
이전에 배 치 된 프로젝트 A 의 외부 네트워크 방문 주 소 는
http://ip1:8080
이 고 외부 네트워크 가 비 친 후에 만 방문 할 수 있다http://ip/app1
.이전 프로젝트 B 의 외부 네트워크 방문 주 소 는http://ip1:8081
이 고 프로젝트 의 방문 주 소 는http://ip/app2
이다.이것 도 크 지도 작 지도 않 은 변동 이 라 고 할 수 있 지만 전환 한 후에 발생 하 는 첫 번 째 문 제 는 바로 정적 자원 의 퍼 가기 로 인해404
이다.예 를 들 어 예전 프로젝트 A 의 방문 주 소 는
http://ip1:8080
문맥 이 없 었 습 니 다.현재 A 의 방문 주 소 는
http://ip/app1
이 고 문맥 app 1 이 여기 있어 서 일부 자원 404 가 있 습 니 다.예 를 들 어 원래
http://ip1:8080
index.html 자원 을 요 청 했 는데 지금 은http://ip/app1
index.html 만 요청 할 수 있 습 니 다.
<!-- index.html -->
<!-- -->
<link href="/index.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
이전 방문index.css
주 소 는http://ip1:8080/index.css
이 었 으 나 지금 은 방문http://ip/index.css
으로 바 뀌 어 404,실제 index.css 주 소 는http://ip/app1/index.css
입 니 다.전단 사용
vue
으로 작 성 됩 니 다.html 의 정적 자원 경 로 는 잘 해결 되 고 웹 팩 포장 을 수정 하면 됩 니 다.
<!-- -->
<link href="/index.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
<!-- -->
<link href="./index.css" rel="external nofollow" rel="stylesheet">
<!-- webpack -->
<link href="<%= BASE_URL %>index.css" rel="external nofollow" rel="stylesheet">
그러나 프로젝트 중 일부 구성 요소 의 요청 은 통일 적 으로 처리 할 수 없고 코드 만 바 꿀 수 있 습 니 다.그러나 저 는 코드 를 움 직 이 고 싶 지 않 습 니 다.웹 팩 포장 은 움 직 이 고 싶 지 않 습 니 다.이러한 수 요 를 바탕 으로 해결 방법 을 생각 했 습 니 다.본문 내용
Nginx 배치 Vue 프로젝트
server {
listen 8087;
# , /app1 , /app1/ , /app1 。 ,
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/
배 치 된 프로젝트,예 를 들 어 app 의 프로젝트 자원 을/Users/zhangpanqin/staic/app
아래 에 놓 습 니 다.방문 주소http://ip/8087/app
<!DOCTYPE html>
<html lang="en">
<head>
<!-- BASE_URL vue.config.js publicPath-->
<link rel="icon" href="<%= BASE_URL %>favicon.ico" rel="external nofollow" >
<!-- , index.css -->
<link href="/index.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
</head>
</html>
브 라 우 저 에 vue 를 입력 할 수 있 는 경로/app/blog
도 페이지 에 접근 할 수 있 도록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'),
},
{
//
path: '*',
name: 'Error404',
component: () => import('@/views/Error404.vue'),
}
];
const router = new VueRouter({
// , vue mode 。
// 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;
http://localhost:8087/app/index.css
css 의 실제 주소 입 니 다.그래서/app
로 시작 하지 않 는 자원 에/app
을 더 하면 된다 고 생각 했 습 니 다.쿠키 만 할 수 있다 고 생각 했 습 니 다.x_vue_path
각 항목 의 경 로 를 기록 한 다음 에 정적 자원 은 이 경로 에서 찾 습 니 다.$cookie_x_vue_path/$uri
아래 설정 은 try 를 사 용 했 습 니 다.files 내부 리 셋 자원 은 브 라 우 저 에서 리 셋 되 지 않 습 니 다.
# gzip , epoll
server {
listen 8087;
# , /app1 , /app1/ , /app1 。 ,
location / {
try_files $uri $uri/;
}
root /Users/zhangpanqin/staic/;
# (.*) , app1 app2
location ~ /(.*)/.*/ {
index index.html /index.html;
add_header Set-Cookie "x_vue_path=/$1;path=/;";
# /Users/zhangpanqin/staic/+/$1/index.html index.html
try_files $uri $uri/ /$1/index.html @404router;
}
# , 。
location ~ (.css|js)$ {
try_files $uri $cookie_x_vue_path/$uri @404router;
}
location @404router {
return 404;
}
}
다음은 이것 은 방향 을 바 꾸 는 설정 입 니 다.
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 ,
rewrite ^($cookie_x_vue_path)/.* $uri break;
# /index.css 302 /app/index.css
rewrite (.css|js)$ $cookie_x_vue_path$uri redirect;
}
location @404router {
return 404;
}
}
이 사고방식 에 따라 모든 자원 을 전송 할 수 있다.업무 코드 를 바 꾸 지 않 고
vue-router
에base
기초 루트 를 하나 더 추가 하면 된다.SpringBoot 배치 Vue 프로젝트
Nginx
통 했 습 니 다.SpringBoot 는 그대로 바 가 지 를 그리 면 됩 니 다.자바 가 편 하 게 쓸 수 있 습 니 다.debug,하하.SpringBoot 맵 정적 자원
@Configuration
public class VueWebConfig implements WebMvcConfigurer {
/**
*
* file:./static/ user.dir ,jar 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) {
//
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 ,
@Bean
public VueErrorController vueErrorController() {
return new VueErrorController(new DefaultErrorAttributes());
}
}
프로젝트 정적 자원 경로 에 쿠키 추가
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";
/**
* /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);
// 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;
}
}
자원 전송 오류 요청잘못된 점프 에 접근 하려 면 인터페이스 요청 과 정적 자원 의 요청 을 구분 하고 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();
// vue ,
if (!requestURI.startsWith(cookie)) {
ModelAndView modelAndView = new ModelAndView();
modelAndView.setStatus(HttpStatus.OK);
// , , redirect
String 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;
}
// accept application/json , json
@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);
}
홈 페이지 이동
@Controller
public class IndexController {
@RequestMapping(value = {"/test", "/test"})
public String index() {
return "forward:/test/index.html";
}
}
본 고 는 장 클 라 이 밍 의 블 로그 www.mfly you.cn/가 창작 한다.자 유 롭 게 옮 겨 싣 고 인용 할 수 있 으 나 서명 한 작가 가 글 의 출처 를 밝 혀 야 한다.당신 이 모 르 는 SpringBoot 와 Vue 배치 솔 루 션 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 SpringBoot 와 Vue 배치 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 조회 하 시기 바 랍 니 다.앞으로 많은 응원 바 랍 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Java・SpringBoot・Thymeleaf】 에러 메세지를 구현(SpringBoot 어플리케이션 실천편 3)로그인하여 사용자 목록을 표시하는 응용 프로그램을 만들고, Spring에서의 개발에 대해 공부하겠습니다 🌟 마지막 데이터 바인딩에 계속 바인딩 실패 시 오류 메시지를 구현합니다. 마지막 기사🌟 src/main/res...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.