react routing能够处理不同的url路径,但tomcat返回404不可用的资源

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了react routing能够处理不同的url路径,但tomcat返回404不可用的资源相关的知识,希望对你有一定的参考价值。

我是reactjs的新手,我在reactjs有一个小项目来玩和学习它。我需要输入基于url路径显示的标题类型。所以以下是我的index.js处理路由:

 const history = useRouterHistory(createHistory)({
     basename: '/test'
})
class Tj extends React.Component {

render() {

    return (
        <Router history={history}>
            <Route path={"/"} component={Bridge} >
                <IndexRoute component={Home} />
                <Route path={"user"} component={T} />
                <Route path={"home"} component={Home} />
            </Route>
            <Route path={"/t/"} component={Bridge2} >
                <IndexRoute component={T} />
                <Route path={"contact"} component={Home} />
            </Route>
        </Router>
    );
}
}
render(
<Provider store={store}>
    <Tj/>
</Provider>,
window.document.getElementById('mainContainer'));

正如您所看到的,我使用test作为根目录,并根据用户的url输入决定我应该使用哪个头。这里还有Bridge2.js:

export class Bridge2 extends React.Component {
render() {

    return (
        <div>
            <div className="row">
                <Header2/>
            </div>
            <div className="row">
                {this.props.children}
            </div>
        </div>
    );
}
}

和Bridge.js:

export class Bridge extends React.Component {
render() {
  //  alert(this.props.children.type);
    var Content;

    if(this.props.children.type){
    Content=<div>
        <div className="row">
            <Header/>
        </div>
        <div className="row">
            {this.props.children}
        </div>
    </div>;
    }
    else{
        Content=<div>
            <div className="row">
                <Header/>
            </div>
            <div className="row">
                {this.props.children}
            </div>
        </div>;
    }
    return (
        Content
    );
}
}

当我在webpack开发服务器中运行它时,每件事情都可以。例如,当我使用http://localhost:3003/test/ bridge.js被加载并且如果我运行http://localhost:3003/test/t/ bridge2.js被加载,这是预期的。

但是,由于web pack dev服务器不是生产服务器,我使用tomcat,现在我使用eclipse web应用程序项目,然后我复制了我的bundle.js文件和index.html。现在的问题是,当我运行tomcat服务器时,它能够识别并显示此路径:

http://localhost:8080/test/但是当我为http://localhost:8080/test/t/我得到:

HTTP状态404 - / test / t /

这基本上说资源文件不可用。就我所观察到的而言,这不是编码中的问题,因为路由在web pack开发服务器中运行良好,但是当涉及到tomcat时,似乎反应路由无法处理它。我在做什么有什么不对吗?这样可行吗?有人可以帮忙吗?

答案

首先,使用react-router时必须注意以下差异。

当您在浏览器中输入“localhost:3003 / test /”时,它将请求服务器,然后它将收到/test/index.html,js包,css,...

之后,每当您单击内部链接(例如'localhost:3003 / test / t /')时,您的浏览器将不再请求服务器。

React-router将解析此客户端,重新呈现页面的部分,并更新浏览器的地址栏(使用html5 pushstate),而不会触发另一个服务器请求。

当您在地址栏中直接输入“localhost:3003 / test / t /”时,您的浏览器将请求服务器,而Tomcat没有/test/t/index.html左右,它返回404.这是因为Tomcat对react-redux和javascript一无所知。

处理此问题的一种方法是将404错误配置为转发到/test/index.html。这可能是默认配置webpack dev服务器的方式。

如果你在Tomcat面前有一个这样的例子,那么在apache上有很多这样的例子。搜索“html5 pushstate apache config”。

这是一个例子

httpd.conf文件

...
<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteBase /
    RewriteRule ^index.html$ - [L]
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule . /index.html [L]
 </IfModule>
...

如果您单独使用tomcat,则可以尝试在war.xml文件中的web.xml中指定它。

...
<error-page>
    <error-code>404</error-code>
    <location>/index.html</location>
</error-page>
...

请注意,这不是特定于反应路由的问题,每个使用html5 pushstate的应用都需要以某种方式处理此问题。 Javascript服务器可以更无缝地处理这个问题。

另一答案

Tomcat 8及以上版本有a simple built-in solution for this。您不需要将它置于Apache之后来处理这个问题,或者切换到哈希路由,或者破解重定向页面以返回到您自己服务器上的不同位置......

使用Tomcat Rewrite

它适用于任何具有UI路由的单页面应用程序框架,如React,Angular,ExtJS等。


简而言之:

1)将一个RewriteValve添加到/tomcat/webapps/{your-web-app-directory}/META-INF/context.xml

<?xml version="1.0" encoding="UTF-8"?>
<Context>  
  <Valve className="org.apache.catalina.valves.rewrite.RewriteValve" />
  ... your other context items
</Context>

2)创建一个名为:/tomcat/webapps/{your-web-app-directory}/WEB-INF/rewrite.config的文件,然后为要指向索引页的任何路径添加重写规则:

RewriteRule ^/user(.*)$    /index.html [L]
RewriteRule ^/home(.*)$    /index.html [L]
RewriteRule ^/contact(.*)$ /index.html [L]

这些规则告诉Tomcat将这三个命名路径的所有请求直接发送到index.html。

3)重启Tomcat

规则可以变得更加漂亮,比如将所有请求发送到index.html除了某个路径,这对/api调用非常有用,这些调用必须在index.html之外。上面的链接涵盖了如何使用Tomcat Rewrite的其他示例。

另一答案

我的解决方案就像是JSP引擎(例如Tomcat)的解决方法,但它可以用最少的代码工作。

我使用以下代码创建了一个与“index.html”(在内容根文件夹中)并行的“index.jsp”:

的index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@include file="index.html"%>

我将所有URL配置为在web.xml中重定向到此JSP

网嗯

<servlet>
    <servlet-name>index</servlet-name>
    <jsp-file>index.jsp</jsp-file>
</servlet>
<servlet-mapping>
    <servlet-name>index</servlet-name>
    <url-pattern>/*</url-pattern>
</servlet-mapping>

现在,任何请求Tomcat的URL都将在内部被重定向到index.html的index.jsp。一旦react-router在浏览器中加载,它就会负责呈现正确的组件和后续请求。

另一答案

我有同样的问题路由不工作。如果404没有重定向并加载index.html问题。我尝试了几种方法,最后找到了解决问题的解决方案。

这对Tomcat 8有用

inside ROOT folder of Tomcat make a new folder WEB-INF and create web.xml 

你可以这样做

sudo gedit /opt/tomcat/webapps/ROOT/WEB-INF/web.xml

将以下内容粘贴到web.xml中

<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>your_display_name</display-name>

    <error-page>
        <error-code>404</error-code>
        <location>/index.html</location>
    </error-page>

</web-app>

重启Tomcat。这为我解决了路由问题。希望这对我认为的人有帮助。谢谢

另一答案

虽然我不熟悉Tomcat,但最有可能发生的是您的服务器正在寻找/test/t/test/t/index.html文件,并且由于不存在,它返回404错误。

使用浏览器历史记录时,您需要具有可以处理路由的服务器。通常这将是一个通配符(*)路由,它返回你的index.html文件(反过来它将返回你的捆绑的js以及索引文件中包含的任何其他静态文件)。

一种解决方案是切换到使用哈希路由器。如果您无法在服务器上进行路由(特别是与托管静态内容的人员相关),则必须进行哈希路由。但是,由于您使用的是服务器,因此您应该能够设置允许您使用浏览器路由器的路由。

正如我之前所说,我不熟悉Tomcat,所以我将描述配置应该是什么。

  1. 应定期提供所有静态文件请求。
  2. /test/*(其中*是任何URL)的所有其他请求应该为您的index.html文件提供服务。
另一答案

我认为对OP问题的回答还应该解决通过默认servlet访问静态资源的问题。

在我的理解中,问题出现在多视图React应用程序中,其中使用路由器来改变页面URL以反映应用程序的状态。这很好,但是如果你意外重新加载页面就会得到404,因为没有任何资源与改变的URL匹配。它还意味着这些更改的URL不能被标记为对不同应用程序视图的直接访问。除非,我们从服务器端获得一些帮助。

根据如何处理对静态资源的访问,或者所选择的实现(过滤器,servlet甚至是JSP),可以有更多的解决方案,但基本思想是为React中定义的每个路由提供主应用程序HTML文件。

假设您在应用程序中定义了两个React Routes:

<Route path={"view1"} component={View1} />
<Route path={"view2"} component={View2} />

您可以创建一个RouterServlet,将请求转发到/ view1或/ view2回到上下文根(/),假设您在此处映射了应用程序。

void doGet(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException 
{
    request.getServletContext().getRequestDispatcher("/").forward(request, response);
}

您可以像这样配置它:

<servlet>
    <servlet-name>RouterServlet</servlet-name>
    <servlet-class>package.RouterServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>RouterServlet</servlet-name>
    <url-pattern>/view1/*</url-pattern>
</servlet-mapping>
<servlet-mapping>
    <servlet-name>RouterServlet</servlet-name>
    <url-pattern>/view2/*</url-pattern>
</servlet-mapping>
另一答案

在我的情况下,我想要一个简单的解决方案,如创建客户错误页面。但是,该解决方案仍设置状态代码404,这是不希望的。

所以我使用一个小的jsp文件,在输出SPA的200之前将状态代码设置为index.html

我希望这可以帮助其他人寻找一个简单的解决方案,而无需返回状态404

网嗯

<error-page>
    <error-code>404</error-code>
    <location>/spa.jsp</location>
</error-page>

spa.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%
    response.setStatus(200);
%><%@include file="./dashboard/index.html"%>
另一答案

对于低于8的Tomcat版本。您只需添加一个web.xml文件并将404路由到index.html

的webapps / [我的应用程式名称] /WEB-INF/web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
          http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
          version="2.4">

  <display-name>my-app-name</display-name>

  <error-page>
    <error-code>404</error-code>
    <location>/index.html</location>
  </error-page>

</web-app>

以上是关于react routing能够处理不同的url路径,但tomcat返回404不可用的资源的主要内容,如果未能解决你的问题,请参考以下文章

React-router history.push()已成功更改URL,但未将我的JXS内容重新呈现为具有匹配路径的正确Route内容

react-router的原理

route和router 当前与全局路由

使用 react-router-relay 访问要在查询中使用的 url 参数

vue路由router,routes,route

Flask解析(二)路由(werkzeug.routing里 Map, Rule)