Vue前端打包部署到sping boot中
以静态项目作为参考[前端vue-cli3+后台sping boot]
-
前端工程目录如下:
-
后台工程目录如下:
-
前后端整合:
在项目整合的过程中,直接将前端开发好后将build构建好的dist下static中的文件拷贝到spring boot的resource的static下,index.html则直接拷贝到spring boot的resource的static下。我们这样就可以愉快的启动sping 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项目了。【在复制的时候,不要进行替换或者覆盖,最好的方式,把原有的的文件进行删除之后在进行复制】