1.4 jfinal-undertow 高级用法
一、基础配置
1、启用配置文件
在 src/main/resources 目录下面创建 undertow.txt 文件,该文件会被 jfinal undertow 自动加载并对 jfinal undertow 进行配置。
如果不想使用 "undertow.txt" 这个文件名,还可以通过 UndertowServer.create(AppConfig.class, "other.txt") 方法的第二个参数来指定自己喜欢的文件名。
配置文件创建好以后,就可以按照下面的文档来配置相应的功能了。
2、常用配置
# true 值支持热加载 undertow.devMode=true undertow.port=80 undertow.host=0.0.0.0 # 绝大部分情况不建议配置 context path undertow.contextPath=/abc
开发时配置成 true 支持热加载,注意该 devMode 与 jfinal 项目中的 devMode 没有任何关系,注意区分。
重要:老版本的 undertow.host 配置的默认值为 localhost,Linux 操作系统下的安全设置可能无法在外网访问 localhost 下部署的项目,修改配置 undertow.host=0.0.0.0 即可。如果使用了 nginx 做了代理,可保持 localhost 配置。
3、web 资源加载路径配置
jfinal undertow 可以十分方便地从文件系统的目录以及 class path 或 jar 包中加载 web 静态资源,以下是配置示例:
undertow.resourcePath = src/main/webapp, classpath:static
如上所示 "src/main/webapp" 表示从项目根目录下的 "src/main/webapp" 下去加载 web 静态资源。 "classpath:static" 表示从 class path 以及 jar 包中的 static 路径下去加载 web 静态资源。
注意:"classpath:static" 这种配置是 jfinal undertow 1.5 才添加的功能。
undertow.resourcePath 配置的另一个重点是,以 "classpath:" 为前缀的配置需要自行注意路径是否存在,尽可能只配置存在的路径。而不以 "classpath:" 打头的配置可以将开发与部署时的路径一起配置进来(逗号分隔开),jfinal undertow 会在运行时检测路径是否存在,存在才真正让其生效,从而很方便一次配置同时适用于开发、生产两种环境。
重要:PathKit.getWebRootPath() 将指向 undertow.resourcePath 配置中的第一个有效目录,而 configEngine(Engine engine) 方法中的 engine 对象已被默认配置了 engine.setBaseTemplatePath(PathKit.getWebRootPath())。所以该配置与 engine 的 baseTemplatePath 有关联。
4、性能配置
# io 线程数与 worker 线程数 # undertow.ioThreads= # undertow.workerThreads=
默认配置已充分考虑常用场景,如果没有压测数据作为指导,建议使用默认配置,不要添加这两项配置。
ioThreads 为 NIO 处理 io 请求的线程数量,在生产环境下建议的配置范围是 cpu 核心数的一倍到两倍。建议根据压测结果进行调整。
workerThreads 是处理请求的线程数量,在生产环境下可以使用默认配置,或者根据压测结果进行配置。在压测数据几乎最好的情况下尽可能选择更小的 workThreads 值。因为当性能达到某个高度时再增加 workThreads 值并不会带来性能提升,但会增加系统的资源消耗。
5、开启 gzip 压缩
# gzip 压缩开关 undertow.gzip.enable=true # 配置压缩级别,默认值 -1。 可配置 1 到 9。 1 拥有最快压缩速度,9 拥有最高压缩率 undertow.gzip.level=-1 # 触发压缩的最小内容长度 undertow.gzip.minLength=1024
开启 gzip 压缩可以降低网络流量,提升访问速度
6、配置 session
# session 过期时间,注意单位是秒 undertow.session.timeout=1800 # 支持 session 热加载,避免依赖于 session 的登录型项目反复登录,默认值为 true。仅用于 devMode,生产环境无影响 undertow.session.hotSwap=true
7、配置 https
# 是否开启 ssl undertow.ssl.enable=false # ssl 监听端口号,部署环境设置为 443 undertow.ssl.port=443 # 密钥库类型,建议使用 PKCS12 undertow.ssl.keyStoreType=PKCS12 # 密钥库文件 undertow.ssl.keyStore=demo.pfx # 密钥库密码 undertow.ssl.keyStorePassword=123456 # 别名配置,一般不使用 undertow.ssl.keyAlias=demo
SSL 证书的获取见后面的第二小节
8、配置 http2
# ssl 开启时,是否开启 http2。检测该配置是否生效在 chrome 地址栏中输入: chrome://net-internals/#http2 undertow.http2.enable=true
开启 http2 可以大大加快访问速度,不必担心 https 比 http 慢这个事
9、配置 http 重定向到 https
# ssl 开启时,http 请求是否重定向到 https undertow.http.toHttps=false # ssl 开启时,http 请求跳转到 https 使用的状态码,默认值 302 undertow.http.toHttpsStatusCode=302
10、配置关闭 http
# ssl 开启时,是否关闭 http undertow.http.disable=false
在启用 https 后,可以配置关闭 http,这样就只能访问 https 了。该配置项比较适合于小程序服务端。
对于一般的 web 项目不建议配置此项,而是配置 undertow.http.toHttps=true 将 http 重定向到 https
11、自由配置 Undertow
以上配置方式由 jfinal undertow 做了直接的支持,如果上面的配置仍然不能满足需求,还可以通过下面的方式自由配置 undertow:
UndertowServer.create(YourJFinalConfig.class) .onStart( builder -> { builder.setServerOption(UndertowOptions.参数名, 参数值); }) .start();
如上所示,通过在 onStart 方法中使用 builder.setServerOption(...) 可以对 underow 进行更加深入的配置,还可以调用 builder 中的其它 API 进行其它类型的配置。上述的 UndertowOptions 中定义了很多 undertow 的配置名,查看其中的注释文档可以知道还有很多有用的配置
12、添加 Filter、WebSocket、Servlet、Listener
特别注意,Undertow 是为嵌入而生的 Web Server,web.xml 已被抛弃,所以无法通过 web.xml 配置 web 组件。
为此 jfinal undertow 提供了 UndertowServer.configWeb(...) 可以很方便添加 Filter、WebSocket、Servlet、Listener 这些标准的 Java Web 组件:
UndertowServer.create(AppConfig.class) .configWeb( builder -> { // 配置 Filter builder.addFilter("myFilter", "com.abc.MyFilter"); builder.addFilterUrlMapping("myFilter", "/*"); builder.addFilterInitParam("myFilter", "key", "value"); // 配置 Servlet builder.addServlet("myServlet", "com.abc.MyServlet"); builder.addServletMapping("myServlet", "*.do"); builder.addServletInitParam("myServlet", "key", "value"); // 配置 Listener builder.addListener("com.abc.MyListener"); // 配置 WebSocket,MyWebSocket 需使用 ServerEndpoint 注解 builder.addWebSocketEndpoint("com.abc.MyWebSocket"); }) .start();
注意,JFinalFilter 会接管所有请求,所以上面代码中 addServletMapping(...) 映射的 servlet 默认是无法被请求到的,需要在 configHandler(Handlers me) 中配置 UrlSkipHandler 让 jfinal 跳过这些 serlvet 的 url
以上代码中的 MyWebSocket 需要使用 ServerEndpoint 注解标识其为一个 WebSocket 组件,例如:
@ServerEndpoint("/myapp.ws") public class MyWebSocket { @OnMessage public void message(String message, Session session) { for (Session s : session.getOpenSessions()) { s.getAsyncRemote().sendText(message); } } }
与上述 MyWebSocket 配合使用的例子 html 在这里可以下载:传送门。社区同学分享的完整 websocket 代码在这里:https://jfinal.com/share/2004
要修改一下该 html 中的 url 为: "ws://localhost:80/myapp.ws",端口号适当调整。
注意:由于 JFinalFilter 会接管所有不带 "." 字符的 URL 请求所以 @ServerEndpoint 注解中的 URL 参数值建议以 ".ws" 结尾,否则请求会响应 404 找不到资源,例如:
@ServerEndpoint("/myapp.ws") public class MyWebSocketEndpoint { ...... }
当然,ServerEndpoint 中的 URL 不使用 ".ws" 结尾也是可以的,只需要参考 jfinal 的 UrlSkipHandler 做一个 Handler 跳过属于 WebSocket 的 URL 即可
最后,websocket 支持需要添加一个依赖,要添加的依赖项请看前面的文档:https://www.xnip.cn/shouce/938/63693.html
二、SSL 证书
1、申请 SSL 证书
建议从阿里云或者腾迅云获取 SSL 证书,有免费版和收费版,阿里云 SSL 证书获取:SSL 证书获取传送门
注意:在申请免费版 SSL 证书的过程中,绑定域名一般输入主机名为 www 的域名,例如: www.jfinal.com
2、下载合适的证书类型
SSL 证书申请下来以后,可以到控制台下载证书,如下图所示:
点击下载链接以后,在右侧下载 tomcat 类型的 SSL 证书
下载的证书里头,有一个 xxx.pfx 文件,该文件就是证书文件。此外还有一个 pfx-password.txt 文件,此文件里面放的是证书密码,将 xxx.pfx 放入项目的 src/main/resources 目录,在 undertow.txt 配置文件中添加如下几行配置:
# 是否开启 ssl undertow.ssl.enable=true # ssl 监听端口号,部署环境设置为 443 undertow.ssl.port=443 # 密钥库类型,一般是 PKCS12 与 JKS,注意根据实际类型调整 undertow.ssl.keyStoreType=PKCS12 # 密钥库文件 undertow.ssl.keyStore=demo.pfx # 密钥库密码 undertow.ssl.keyStorePassword=123456
其中的 "demo.pfx" 即为前面下载的证书文件的文件名,"123456" 即为证书密码,这两个配置根据你下载到的实际内容进行修改。"PKCS12" 这个配置是证书类型,阿里云下载的 tomcat 型证书为 PKCS12,腾迅云可能是 "JKS"
3、启动项目
启动项目,通过 "https://申请证书时绑定的域名" 即可访问
三、Https 双向认证
如果你的 jfinal undertow 项目需要对客户端进行 ssl 认证,需要使用如下方式进行配置:
UndertowServer.create(YourJFinalConfig.class) .onStart( builder -> { builder.setSocketOption(Options.SSL_CLIENT_AUTH_MODE, SslClientAuthMode.REQUESTED); }) .start();
该方法来自于社区用户的分享:https://jfinal.com/feedback/7758