Vue-cli3.0项目部署到sping boot 方案

Vue前端打包部署到sping boot中

以静态项目作为参考[前端vue-cli3+后台sping boot]

  • 前端工程目录如下:

    vue-cli3工程目录

  • 后台工程目录如下:

    spring boot 工程目录

  • 前后端整合:

    在项目整合的过程中,直接将前端开发好后将build构建好的dist下static中的文件拷贝到spring boot的resource的static下,index.html则直接拷贝到spring boot的resource的static下。我们这样就可以愉快的启动sping boot,输入网址就可以愉快的访问啦!但是通过上面的整合后会出现两个比较大的问题。vue-cli3打包部署到spring boot 工程目录

  • 前后端整合核心问题处理:
    <p>1. 无法正常访问静态资源 。</p>
    
     > 解决该问题问题,我们必须重新指定spring boot的静态资源处理前缀,代码:
    
@Configuration
public class WebAppConfigurer extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/holmeslog/**").addResourceLocations("file:" + SystemConfig.getProperty("holmeslog.path"));
        registry.addResourceHandler("/processorlog/**").addResourceLocations("file:" + SystemConfig.getProperty("processorlog.path"));
        registry.addResourceHandler("/installtar/**").addResourceLocations("file:" + SystemConfig.getProperty("installtar.path"));
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); //重新指定spring boot的静态资源处理前缀
        super.addResourceHandlers(registry);
    }
}
  <p>2. vue router路由的路径无法正常解析 。</p>

   > 对vue的路由的路径做rewrite,交给router来处理,而不是spring boot自己处理,rewrite时可以考虑路由的路径统一增加后缀,然后在spring boot中编写过滤拦截特定后缀来做请求转发交给vue的路由处理。前端路增加fe,如
export default {
  path: '/fe/regular',
  component: () => import('@/views/empty'),
  name: 'regular',
  meta: { title: '规则配置', icon: 'guize' },
  children: [{
    path: 'find',
    name: 'regular-find',
    meta: { hidden: true, title: '发现规则', icon: 'right' },
    component: () => import('@/views/regular/find')
  }, 
  ...... 
  {
    path: 'mask-edit/:id',
    name: 'regular-mask-edit',
    meta: { title: '编辑脱敏规则', icon: 'right', hidden: true, breadcrumb: [{ name: 'regular-mask', title: '规则配置' }, { name: 'regular-mask', title: '脱敏规则' }] },
    component: () => import('@/views/regular/mask-edit.js')
  }]
}

   > 后台改变,如
Application.java

    public FilterRegistrationBean someFilterRegistration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        registration.setFilter(XssFilter());
        registration.addUrlPatterns("/*");
        registration.addInitParameter("paramName", "paramValue");
        registration.addInitParameter(XssFilter.REWRITE_TO,"/index.html");  // 重点
        registration.addInitParameter(XssFilter.REWRITE_PATTERNS, "/fe/*");  // 重点
        registration.setName("XssFilter");
        return registration;
    }

XssFilter.java

public class XssFilter implements Filter {

    //需要rewrite的目的地址
    public static final String REWRITE_TO ="rewriteUrl";
    public static final String REWRITE_PATTERNS = "rewritePatterns";
    private Set<String> urlPatterns = null;//配置url通配符
    private String rewriteTo = null;
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        rewriteTo = filterConfig.getInitParameter(REWRITE_TO);
        String exceptUrlString = filterConfig.getInitParameter(REWRITE_PATTERNS);
        if(StringUtil.isEmpty(exceptUrlString)) {
            urlPatterns = Collections.emptySet();
        }else {
            urlPatterns = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(exceptUrlString.split(";",0))));
        }
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        MHttpServletRequest xssRequest = new MHttpServletRequest((HttpServletRequest) request);
        HttpServletRequest request1 = xssRequest;
        String servletPath = request1.getServletPath();
        String context = request1.getContextPath();
        if(isMatches(urlPatterns, servletPath)) {
            request.getRequestDispatcher(context+ "/"+ rewriteTo).forward(xssRequest,response);
        } else if(servletPath.contains("main")) {//兼容处理main和main#
            request.getRequestDispatcher(context+ "/"+ rewriteTo).forward(xssRequest,response);
        }else {
            chain.doFilter(xssRequest, response);
        }

    }

    @Override
    public void destroy() {
    }

    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;
    }
}

后端拦截到带有/fe的都交给router来处理!(或者spring boot 的接口都增加标识,拦截spring boot的接口标识,非接口统一交给前端来处理)

重点:

   > 上面这是最简单的合并方式,但是如果作为工程级的项目开发,并不推荐使用手工合并,也不推荐将前端代码构建后提交到spring boot的resouce下。好的方式应该是保持前后端完全独立开发代码,项目代码互不影响,编写脚本在构建spring boot时触发前端构建并编写自动化脚本将前端webpack构建好的资源拷贝到spring boot下再进行jar的打包,最后就得到了一个完全包含前后端的spring boot项目了。【在复制的时候,不要进行替换或者覆盖,最好的方式,把原有的的文件进行删除之后在进行复制】
前端路由使用的是history模式
ps:本方案只是在静态项目场景下的选择,如果一切条件允许,强力推荐做完全的前后端分离。就算后期完全分开部署,也没有影响。
如果文档有更好的补充和好的建议,欢迎联系@博主
如有雷同,请联系@博主。

猜你喜欢

转载自blog.csdn.net/alnorthword/article/details/85690243