zoukankan      html  css  js  c++  java
  • Vue-cli3与springboot项目整合打包

    一、需求

      
        使用前后端分离编写了个小程序,前端使用的是vue-cli3创建的项目,后端使用的是springboot创建的项目,部署的时候一起打包部署,本文对一些细节部分进行了说明。
     

    二、Vue项目具体配置

     
        (1) vue正常开发使用代理与后台交互,在打包时候,有些配置需要和后端保持一致
     
        (2)配置生产时环境变量: (file:  .env.production),
      .env.production是我自己配置的生产时环境变量,可以自己创建(具体可以参考:vue-cli3环境配置),也可以忽略这个,直接填写,例如,在axios的配置中,可以直接配置成Axios.defaults.baseURL = '/app_name/v1'
     
    NODE_ENV = 'production'
    VUE_APP_BASE_URL= /app_name/v1
    VUE_APP_CONTEXT=/pre-lcas
    VUE_APP_ASSETS=static 
    1. VUE_APP_BASE_URL
              用于给所有http请求指定起始路径,前端项目中使用axios组件支持http请求,在axios的配置文件中指定 Axios.defaults.baseURL = process.env.VUE_APP_BASE_URL , 这样原本通过代理与后台进行的请求,都会加上`/app_name/v1`,
                例如: 在前端代码中使用的是: axios.get('/reqUrl/abc')......  向后台发起请求,根据上面配置后,打包后的工程请求路径会变成 {http://xxx:xx/app_name/v1/reqUrl/abc} 可以通过这个配置,匹配前端请求。
     
    1. VUE_APP_CONTEXT和VUE_APP_ASSETS
            用于设置打包后的成果物相关信息,在配置文件vue.config.js中使用,配置方式如下:
    module.exports = {
      // 设置路径
      publicPath: process.env.VUE_APP_CONTEXT,
      assetsDir: process.env.VUE_APP_ASSETS,
    ......
    }
    publicPath和assetsDir的作用可以参考官网,如果assetsDir不配置,默认会把index.html文件和css等目录都放到static目录下,这样复制springboot项目下会出现无法访问静态资源的问题,尝试了几种方法,还是将assetsDir配置成static比较好。打包后的资源目录结构如下:
    dist
    --static
    ----css
    ----fonts
    ----img
    ----js
    --favicon.ico
    --index.html
    复制的时候,将static文件夹复制到springboot的/src/main/resource下,将favicon.ico和index.html也复制到static目录下。如果springboot是多module工程,静态文件放到启动文件所在模块下的resource目录中。复制后的springboot目录如下:
    /src
    --main
    --|--java
    --|--|--com.xx.xx.WebApplication
    --|--resource
    --|--|--static
    --|--|--|--css
    --|--|--|--fonts
    --|--|--|--img
    --|--|--|--js
    --|--|--|--favicon.ico
    --|--|--|--index.html
    --|--|--application.properties

    三、springboot项目配置

     
    静态资源复制到springboot后,还是会出现无法访问资源的问题,需要设置资源访问规则。
     
    具体代码是:
     
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    @Configuration
    public class WebConfig implements WebMvcConfigurer {
        @Override
        public void addResourceHandlers(ResourceHandlerRegistry registry) {
            registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
            WebMvcConfigurer.super.addResourceHandlers(registry);
        }
      /**
       * 路由过滤,如果路径中包含‘home’关键词(前端所有路由都包含‘home’)
       * @return
       */
      @Bean
      public FilterRegistrationBean filterRegistration() {
       FilterRegistrationBean<RewriteFilter> registration = new FilterRegistrationBean<>();
       //注册rewrite过滤器
       registration.setFilter(new RewriteFilter());
       registration.addUrlPatterns("/*");
       registration.addInitParameter(RewriteFilter.REWRITE_TO,"/index.html");
       registration.addInitParameter(RewriteFilter.REWRITE_PATTERNS, "/home/*");
       registration.setName("rewriteFilter");
       registration.setOrder(1);
       return registration;
      }
    }

     RewriteFilter.java代码

    import org.springframework.util.StringUtils;
    
    import javax.servlet.*;
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.regex.Pattern;
    
    /**
     * 过滤后端请求,不属于后端的请求,交由前端路由处理
     * @author:   2019/11/1 9:50
     * @since: 0.0.1-SNAPSHOT
     * @modified By:
     */
    public class RewriteFilter implements Filter {
        /**
         * 需要rewrite到的目的地址
         */
        public static final String REWRITE_TO = "rewriteUrl";
    
        /**
         * 拦截的url,url通配符之前用英文分号隔开
         */
        public static final String REWRITE_PATTERNS = "urlPatterns";
    
        /** 配置url通配符 */
        private Set<String> urlPatterns = null;
    
        private String rewriteTo = null;
        @Override
        public void init(FilterConfig cfg) throws ServletException {
            //初始化拦截配置
            rewriteTo = cfg.getInitParameter(REWRITE_TO);
            String exceptUrlString = cfg.getInitParameter(REWRITE_PATTERNS);
            if (!StringUtils.isEmpty(exceptUrlString)) {
                urlPatterns = Collections.unmodifiableSet(
                        new HashSet<>(Arrays.asList(exceptUrlString.split(";", 0))));
            } else {
                urlPatterns = Collections.emptySet();
            }
        }
    
        @Override
        public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws IOException, ServletException {
            HttpServletRequest request = (HttpServletRequest) req;
            String servletPath = request.getServletPath();
            //匹配到后端路径标识,放行,否则,交给前端路由
            if (isMatches(urlPatterns, servletPath)) {
                req.getRequestDispatcher(rewriteTo).forward(req, resp);
            }else{
                chain.doFilter(req, resp);
            }
        }
    
        @Override
        public void destroy() {
    
        }
    
        /**
         * 匹配返回true,不匹配返回false
         * @param patterns 正则表达式或通配符
         * @param url 请求的url
         * @return
         */
        private boolean isMatches(Set<String> patterns, String url) {
            if(null == patterns){
                return false;
            }
            for (String str : patterns) {
                if (str.endsWith("/*")) {
                    String name = str.substring(0, str.length() - 2);
                    if (url.contains(name)) {
                        return true;
                    }
                } else {
                    Pattern pattern = Pattern.compile(str);
                    if (pattern.matcher(url).matches()) {
                        return true;
                    }
                }
            }
            return false;
        }
    }
    RewriteFilter.java

    四、说明

    有的文章在前后端分离后再整合打包这个问题上,都说明了两个问题,
    一个是要保证整合后静态资源可以被访问到,这个问题需要确保打包时的路径,因为如果打包失误,会在加载index.html时候找不到css/js等资源;
    另一个是要保证请求路径的分离,用户看到地址栏的是vue-router中的指定路径,页面渲染获取数据使用的是axios请求路径,后台开放的是服务路径,一定要确保axios路径与后台开放的服务路径匹配上。
     
    有的文章中提到,需要后端对router中的路径进行处理,我测试的过程中,并没有出现异常,把访问不到的路径交给前端处理就行了,前端会统一处理404异常,跳转到缺省的404错误页面。
     
    2019年11月20日 19:49:04修改:
    补充了后端对前端路由的处理,前面有相关代码。 
    如果后端不对前端路由进行处理,也就是说明把前端路由交个前端进行处理,正常访问不会出现问题,如果用户刷新浏览器,会出现404异常,因为后端代码无法处理前端路由请求。

    参考文章:

    vue-cli3.0配置开发环境,测试环境,线上环境(https://blog.csdn.net/qq_37055675/article/details/85047451
     
    springboot+vue的前后端分离与合并方案( https://my.oschina.net/u/1760791/blog/1577662
     
     
     
  • 相关阅读:
    postfix 邮件中继配置
    shell脚本网络流量实时查看
    zabbix配置邮件报警(第四篇)
    pptp服务故障
    Centos6.7 ELK日志系统部署
    rrdtool 实践
    Centos6.7安装Cacti教程
    Nagios事件机制实践
    Nrpe 插件安装教程
    如何查找一个命令由哪个rpm安装&&rpm 的相关查询方法
  • 原文地址:https://www.cnblogs.com/donfaquir/p/11776522.html
Copyright © 2011-2022 走看看