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

3zwjbxry  于 2023-08-04  发布在  React
关注(0)|答案(9)|浏览(108)

我在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 dev server中运行它时,一切都很好。例如,当我使用http://localhost:3003/test/时,bridge.js被加载,如果我运行http://localhost:3003/test/t/,bridge2.js被加载,这是预期的。
然而,由于web包开发服务器不是生产服务器,我使用tomcat,现在我使用eclipse web应用程序项目,我复制了我的bundle.js文件和index.html。现在的问题是,当我运行tomcat服务器时,它能够很好地识别并显示这个路径:
http://localhost:8080/test/,但当http://localhost:8080/test/t/时,我得到:
HTTP Status 404 - /test/t/
基本上说资源文件不可用。据我观察,这在编码中不是问题,因为路由在web包开发服务器中工作得很好,但是当涉及到tomcat时,react路由似乎无法处理它。我做的事有什么不对吗?是否可行?

xwmevbvl

xwmevbvl1#

首先,在使用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-reduxjavascript一无所知。
处理此问题的一种方法是将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文件中指定此选项:

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


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

puruo6ea

puruo6ea2#

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重写的其他示例。

ijnw1ujt

ijnw1ujt3#

我有同样的问题路由不工作。如果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。这为我解决了路由问题。

llew8vvj

llew8vvj4#

我的解决方案就像是JSP引擎的一个变通方法(例如Tomcat),但它用最少的代码就能很好地工作。
我创建了一个“index.jsp”与“index.html”并行(在内容根文件夹中),代码如下:

index.jsp

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

字符串
我在web.xml中配置了所有URL以重定向到此JSP

web.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加载到浏览器中,它就会负责渲染正确的组件和后续请求。

ndh0cuux

ndh0cuux5#

在我的情况下,我想要一个简单的解决方案,如创建一个客户错误页面。然而,该解决方案仍然设置了不期望的状态代码404
因此,我使用了一个小的jsp文件,它将在输出SPA的index.html之前将状态码设置为200
我希望这可以帮助其他人寻找一个简单的解决方案,而不返回状态404

web.xml

<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"%>

f87krz0w

f87krz0w6#

对于Tomcat版本8以下。您只需添加一个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>

字符串

8e2ybdfx

8e2ybdfx7#

  • 我认为对OP问题的回答还应该涉及通过默认servlet访问静态资源。*

在我的理解中,问题出现在多视图React应用程序中,其中路由器用于更改页面URL以反映应用程序的状态。这很好,但是如果你不小心重新加载页面,你会得到404,因为没有任何资源匹配更改后的URL。这也意味着这样改变的URL不能被标记为直接访问不同的应用程序视图。除非,我们从服务器端得到一点帮助。
根据如何处理对静态资源的访问,或者选择的实现(filter,servlet甚至JSP),可能有更多的解决方案,但基本思想是为React中定义的每个Routes提供主应用程序HTML文件。
假设你在应用程序中定义了两个React Routes:

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

字符串
您可以创建一个 RouterServlet 来将请求转发到/view 1或/view 2并返回到上下文根(/),假设您将应用程序Map到此处。

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>

9udxz4iz

9udxz4iz8#

虽然我不熟悉Tomcat,但最有可能发生的情况是,您的服务器正在查找/test/t/test/t/index.html文件,由于不存在,因此返回404错误。
当您使用浏览器历史记录时,您需要有一个可以处理路由的服务器。通常,这将是一个通配符(*)路由,它返回您的index.html文件(反过来,它将返回捆绑的js以及索引文件中包含的任何其他静态文件)。
一种解决方案是切换到使用哈希路由器。如果您无法在服务器上进行路由(特别是对于托管静态内容的用户而言),那么哈希路由是必要的。但是,因为你使用的是服务器,你应该能够设置路由,允许你使用浏览器路由器。
正如我之前所说的,我不熟悉Tomcat,所以我只描述一下应该是什么配置。
1.所有静态文件的请求都应定期提供。
1.所有其他对/test/*的请求(其中 * 是任何URL)都应该服务于您的index.html文件。

yptwkmov

yptwkmov9#

对于那些在嵌入式Tomcat服务器上使用springboot的人来说,解决方案相当简单。我努力了很久才来到这里,但希望这能帮助到别人。
这是基于上面的@rafael-z响应。
我们只需要利用springboot提供的错误处理-在一些Springbean中添加以下内容

@Bean
public ErrorPageRegistrar errorPageRegistrar() {
    return this::registerErrorPages;
}

private void registerErrorPages(ErrorPageRegistry registry) {
    registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/index.html"));
}

字符串

相关问题