更改Web根目录

微笑、不失礼 提交于 2020-04-16 16:48:38

【推荐阅读】微服务还能火多久?>>>

配置缓存

默认情况下,静态处理程序将设置缓存标头以使浏览器能够有效地缓存文件。

Vert.x的Web设置标题cache-controllast-modifieddate

cache-controlmax-age=86400默认设置为。这相当于一天。setMaxAgeSeconds如果需要,可以配置它 。

如果浏览器发送带有if-modified-since标头的GET或HEAD请求,并且该资源自该日期起未被修改,304则返回状态,告知浏览器使用其本地缓存的资源。

如果不需要处理缓存头,则可以禁用它setCachingEnabled

启用缓存处理后,Vert.x-Web将缓存内存中资源的最后修改日期,这样可以避免磁盘命中每次都检查实际的上次修改日期。

缓存中的条目具有到期时间,在此之后,将再次检查磁盘上的文件并更新缓存条目。

如果您知道您的文件永远不会在磁盘上更改,那么缓存条目将永远不会过期。这是默认值。

如果您知道在服务器运行时您的文件可能在磁盘上发生更改,那么您可以将只读文件设置为false setFilesReadOnly

要在任何时候启用可以在内存中缓存的最大条目数,您可以使用 setMaxCacheSize

要配置可以使用的缓存条目的到期时间setCacheEntryTimeout

配置索引页面

对根路径的任何请求/都将导致索引页面被提供。默认情况下,索引页面是index.html。这可以配置setIndexPage

更改Web根目录

默认情况下,将从目录提供静态资源webroot。配置此用途 setWebRoot

提供隐藏文件

默认情况下,服务器将提供隐藏文件(以文件开头.)。

如果您不想要提供隐藏文件,可以使用它进行配置setIncludeHidden

目录列表

服务器还可以执行目录列表。默认情况下,禁用目录列表。要启用它setDirectoryListing

启用目录列表时,返回的内容取决于accept标头中的内容类型。

对于text/html目录列表,可以使用用于呈现目录列表页面的模板进行配置setDirectoryTemplate

禁用磁盘上的文件缓存

默认情况下,Vert.x会将从类路径提供的文件缓存到磁盘上的文件中,该文件位于.vertx当前工作目录中调用的目录的子目录中。这在将服务部署为生产中的fatjars时非常有用,每次从类路径提供文件都很慢。

在开发过程中,这可能会导致问题,就像在服务器运行时更​​新静态内容一样,缓存文件将不会提供更新的文件。

要禁用文件缓存可以提供您vert.x选项的属性fileResolverCachingEnabledfalse。为了向后兼容,它还会将该值默认为系统属性vertx.disableFileCaching。例如,您可以在IDE中设置运行配置,以便在运行主类时进行设置。

CORS处理

跨源资源共享是一种安全机制,允许从一个域请求资源并从另一个域提供资源。

Vert.x-Web包含一个处理CorsHandlerCORS协议的处理程序。

这是一个例子:

router.route().handler(CorsHandler.create("vertx\\.io").allowedMethod(HttpMethod.GET)); router.route().handler(routingContext -> { // Your app handlers });

模板

Vert.x-Web包括动态页面生成功能,包括对几个流行模板引擎的开箱即用支持。您也可以轻松添加自己的。

模板引擎由描述TemplateEngine。为了渲染模板 render,使用了。

使用模板最简单的方法不是直接调用模板引擎而是使用模板引擎 TemplateHandler。此处理程序根据HTTP请求中的路径为您调用模板引擎。

默认情况下,模板处理程序将在名为的目录中查找模板templates。这可以配置。

处理程序将返回具有text/html默认内容类型的呈现结果。这也可以配置。

创建模板处理程序时,您将传入所需模板引擎的实例。模板引擎未嵌入到vertx-web中,因此您需要配置项目以访问它们。为每个模板引擎提供配置。

这里有些例子:

TemplateEngine engine = HandlebarsTemplateEngine.create();
TemplateHandler handler = TemplateHandler.create(engine); // This will route all GET requests starting with /dynamic/ to the template handler // E.g. /dynamic/graph.hbs will look for a template in /templates/graph.hbs router.get("/dynamic/*").handler(handler); // Route all GET requests for resource ending in .hbs to the template handler router.getWithRegex(".+\\.hbs").handler(handler);

MVEL模板引擎

要使用MVEL,您需要将以下依赖项添加到项目中: io.vertx:vertx-web-templ-mvel:3.8.0。使用以下命令创建MVEL模板引擎的实例:io.vertx.ext.web.templ.MVELTemplateEngine#create()

使用MVEL模板引擎时,.templ如果文件名中未指定扩展名,它将默认查找带扩展名的模板。

路由上下文RoutingContext在MVEL模板中可用作context变量,这意味着您可以基于上下文中的任何内容(包括请求,响应,会话或上下文数据)来呈现模板。

这里有些例子:

请求路径是@ {context.request()。path()}

会话中的变量'foo'是@ {context.session()。get('foo')}

上下文数据中的值“bar”是@ {context.get('bar')}

有关如何编写MVEL模板的信息,请参阅MVEL模板文档

玉模板引擎

要使用Jade模板引擎,您需要将以下依赖项添加到项目中: io.vertx:vertx-web-templ-jade:3.8.0。使用以下方法创建Jade模板引擎的实例:io.vertx.ext.web.templ.JadeTemplateEngine#create()

使用Jade模板引擎时,.jade如果文件名中未指定扩展名,它将默认查找带扩展名的模板。

路由上下文RoutingContext在Jade模板中可用作context变量,这意味着您可以基于上下文中的任何内容(包括请求,响应,会话或上下文数据)来呈现模板。

这里有些例子:

!五
HTML
 头
   title = context.get('foo')+ context.request()。path()
 身体

有关如何编写Jade模板的信息,请参阅Jade4j文档

把手模板引擎

要使用Handlebars,您需要将以下依赖项添加到项目中: io.vertx:vertx-web-templ-handlebars:3.8.0。使用以下方法创建Handlebars模板引擎的实例:io.vertx.ext.web.templ.HandlebarsTemplateEngine#create()

使用Handlebars模板引擎时,.hbs如果文件名中未指定扩展名,它将默认查找带扩展名的模板。

Handlebars模板无法调用对象中的任意方法,因此我们不能将路由上下文传递给模板,让模板像我们可以使用其他模板引擎一样内省它。

相反,上下文data在模板中可用。

如果要访问其他数据(如请求路径,请求参数或会话数据),则应在模板处理程序之前将其添加到处理程序中的上下文数据中。例如:

TemplateHandler handler = TemplateHandler.create(engine);

router.get("/dynamic").handler(routingContext -> { routingContext.put("request_path", routingContext.request().path()); routingContext.put("session_data", routingContext.session().data()); routingContext.next(); }); router.get("/dynamic/").handler(handler);

有关如何编写把手模板的信息,请参阅Handlebars Java端口文档

Thymeleaf模板引擎

要使用Thymeleaf,您需要为项目添加以下依赖项: io.vertx:vertx-web-templ-thymeleaf:3.8.0。使用以下方法创建Thymeleaf模板引擎的实例:io.vertx.ext.web.templ.ThymeleafTemplateEngine#create()

使用Thymeleaf模板引擎时,.html如果文件名中未指定扩展名,它将默认查找带扩展名的模板。

路由上下文RoutingContext在Thymeleaf模板中可用作context变量,这意味着您可以基于上下文中的任何内容(包括请求,响应,会话或上下文数据)来呈现模板。

这里有些例子:

[剪断]
<p th:text =“$ {context.get('foo')}”> </ p>
<p th:text =“$ {context.get('bar')}”> </ p>
<p th:text =“$ {context.normalisedPath()}”> </ p>
<p th:text =“$ {context.request()。params()。get('param1')}”> </ p>
<p th:text =“$ {context.request()。params()。get('param2')}”> </ p>
[剪断]

有关如何编写Thymeleaf模板的信息,请参阅Thymeleaf文档

Apache FreeMarker模板引擎

要使用Apache FreeMarker,您需要将以下依赖项添加到项目中: io.vertx:vertx-web-templ-freemarker:3.8.0。使用以下方法创建Apache FreeMarker模板引擎的实例:io.vertx.ext.web.templ.Engine#create()

使用Apache FreeMarker模板引擎时,.ftl如果文件名中未指定扩展名,它将默认查找带扩展名的模板。

路由上下文RoutingContext在Apache FreeMarker模板中作为context变量提供,这意味着您可以基于上下文中的任何内容(包括请求,响应,会话或上下文数据)来呈现模板。

这里有些例子:

[剪断]
<p th:text =“$ {context.foo}”> </ p>
<p th:text =“$ {context.bar}”> </ p>
<p th:text =“$ {context.normalisedPath()}”> </ p>
<p th:text =“$ {context.request()。params()。param1}”> </ p>
<p th:text =“$ {context.request()。params()。param2}”> </ p>
[剪断]

有关如何编写Apache FreeMarker模板的信息,请参阅Apache FreeMarker文档

卵石模板引擎

要使用Pebble,您需要为项目添加以下依赖项: io.vertx:vertx-web-templ-pebble:3.8.0。使用以下方法创建Pebble模板引擎的实例:io.vertx.ext.web.templ.PebbleTemplateEngine#create(vertx)

使用Pebble模板引擎时,.peb如果文件名中未指定扩展名,它将默认查找带扩展名的模板。

路由上下文RoutingContext在Pebble模板中可用作context变量,这意味着您可以基于上下文中的任何内容(包括请求,响应,会话或上下文数据)来呈现模板。

这里有些例子:

[剪断]
<p th:text =“{{context.foo}}”> </ p>
<p th:text =“{{context.bar}}”> </ p>
<p th:text =“{{context.normalisedPath()}}”> </ p>
<p th:text =“{{context.request()。params()。param1}}”> </ p>
<p th:text =“{{context.request()。params()。param2}}”> </ p>
[剪断]

有关如何编写Pebble模板的信息,请参阅Pebble文档

摇杆模板引擎

要使用Rocker,请将其io.vertx:vertx-web-templ-rocker:3.8.0作为依赖项添加到项目中。然后,您可以使用创建Rocker模板引擎实例io.vertx.ext.web.templ.rocker#create()

然后,传递给render方法的JSON上下文对象的值将作为模板参数公开。鉴于:

[剪断]
final JsonObject context = new JsonObject()
 .put(“foo”,“badger”)
 .put(“bar”,“fox”)
 .put(“context”,new JsonObject()。put(“path”,“/ foo / bar”));

engine.render(context,“somedir / TestRockerTemplate2”,render  - > {
 //(...)
});
[剪断]

然后模板可以作为以下somedir/TestRockerTemplate2.rocker.html资源文件:

@import io.vertx.core.json.JsonObject
@args(JsonObject context,String foo,String bar)
你好@foo和@bar
请求路径是@ context.getString(“path”)

禁用缓存

在开发期间,您可能希望禁用模板缓存,以便在每个请求上重新评估模板。为此,您需要设置系统属性:io.vertx.ext.web.TemplateEngine.disableCacheto true

默认情况下,它将为false。因此始终启用缓存。

错误处理程序

您可以使用模板处理程序或其他方式呈现自己的错误,但Vert.x-Web还包含一个可以为您呈现错误页面的四四方方的“漂亮”错误处理程序。

处理程序是ErrorHandler。要使用错误处理程序,只需将其设置为您想要覆盖的任何路径的失败处理程序。

请求记录器

Vert.x-Web包含一个LoggerHandler可用于记录HTTP请求的处理程序。您应该在任何可能失败的处理程序之前安装此处理程序RoutingContext

默认情况下,请求会记录到Vert.x记录器,该记录器可以配置为使用JUL日志记录,log4j或SLF4J。

LoggerFormat

提供favicon

Vert.x-Web包含FaviconHandler特别用于服务favicons 的处理程序。

可以使用文件系统的路径指定Favicons,或者默认情况下,Vert.x-Web将使用名称在类路径中查找文件favicon.ico。这意味着您将favicon捆绑在应用程序的jar中。

超时处理程序

Vert.x-Web包含一个超时处理程序,如果处理时间过长,您可以使用它来超时请求。

这是使用的实例配置的TimeoutHandler

如果请求在写入503响应之前超时,则响应将返回给客户端。

下面是一个使用超时处理程序的示例,该处理程序将/foo超过5秒后开始的所有路径请求:

router.route("/foo/").handler(TimeoutHandler.create(5000));

响应时间处理程序

此处理程序设置标头x-response-time响应标头,其中包含从接收请求到写入响应标头的时间(以毫秒为单位),例如:

x响应时间:1456ms

内容类型处理程序

ResponseContentTypeHandler可以设置Content-Type自动报头。假设我们正在构建一个RESTful Web应用程序。我们需要在所有处理程序中设置内容类型:

router.get("/api/books").produces("application/json").handler(rc -> findBooks(ar -> { if (ar.succeeded()) { rc.response().putHeader("Content-Type", "application/json").end(toJson(ar.result())); } else { rc.fail(ar.cause()); } }));

如果API表面变得非常大,则设置内容类型会变得很麻烦。要避免这种情况,请添加ResponseContentTypeHandler到相应的路由:

router.route("/api/*").handler(ResponseContentTypeHandler.create()); router.get("/api/books").produces("application/json").handler(rc -> findBooks(ar -> { if (ar.succeeded()) { rc.response().end(toJson(ar.result())); } else { rc.fail(ar.cause()); } }));

处理程序从中获取适当的内容类型getAcceptableContentType。因此,您可以轻松共享同一个处理程序以生成不同类型的数据:

router.route("/api/*").handler(ResponseContentTypeHandler.create()); router.get("/api/books").produces("text/xml").produces("application/json").handler(rc -> findBooks(ar -> { if (ar.succeeded()) { if (rc.getAcceptableContentType().equals("text/xml")) { rc.response().end(toXML(ar.result())); } else { rc.response().end(toJson(ar.result())); } } else { rc.fail(ar.cause()); } }));

SockJS

SockJS是一个客户端JavaScript库和协议,它提供了一个简单的类似WebSocket的接口,允许您连接到SockJS服务器,而不管实际的浏览器或网络是否允许真正的WebSockets。

它通过支持浏览器和服务器之间的各种不同传输,并根据浏览器和网络功能在运行时选择一个来实现这一点。

所有这些对您来说都是透明的 - 您只需使用类似WebSocket的界面即可

有关SockJS的更多信息,请访问SockJS网站

SockJS处理程序

Vert.x提供了一个开箱即用的处理程序SockJSHandler,在Vert.x-Web应用程序中使用SockJS。

您应该使用每个SockJS应用程序创建一个处理程序SockJSHandler.create。您还可以在创建实例时指定配置选项。配置选项用实例描述SockJSHandlerOptions

Router router = Router.router(vertx);

SockJSHandlerOptions options = new SockJSHandlerOptions().setHeartbeatInterval(2000); SockJSHandler sockJSHandler = SockJSHandler.create(vertx, options); router.route("/myapp/*").handler(sockJSHandler);

处理SockJS套接字

在服务器端,您在SockJS处理程序上设置了一个处理程序,每次从客户端建立SockJS连接时都会调用它:

传递给处理程序的对象是SockJSSocket。这有一个熟悉的类似套接字的接口,你可以读取和写入类似于a NetSocket或a WebSocket。它还实现了ReadStream, WriteStream因此您可以将其与其他读写流相连。

下面是一个简单的SockJS处理程序的示例,该处理程序只返回它读取的任何数据:

Router router = Router.router(vertx);

SockJSHandlerOptions options = new SockJSHandlerOptions().setHeartbeatInterval(2000); SockJSHandler sockJSHandler = SockJSHandler.create(vertx, options); sockJSHandler.socketHandler(sockJSSocket -> { // Just echo the data back sockJSSocket.handler(sockJSSocket::write); }); router.route("/myapp/*").handler(sockJSHandler);

客户端

在客户端JavaScript中,您使用SockJS客户端库进行连接。

你可以在这里找到。

有关使用SockJS JavaScript客户端的完整详细信息,请访问SockJS网站,但总结一下,您可以使用以下内容:

var sock = new SockJS('http://mydomain.com/myapp');

sock.onopen = function(){
 的console.log( '开放');
};

sock.onmessage = function(e){
 console.log('message',e.data);
};

sock.onclose = function(){
 的console.log( '关闭');
};

sock.send( '试验');

sock.close();

配置SockJS处理程序

可以使用各种选项配置处理程序SockJSHandlerOptions

insertJSESSIONID

插入JSESSIONID cookie,以便负载均衡器确保对特定SockJS会话的请求始终路由到正确的服务器。默认是true

sessionTimeout

close当一段时间没有看到接收连接的客户端时,服务器发送事件。此延迟由此设置配置。默认情况下,在close5秒内未看到接收连接时将发出事件。

heartbeatInterval

为了防止代理和负载均衡器关闭长时间运行的http请求,我们需要假装连接处于活动状态并偶尔发送心跳包。此设置控制此操作的频率。默认情况下,每25秒发送一次心跳包。

maxBytesStreaming

大多数流传输在客户端保存响应,并且不释放传递的消息使用的内存。这种运输需要偶尔进行垃圾收集。max_bytes_streaming设置在关闭之前可通过单个HTTP流请求发送的最小字节数。之后客户端需要打开新请求。将此值设置为1可以有效地禁用流式传输,并使流式传输的行为类似于轮询传输。默认值为128K。

libraryURL

不支持跨域通信的传输('eventsource'到名称之一)使用iframe技巧。一个简单的页面从SockJS服务器(使用其外部域)提供,并放置在一个不可见的iframe中。从这个iframe运行的代码不需要担心跨域问题,因为它从域本地运行到SockJS服务器。这个iframe也需要加载SockJS javascript客户端库,这个选项允许你指定它的url(如果你不确定,请指向最新的缩小的SockJS客户端版本,这是默认值)。默认值为http://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js

disabledTransports

这是您要禁用的传输列表。可能的值为WEBSOCKET,EVENT_SOURCE,HTML_FILE,JSON_P,XHR。

SockJS事件总线桥

Vert.x-Web附带一个称为事件总线桥的内置SockJS套接字处理程序,它有效地将服务器端Vert.x事件总线扩展到客户端JavaScript。

这将创建一个分布式事件总线,它不仅跨越服务器端的多个Vert.x实例,还包括在浏览器中运行的客户端JavaScript。

因此,我们可以创建一个包含许多浏览器和服务器的庞大分布式总线。只要连接服务器,浏览器就不必连接到同一台服务器。

这是通过提供一个简单的客户端JavaScript库来实现的,该库vertx-eventbus.js提供了一个非常类似于服务器端Vert.x事件总线API的API,它允许您向事件总线发送和发布消息并注册处理程序以接收消息。

此JavaScript库使用JavaScript SockJS客户端通过终止于SockJSHandler服务器端的SockJS连接来隧道传输事件总线流量。

然后在其SockJSHandler上安装一个特殊的SockJS套接字处理程序,它处理SockJS数据并将其与服务器端事件总线桥接。

要激活网桥,只需调用 bridgeSockJS处理程序即可。

Router router = Router.router(vertx);

SockJSHandler sockJSHandler = SockJSHandler.create(vertx); BridgeOptions options = new BridgeOptions(); sockJSHandler.bridge(options); router.route("/eventbus/*").handler(sockJSHandler);

在客户端JavaScript中,您使用'vertx-eventbus.js`库来创建与事件总线的连接以及发送和接收消息:

<script src="http://cdn.jsdelivr.net/sockjs/0.3.4/sockjs.min.js"></script> <script src='vertx-eventbus.js'></script> <script>  var eb = new EventBus('http://localhost:8080/eventbus'); eb.onopen = function() { // set a handler to receive a message eb.registerHandler('some-address', function(error, message) { console.log('received a message: ' + JSON.stringify(message)); }); // send a message eb.send('some-address', {name: 'tim', age: 587}); } </script>

该示例的第一件事是创建事件总线的实例

var eb = new EventBus('http://localhost:8080/eventbus');

构造函数的参数是连接到事件总线的URI。由于我们使用前缀创建桥,eventbus我们将在那里连接。

在打开连接之前,您无法对连接执行任何操作。当它打开时,onopen将调用处理程序。

该桥支持自动重新连接,具有可配置的延迟和退避选项。

var eb = new EventBus('http://localhost:8080/eventbus'); eb.enableReconnect(true); eb.onopen = function() {}; // Set up handlers here, will be called on initial connection and all reconnections eb.onreconnect = function() {}; // Optional, will only be called on reconnections // Alternatively, pass in an options object var options = { vertxbus_reconnect_attempts_max: Infinity, // Max reconnect attempts vertxbus_reconnect_delay_min: 1000, // Initial delay (in ms) before first reconnect attempt vertxbus_reconnect_delay_max: 5000, // Max delay (in ms) between reconnect attempts vertxbus_reconnect_exponent: 2, // Exponential backoff factor vertxbus_randomization_factor: 0.5 // Randomization factor between 0 and 1 }; var eb2 = new EventBus('http://localhost:8080/eventbus', options); eb2.enableReconnect(true); // Set up handlers...

您可以使用依赖项管理器检索客户端库:

  • Maven(在你的pom.xml):

<dependency>
 <groupId>io.vertx</groupId>
 <artifactId>vertx-web</artifactId> <version>3.8.0</version> <classifier>client</classifier> <type>js</type> </dependency>
  • Gradle(在您的build.gradle文件中):

compile 'io.vertx:vertx-web:3.8.0:client'

该图书馆也可用于:

请注意,API已在3.0.0和3.1.0版本之间进行了更改。请检查更改日志。以前的客户端仍然兼容,仍然可以使用,但新客户端提供更多功能,并且更接近vert.x事件总线API。

保护桥梁

如果您在没有保护它的情况下启动了上述示例中的桥接器,并尝试通过它发送消息,您会发现消息神秘地消失了。他们发生了什么?

对于大多数应用程序,您可能不希望客户端JavaScript能够向服务器端的任何处理程序或所有其他浏览器发送任何消息。

例如,您可能在事件总线上有一个服务,允许访问或删除数据。我们不希望行为不端或恶意的客户端能够删除数据库中的所有数据!

此外,我们不一定希望任何客户端能够监听任何事件总线地址。

为了解决这个问题,SockJS桥将默认拒绝通过任何消息。您可以告诉桥接器哪些消息可以通过。(对于总是允许通过的回复消息,有一个例外)。

换句话说,网桥就像一种具有默认拒绝所有策略的防火墙。

配置网桥告诉它应该通过哪些消息很容易。

您可以使用在调用bridge时传入的内容来指定要允许入站和出站流量的 匹配项BridgeOptions

每个匹配都是一个PermittedOptions对象:

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!