# 1.4 Advanced Usage of jfinal-undertow
# I. Basic Configuration
# 1. Enable Configuration File
Create an undertow.txt
file in the src/main/resources
directory. This file will be automatically loaded by jfinal undertow and configure it.
If you prefer not to use the filename "undertow.txt", you can specify your desired filename by passing it as the second parameter of the UndertowServer.create(AppConfig.class, "other.txt")
method.
Once the configuration file is created, you can refer to the following documentation to set up the respective functionalities.
# 2. Common Configurations
# 'true' enables hot reloading
undertow.devMode=true
undertow.port=80
undertow.host=0.0.0.0
# In most cases, it's not recommended to set the context path
undertow.contextPath=/abc
2
3
4
5
6
7
Set to 'true' during development to enable hot reloading. Note that this devMode
is unrelated to the devMode
in the jfinal project. Please differentiate between them.
Important: The default value for the older version of undertow.host
is localhost
. Due to security settings on Linux, projects deployed under localhost may not be accessible from the public internet. Adjust the setting to undertow.host=0.0.0.0
. If you're using nginx as a proxy, you can keep the localhost
setting.
# 3. Web Resource Load Path Configuration
jfinal undertow can easily load web static resources from the file system directory, class path, or jar packages. Here's a configuration example:
undertow.resourcePath = src/main/webapp, classpath:static
As shown above, "src/main/webapp" indicates loading web static resources from the "src/main/webapp" directory in the project root. "classpath:static" signifies loading web static resources from the static path in the class path or jar packages.
Note: The configuration "classpath:static" was added in jfinal undertow 1.5.
Another key point about undertow.resourcePath
is that configurations prefixed with "classpath:" require manual validation of the existence of the path. It's preferable to only specify existing paths. Configurations without the "classpath:" prefix can have both the development and deployment paths configured (separated by commas). jfinal undertow will check the existence of paths at runtime and only activate them if they exist. This is convenient for a one-time configuration suitable for both development and production environments.
Important: PathKit.getWebRootPath()
will point to the first valid directory in the undertow.resourcePath
configuration. The engine
object in the configEngine(Engine engine)
method has already been set by default to engine.setBaseTemplatePath(PathKit.getWebRootPath())
. So, this configuration is related to the engine's baseTemplatePath
.
# 4. Performance Configuration
# Number of io threads and worker threads
# undertow.ioThreads=
# undertow.workerThreads=
2
3
The default configuration has been optimized for common use cases. Without performance test data as guidance, it's recommended to stick to the default settings and avoid adding these configurations.
ioThreads
represents the number of NIO threads handling io requests. In a production environment, it's suggested to set this between one to two times the number of CPU cores. Adjustments should be based on performance test results.
workerThreads
denotes the number of threads processing requests. In production, the default setting can be used, or adjustments can be made based on performance tests. When performance reaches a certain level, increasing the value of workThreads
won't lead to performance improvements but will increase system resource consumption.
# 5. Enable gzip Compression
# gzip compression switch
undertow.gzip.enable=true
# Set compression level, default is -1. Can be set between 1 and 9. 1 has the fastest compression speed, 9 has the highest compression rate.
undertow.gzip.level=-1
# Minimum content length to trigger compression
undertow.gzip.minLength=1024
2
3
4
5
6
Enabling gzip compression can reduce network traffic and improve access speed.
# 6. Session Configuration
# Session expiration time, note the unit is in seconds.
undertow.session.timeout=1800
# Support session hot reloading to avoid repeated logins for projects dependent on sessions. Default is true. Only for devMode, no impact in production.
undertow.session.hotSwap=true
2
3
4
# 7. HTTPS Configuration
# Whether to enable ssl
undertow.ssl.enable=false
# ssl listening port, set to 443 in a production environment
undertow.ssl.port=443
# Keystore type, recommended to use PKCS12
undertow.ssl.keyStoreType=PKCS12
# Keystore file
undertow.ssl.keyStore=demo.pfx
# Keystore password
undertow.ssl.keyStorePassword=123456
# Alias configuration, generally not used
undertow.ssl.keyAlias=demo
2
3
4
5
6
7
8
9
10
11
12
Instructions on obtaining an SSL certificate can be found in the following subsection.
# 8. HTTP2 Configuration
# Whether to enable http2 when ssl is on. To check if this configuration is active, enter in the Chrome address bar: chrome://net-internals/#http2
undertow.http2.enable=true
2
Enabling http2 can significantly speed up access. You don't need to worry about https being slower than http.
# 9. Redirecting HTTP to HTTPS
# When ssl is enabled, should http requests redirect to https?
undertow.http.toHttps=false
# When ssl is enabled, the status code used for redirecting http requests to https. Default value is 302.
undertow.http.toHttpsStatusCode=302
2
3
4
# 10. Disable HTTP
# Whether to disable http when ssl is on
undertow.http.disable=false
2
After enabling https, you can configure to disable http, so only https can be accessed. This configuration is suitable for mini-program servers.
For general web projects, it's not recommended to use this configuration. Instead, set undertow.http.toHttps=true
to redirect http to https.
# 11. Freely Configure Undertow
The above configurations are directly supported by jfinal undertow. If these configurations don't meet your requirements, you can freely configure undertow as follows:
UndertowServer.create(YourJFinalConfig.class)
.onStart( builder -> {
builder.setServerOption(UndertowOptions.PARAMETER_NAME, PARAMETER_VALUE);
})
.start();
2
3
4
5
As shown above, using the onStart
method and calling builder.setServerOption(...)
allows for deeper configuration of undertow. You can also call other APIs in the builder for different types of configurations. UndertowOptions
defines many undertow configuration names. Check its documentation comments to find many useful configurations.
# 12. Add Filter, WebSocket, Servlet, Listener
It's crucial to note that Undertow is a web server designed for embedding, so the web.xml
has been deprecated,
meaning you can't configure web components through web.xml
.
To address this, jfinal undertow provides UndertowServer.configWeb(...)
which allows you to easily add standard Java Web components such as Filter, WebSocket, Servlet, and Listener:
UndertowServer.create(AppConfig.class)
.configWeb( builder -> {
// Configure Filter
builder.addFilter("myFilter", "com.abc.MyFilter");
builder.addFilterUrlMapping("myFilter", "/*");
builder.addFilterInitParam("myFilter", "key", "value");
// Configure Servlet
builder.addServlet("myServlet", "com.abc.MyServlet");
builder.addServletMapping("myServlet", "*.do");
builder.addServletInitParam("myServlet", "key", "value");
// Configure Listener
builder.addListener("com.abc.MyListener");
// Configure WebSocket. MyWebSocket should use the ServerEndpoint annotation
builder.addWebSocketEndpoint("com.abc.MyWebSocket");
})
.start();
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Note: The JFinalFilter
will take over all requests. Thus, servlets mapped in addServletMapping(...)
in the above code by default cannot be accessed. You need to configure the UrlSkipHandler
in the configHandler(Handlers me)
to let jfinal skip these servlet URLs.
The MyWebSocket
in the above code should be annotated with ServerEndpoint
to indicate that it's a WebSocket component, like:
@ServerEndpoint("/myapp.ws")
public class MyWebSocket {
@OnMessage
public void message(String message, Session session) {
for (Session s : session.getOpenSessions()) {
s.getAsyncRemote().sendText(message);
}
}
}
2
3
4
5
6
7
8
9
An example HTML that works with the above MyWebSocket
can be downloaded from the link provided (not accessible in this context). Community members have also shared complete WebSocket code here (opens new window).
You need to adjust the URL in the HTML to: "ws://localhost:80/myapp.ws", changing the port number as appropriate.
Note: Since JFinalFilter
takes over all URL requests that don't have a "." character, it's suggested that the URL parameter value in the @ServerEndpoint
annotation should end with ".ws". Otherwise, you'll receive a 404 error, indicating the resource is not found, like:
@ServerEndpoint("/myapp.ws")
public class MyWebSocketEndpoint {
......
}
2
3
4
Alternatively, if the URL in the ServerEndpoint
doesn't end with ".ws", you can refer to jfinal's UrlSkipHandler
and implement a Handler
to skip WebSocket URLs.
Lastly, WebSocket support requires adding a dependency. The dependencies to be added can be found in the earlier documentation: link (opens new window).
# II. SSL Certificates
# 1. Apply for an SSL Certificate
It's recommended to obtain SSL certificates from platforms like Alibaba Cloud or Tencent Cloud. Both free and paid versions are available. For obtaining an SSL certificate from Alibaba Cloud, refer to the provided link (not accessible in this context).
Note: When applying for a free SSL certificate, the bound domain generally uses a hostname like www, e.g., www.jfinal.com.
# 2. Download the Appropriate Certificate Type
Once the SSL certificate has been approved, you can download it from the control panel as shown in the provided screenshot (not accessible in this context).
After clicking the download link, download the Tomcat type of SSL certificate as shown in the second screenshot.
Within the downloaded certificate, there's a file named xxx.pfx
, which is the certificate file. Additionally, there's a pfx-password.txt
file containing the certificate password. Place the xxx.pfx
file in the project's src/main/resources
directory and add the following lines to the undertow.txt
configuration file:
# Enable ssl
undertow.ssl.enable=true
# ssl listening port, set to 443 in production
undertow.ssl.port=443
# Keystore type, typically either PKCS12 or JKS. Adjust based on actual type.
undertow.ssl.keyStoreType=PKCS12
# Keystore file
undertow.ssl.keyStore=demo.pfx
# Keystore password
undertow.ssl.keyStorePassword=123456
2
3
4
5
6
7
8
9
10
The "demo.pfx" in the configuration is the filename of the previously downloaded certificate, and "123456" is the certificate password. Adjust these settings based on the actual contents of your download. "PKCS12" is the certificate type; Alibaba Cloud's Tomcat type certificate uses PKCS12, while Tencent Cloud might use "JKS".
# 3. Launch the Project
Start the project and access it via the domain bound when applying for the certificate using "https".
# III. Two-Way SSL Authentication
If your jfinal undertow project needs to authenticate clients using SSL, configure it as follows:
UndertowServer.create(YourJFinalConfig.class)
.onStart( builder -> {
builder.setSocketOption(Options.SSL_CLIENT_AUTH_MODE, SslClientAuthMode.REQUESTED);
})
.start();
2
3
4
5
This method was shared by community users at the provided link https://jfinal.com/feedback/7758 (opens new window).