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

IT技术 reactjs react-router
2021-04-04 16:08:05

我有一个小项目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 开发服务器不是生产服务器,我使用 tomcat,现在我使用 eclipse web 应用程序项目,并将我的 bundle.js 文件和 index.html 复制到那里。现在的问题是,当我运行 tomcat 服务器时,它能够识别并正常显示此路径:

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

HTTP 状态 404 - /test/t/

这基本上说资源文件不可用。据我观察,这在编码中不是问题,因为路由在 webpack 开发服务器中工作正常,但是当涉及到 tomcat 时,似乎react路由无法处理它。我在做什么有什么问题吗?这种方式完全可行吗?

6个回答

首先,在使用react-router.

当您localhost:3003/test/在浏览器中输入时,它会请求服务器,然后它会收到/test/index.htmljs捆绑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 开发服务器默认配置的方式。

有很多在 apache 上执行此操作的示例,如果您在我们的 Tomcat 前面有一个。搜索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,您可以尝试在web.xml,.war文件中指定

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

请注意,这不是一个react-router特定的问题,每个使用 HTML5 的应用程序都pushstate()需要以某种方式处理这个问题。不过,Javascript 服务器可以更无缝地处理这个问题。

我对 Apache 配置知之甚少,但我设法调整了这一配置以使其无缝地为我工作。最后一个 Rewrite 规则可以在子文件夹的名称前面加上,以便它返回该特定文件夹中的 index.html。谢谢详细的解释!
2021-06-02 16:08:05
非常感谢您阐明这一点,因为我完全糊涂了。也非常感谢@paul S 的大力帮助
2021-06-03 16:08:05

Tomcat 8 及更高版本对此有一个简单的内置解决方案你不需要把它放在 Apache 后面来处理这个,或者切换到散列路由,或者破解一个重定向页面来回到你自己服务器上的不同位置......

使用Tomcat重写

它适用于任何具有 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 的其他示例。

不知道为什么这不是公认的答案......它应该是。基本路径对于具有相对上下文的反应路由器来说很好,但这不是问题所在。问题是关于Tomcat的。如果其他人在 tomcat 上遇到这个问题,我不得不将我的静态文件夹复制到父 webapps 文件夹以避免可怕的“白屏死机”
2021-05-27 16:08:05
我们可以有一个重定向到 index.html 的通用签名,而不是在这里写所有的路由吗?
2021-06-07 16:08:05
@Ricky 当然,您可以这样做,^/(.*)$但是您必须为 favicon.ico 或您的服务器可能被请求的任何其他资源或任何用于获取数据的 api 调用添加排除项
2021-06-10 16:08:05
清洁溶液。但是你需要tomcat 8以上
2021-06-16 16:08:05

我有同样的问题路由不工作。如果 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 9,对于那些将react app部署到tomcat的人,请尝试此方法
2021-06-16 16:08:05

我的解决方案类似于 JSP 引擎(例如 Tomcat)的解决方法,但它使用最少的代码就可以很好地工作。

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

索引.jsp

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

我在 web.xml 中将所有 url 配置为重定向到这个 JSP

网页.xml

<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.jsp,实际上是 index.html。一旦 react-router 在浏览器中加载,它就会负责渲染正确的组件和后续请求。

这也将路由资源,并且反应应用程序将无法工作。
2021-06-19 16:08:05

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

webapps/[my-app-name]/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>