あなたが知らないSprigBootとVueの展開解決策


前言
この間、会社の外部ネットワークが展開したデモンストレーション環境はすべてイントラネット環境に移行しました。すべての外部デモンストレーションの環境は外部ネットワークマッピングを申請してこそ、あるサービスにアクセスできます。私は1つの外部ネットワークアドレスwww.a.comを使用して1つのイントラネットアドレスhttp://ip:portにマッピングし、次いでこのアドレスhttp://ip:portでインテンxをプロキシとして各グループのプロジェクトhttp://ipn:portnに転送し、そのうち、いくつかの静的リソース404にも遭遇し、主にこの404問題を解決する。
最近また一つのプロジェクトを作りました。ユーザーの体験を考慮して、展開の複雑さを減らすために、ウェブサーバをSpring Bootでウェブリソースにマッピングする方法を考えました。
条件が許容されています。または性能に対する要求が高いです。推薦は前後に分離して配置されています。inxはウェブサーバをしています。バックエンドはインターフェースサービスのみを提供しています。
以前に展開されたプロジェクトAの外部ネットワークアクセスアドレスはhttp://ip1:8080で、外部ネットワークマッピング後はhttp://ip/app1にしかアクセスできませんでした。以前のプロジェクトBの外部ネットワークアクセスアドレスはhttp://ip1:8081で、プロジェクトアクセスアドレスはhttp://ip/app2です。これも大きな変動といえるが、切り替え後に遭遇する最初の問題は、静的リソース転送が404をもたらすことである。
例えば、以前のプロジェクトAのアクセスアドレスは、http://ip1:8080であり、文脈がない。
現在Aのアクセスアドレスはhttp://ip/app1であり、ここではコンテキストアプリ1があり、いくつかのリソース404が生じる。
例えば、http://ip1:8080はindex.htmlリソースを要求しましたが、今はhttp://ip/app1にindex.までお願いするしかありません。

<!-- 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にアクセスするようになったので、実際のindex.cssアドレスはhttp://ip/app1/index.cssであった。
フロントエンドはvueを使って作成しています。htmlの静的リソースパスはよく解決できます。webpackパッケージを変更すればいいです。

<!--          -->
<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">
しかし、プロジェクトの中にはいくつかのコンポーネントの要求があります。しかし、コードを使いたくないです。webpackパッケージは動きたくないです。これらの需要に基づいて一つの方法を考えて解決します。
本論文の内容
  • Ngixはvueプロジェクトを展開していますが、どうやって静的資源の損失を友好的に処理することができますか?
  • SpringBootは、ウェブサーバの機能マッピングvueプロジェクトをウェブリソースとして提供し、vueルーティング転送index.を処理する。
  • デモコードのアドレス
    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は、各プロジェクトのパスを記録し、静的リソースをこの経路で探します。
    この配置は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;
      }
    }

    この考え方によって、すべてのリソースを転送することができます。トラフィックコードを変更する必要はなく、$cookie_x_vue_path/$urivue-routerベースのルートを追加するだけです。
    Spring Boot展開Vueプロジェクトbaseが通りました。SpringBootはなぞなぞによって芦の絵瓢を描けばいいです。それともjavaの書く快適さです。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.mflyyou.cn/によって作成されます。転載・引用は自由ですが、著者と署名し、出典を明記してください。
    ここで、あなたの知らないSprigBootとVueの展開解決策についての記事を紹介します。Spring BootとVueの展開内容については、以前の文章を検索したり、下記の関連記事を見たりしてください。これからもよろしくお願いします。