2 回答

TA貢獻1831條經驗 獲得超10個贊
對于任何正在尋找解決方案的人,我讓它與 Jettys 一起工作RewriteHandler。我的服務器設置現在如下所示:
server = new Server(config.getServer().getPort());
RewriteHandler rewriteHandler = new RewriteHandler();
rewriteHandler.setRewriteRequestURI(true);
rewriteHandler.setRewritePathInfo(false);
rewriteHandler.setOriginalPathAttribute("requestedPath");
RewriteRegexRule rule1 = new RewriteRegexRule();
rule1.setRegex("^((?!"+wsPath+"|\\.js|\\.css|\\.jpe?g|\\.png).)*$");
rule1.setReplacement("/index.html");
rewriteHandler.addRule(rule1);
URL webRootLocation = this.getClass().getResource("/frontend/index.html");
if (webRootLocation == null)
throw new IllegalStateException("Unable to determine Web-Root URL location");
URI webRootUri = URI.create(webRootLocation.toURI().toASCIIString().replaceFirst("/index.html$","/"));
logger.debug("Web-Root URI: {}",webRootUri);
ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
contextHandler.setContextPath("/");
contextHandler.setBaseResource(Resource.newResource(webRootUri));
contextHandler.setWelcomeFiles(new String[]{ "index.html" });
rewriteHandler.setHandler(contextHandler);
// Initialize WebSocket
ServerContainer container = WebSocketServerContainerInitializer.initialize(contextHandler);
List<Class<? extends Encoder>> encoders = new ArrayList<>();
encoders.add(MessageEncoder.class);
List<Class<? extends Decoder>> decoders = new ArrayList<>();
decoders.add(MessageDecoder.class);
ServerEndpointConfig endpointConfig = ServerEndpointConfig.Builder
.create(AppEndpoint.class, "/" + wsPath)
.encoders(encoders)
.decoders(decoders)
.configurator(new AppEndpointConfig(config, factory))
.build();
container.addEndpoint(endpointConfig);
server.setHandler(rewriteHandler);
contextHandler.addServlet(DefaultServlet.class, "/");
server.start();
server.join();
這并不理想,因為只有特定的文件結尾與正則表達式匹配,但它確實可以與 Jetty 內構建和部署的 Angular 應用程序配合使用。如果使用 RESTful API,則必須定義一些正則表達式來匹配 API 的路徑,如wsPath我的示例中的(一個簡單的字符串)。

TA貢獻1824條經驗 獲得超5個贊
在 Servlet 世界中實現此目的的唯一方法是讓錯誤頁面處理 404 狀態代碼并自行發出重定向。
這只能在特定的 Web 應用程序中完成,而不能從通用重寫處理例程中完成。
為什么?
那么,“如果請求的資源不存在,則使用index.html”是關鍵。
會發生什么。
輸入了 web 應用程序,但沒有匹配的 url-pattern,因此使用默認的 url-pattern?(of )。
"/"
默認 url 模式映射到所謂的“默認 Servlet”
默認 Servlet 負責在 Web 應用程序的基礎資源中查找匹配的資源,并將該內容作為靜態資源請求返回。
如果靜態資源不存在,并且請求是針對目錄(例如:
/js/
然后使用歡迎文件列表來查找歡迎文件。(此列表在 中配置WEB-INF/web.xml
)
<welcome-file-list>
? ? <welcome-file>index.html</welcome-file>
? ? <welcome-file>index.htm</welcome-file>
? ? <welcome-file>index.jsp</welcome-file>
</welcome-file-list>
如果靜態資源仍然不存在,則將其作為 404 響應進行處理。
同時,servlet 規范的錯誤頁面處理例程啟動。這將導致在您的WEB-INF/web.xml.
<servlet>
? <servletname>404Handler</servlet-name>
? <servlet-class>com.acme.My404Servlet</servlet-class>
</servlet>
<servlet-mapping>
? <servlet-name>404Handler</servlet-name>
? <url-pattern>/404status</url-pattern>
</servlet-mapping>
<!-- ... then later ... -->
<error-page>
? ? <error-code>404</error-code>
? ? <location>/404status</location>
</error-page>
該路徑可以是 servlet、靜態資源、jsp 等。幾乎可以是任何可以通過路徑引用的內容。
如果它是 servlet(或 jsp),您可以通過請求屬性詢問原始請求,以了解處理此錯誤的原因。
嵌入式碼頭中的一個例子是......
package jetty.errors;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.PathResource;
public class EmbeddedWelcomeErrorDemo
{
? ? public static void main(String[] args) throws Exception
? ? {
? ? ? ? Server server = new Server(8080);
? ? ? ? String baseDir = System.getProperty("user.home");
? ? ? ? if (args.length > 0)
? ? ? ? ? ? baseDir = args[0];
? ? ? ? Path basePath = Paths.get(baseDir);
? ? ? ? if (!Files.exists(basePath) || !Files.isDirectory(basePath))
? ? ? ? {
? ? ? ? ? ? throw new IOException("Not a valid directory: " + basePath);
? ? ? ? }
? ? ? ? ServletContextHandler context = new ServletContextHandler();
? ? ? ? context.setContextPath("/");
? ? ? ? context.setBaseResource(new PathResource(basePath));
? ? ? ? context.setWelcomeFiles(new String[]{
? ? ? ? ? ? "index.html"
? ? ? ? });
? ? ? ? // Add error page mapping for context
? ? ? ? context.addServlet(ErrorHandling.class, "/errorpage");
? ? ? ? ErrorPageErrorHandler errorMapper = new ErrorPageErrorHandler();
? ? ? ? errorMapper.addErrorPage(404, "/errorpage");
? ? ? ? context.setErrorHandler(errorMapper);
? ? ? ? // to handle static resources against base resource (always last)
? ? ? ? // always named "default" (per spec)
? ? ? ? ServletHolder defaultHolder = new ServletHolder("default", DefaultServlet.class);
? ? ? ? // assigned to default url-pattern of "/" (per spec)
? ? ? ? context.addServlet(defaultHolder, "/");
? ? ? ? HandlerList handlers = new HandlerList();
? ? ? ? handlers.addHandler(context);
? ? ? ? handlers.addHandler(new DefaultHandler()); // for non-context errors
? ? ? ? server.setHandler(handlers);
? ? ? ? server.start();
? ? ? ? server.join();
? ? }
? ? public static class ErrorHandling extends HttpServlet
? ? {
? ? ? ? @Override
? ? ? ? protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
? ? ? ? {
? ? ? ? ? ? if (req.getDispatcherType() != DispatcherType.ERROR)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? // we didn't get here from a error dispatch.
? ? ? ? ? ? ? ? // somebody attempted to use this servlet directly.
? ? ? ? ? ? ? ? resp.setStatus(404);
? ? ? ? ? ? ? ? return;
? ? ? ? ? ? }
? ? ? ? ? ? String requestedResource = (String)req.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
? ? ? ? ? ? log("[ErrorHandling] Requested resource was " + requestedResource);
? ? ? ? ? ? int statusCode = (int)req.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
? ? ? ? ? ? switch (statusCode)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? case 404:
? ? ? ? ? ? ? ? ? ? // let handle it by a redirect
? ? ? ? ? ? ? ? ? ? resp.sendRedirect("/");
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? ? ? default:
? ? ? ? ? ? ? ? ? ? // pass the other errors through
? ? ? ? ? ? ? ? ? ? resp.setStatus(statusCode);
? ? ? ? ? ? ? ? ? ? break;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
發生的情況的一些例子。
$ mkdir $HOME/tmp-base
$ mdkir css
$ echo "this is the index.html" > index.html
$ echo "this is my other html" > myother.html
$ echo "this is my fancy css" > css/main.css
然后使用命令行運行服務器示例到該目錄
$ java ... jetty.errors.EmbeddedWelcomeErrorDemo $HOME/tmp-base
2019-09-24 14:17:55.540:INFO::main: Logging initialized @190ms to org.eclipse.jetty.util.log.StdErrLog
2019-09-24 14:17:55.621:INFO:oejs.Server:main: jetty-9.4.20.v20190813; built: 2019-08-13T21:28:18.144Z; git: 84700530e645e812b336747464d6fbbf370c9a20; jvm 1.8.0_202-b08
2019-09-24 14:17:55.661:INFO:oejsh.ContextHandler:main: Started o.e.j.s.ServletContextHandler@7921b0a2{/,file:///home/joakim/tmp-base/,AVAILABLE}
2019-09-24 14:17:55.674:INFO:oejs.AbstractConnector:main: Started ServerConnector@7cef4e59{HTTP/1.1,[http/1.1]}{0.0.0.0:8080}
2019-09-24 14:17:55.674:INFO:oejs.Server:main: Started @325ms
然后提出一些要求...
$ curl -L -vv http://localhost:8080/
*? ?Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 200 OK
< Date: Tue, 24 Sep 2019 19:26:28 GMT
< Last-Modified: Tue, 24 Sep 2019 19:12:21 GMT
< Content-Type: text/html
< Accept-Ranges: bytes
< Content-Length: 23
< Server: Jetty(9.4.20.v20190813)
<?
this is the index.html
* Connection #0 to host localhost left intact
這是受歡迎的文件處理
$ curl -L -vv http://localhost:8080/myother.html
*? ?Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /myother.html HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 200 OK
< Date: Tue, 24 Sep 2019 19:21:10 GMT
< Last-Modified: Tue, 24 Sep 2019 19:13:46 GMT
< Content-Type: text/html
< Accept-Ranges: bytes
< Content-Length: 22
< Server: Jetty(9.4.20.v20190813)
<?
This is my other html
* Connection #0 to host localhost left intact
這是正常的靜態文件服務
$ curl -L -vv http://localhost:8080/css/main.css
*? ?Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /css/main.css HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 200 OK
< Date: Tue, 24 Sep 2019 19:22:22 GMT
< Last-Modified: Tue, 24 Sep 2019 19:22:16 GMT
< Content-Type: text/css
< Accept-Ranges: bytes
< Content-Length: 21
< Server: Jetty(9.4.20.v20190813)
<?
this is my fancy css
* Connection #0 to host localhost left intact
這是正常的靜態文件服務
如果我向不存在的資源或目錄發出一些請求......
$ curl -L -vv http://localhost:8080/css/bogus.css
*? ?Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /css/bogus.css HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 302 Found
< Date: Tue, 24 Sep 2019 19:22:46 GMT
< Location: http://localhost:8080/
< Content-Length: 0
< Server: Jetty(9.4.20.v20190813)
<?
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8080/'
* Found bundle for host localhost: 0x5647e1581a50 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 200 OK
< Date: Tue, 24 Sep 2019 19:22:46 GMT
< Last-Modified: Tue, 24 Sep 2019 19:12:21 GMT
< Content-Type: text/html
< Accept-Ranges: bytes
< Content-Length: 23
< Server: Jetty(9.4.20.v20190813)
<?
this is the index.html
* Connection #0 to host localhost left intact
這是由ErrorHandlingservlet處理的
$ curl -L -vv http://localhost:8080/this/directory/does/not/exist
*? ?Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /this/directory/does/not/exist HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 302 Found
< Date: Tue, 24 Sep 2019 19:23:02 GMT
< Location: http://localhost:8080/
< Content-Length: 0
< Server: Jetty(9.4.20.v20190813)
<?
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8080/'
* Found bundle for host localhost: 0x561eefa8b020 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 200 OK
< Date: Tue, 24 Sep 2019 19:23:02 GMT
< Last-Modified: Tue, 24 Sep 2019 19:12:21 GMT
< Content-Type: text/html
< Accept-Ranges: bytes
< Content-Length: 23
< Server: Jetty(9.4.20.v20190813)
<?
this is the index.html
* Connection #0 to host localhost left intact
這是由ErrorHandlingservlet處理的
[joakim@hyperion tmp]$ curl -L -vv http://localhost:8080/non-existant.jpeg
*? ?Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (#0)
> GET /non-existant.jpeg HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 302 Found
< Date: Tue, 24 Sep 2019 19:21:18 GMT
< Location: http://localhost:8080/
< Content-Length: 0
< Server: Jetty(9.4.20.v20190813)
<?
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'http://localhost:8080/'
* Found bundle for host localhost: 0x563f476b6a50 [can pipeline]
* Re-using existing connection! (#0) with host localhost
* Connected to localhost (::1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.58.0
> Accept: */*
>?
< HTTP/1.1 200 OK
< Date: Tue, 24 Sep 2019 19:21:18 GMT
< Last-Modified: Tue, 24 Sep 2019 19:12:21 GMT
< Content-Type: text/html
< Accept-Ranges: bytes
< Content-Length: 23
< Server: Jetty(9.4.20.v20190813)
<?
this is the index.html
* Connection #0 to host localhost left intact
添加回答
舉報