🍀 简窝 Blog
📃 文章详情

vue的history 路由模式下和Springboot后端路由冲突问题

问题:

在进行springboot+vue前后端项目的整合时,把vue项目打包编译后放入后端项目中,后端编译成jar包运行,

首页可以正常显示,但是在点击页面进行跳转或者刷新页面时,会出现404。

vue路由的两种模式

  1. 对于一个url来说,hash值定义—— #及其后面的内容就是hash值,例如/index#/detail。
  2. hash值不会包含在 HTTP 请求中,即:hash值不会带给服务器。
  3. 而普通的路由,比如/index/detail,就是 history 模式。

 hash模式:

  • 地址中永远带着#号,不美观 。
  • 若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
  • 兼容性较好。

 history模式:

  • 地址干净,美观 。
  • 兼容性和hash模式相比略差。
  • 应用部署上线时需要后端支持,解决刷新页面服务端404的问题。

vue的路由中:Hash模式不会冲突, 但是History模式会冲突. 浏览器先渲染服务端发回的页面内容, 然后前端路由

再更改页面内容, 最终按前端路由的规则显示页面内容. 流程如下:

一个新的请求发起后 --> 后端路由 -> 后端路由规则返回内容 --> 浏览器加载页面内容 --> 前端路由处理渲染 -> 按前端路由规则修改页面内容 --> 结束

页面刷新的问题

Hash模式:hash值变更不会让浏览器发请求外, 因此在刷新浏览器时,不会向服务器发起请求,只有前端的路由匹配处理来引起页面变化,除了hash的其他部分的变更都会引起浏览器发送请求,如上下文地址等

History模式:url一变化,就会向浏览器发请求,前提是刷新页面,但是vue是单页面应用,只有路由带来的组件变化,因此页面不刷新即不发请求。

发起请求后,服务器收到请求,根据自己配置的路由规则处理,如果是前端路由,则转发到 vue 页面的入口地址,比如/index,若没有对应的路由,就会返回404页面

解决办法

创建一个过滤器,根据 url 过滤请求,如果是前端 vue 的路由地址,则统一转发到/index入口地址,否则,就走正常的后端路由。

@Configuration
@Slf4j
public class UrlFilterConfig {
    @Resource
    private HistoryModeFilter historymodeFilter;
    // 前端路由
    @Value("${vue.root.exclusive}")
    private String exclusiveVueUrl;
    
    @Bean
    public FilterRegistrationBean historymodeFilterBean() {
        String[] urls= exclusiveVueUrl.split(Constants.COMMA_SEPARATOR);
        FilterRegistrationBean registration = new FilterRegistrationBean(historymodeFilter);
        registration.addUrlPatterns(urls);
        registration.setName("historymodeFilter");
        registration.setOrder(1);
        return registration;
    }

 

@Component
@Slf4j
public class HistoryModeFilter extends OncePerRequestFilter {
    private String endpoint = "/index";

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        log.info(">>Vue url filter: [{}]", request.getRequestURI());
        RequestDispatcher rd = request.getRequestDispatcher(endpoint);
        rd.forward(request, response);
    }
}

根据上述的流程,首先在浏览器的地址输入项目url,如果是 vue 路由,则都转发到/index下,后端返回单页面到浏览器,浏览器收到html后加载 ,然后就会根据vue的路由规则进行渲染处理

因为vue是单页面应用,所以只要返回index页面就好,之后vue有自己的路由规则处理,这样就解决了前后路由冲突,以及history模式下刷新的问题。

至于其他的 api 请求,都是后端的正常的处理。

 

📑 目录