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,所以我将描述配置应该是什么。
- 应定期提供所有静态文件请求。
- 对
/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内容