001/** 002 * Copyright (c) 2015-2022, Michael Yang 杨福海 (fuhai999@gmail.com). 003 * <p> 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * <p> 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * <p> 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.jboot.app.undertow; 017 018import com.jfinal.server.undertow.PropExt; 019import com.jfinal.server.undertow.UndertowConfig; 020import com.jfinal.server.undertow.hotswap.HotSwapResolver; 021import io.jboot.app.config.JbootConfigManager; 022 023import java.io.IOException; 024import java.net.ServerSocket; 025 026public class JbootUndertowConfig extends UndertowConfig { 027 028 protected static final String DEV_MODE = "undertow.devMode"; 029 protected static final String UNDERTOW_PORT = "undertow.port"; 030 protected static final String UNDERTOW_HOST = "undertow.host"; 031 protected static final String UNDERTOW_RESOURCEPATH = "undertow.resourcePath"; 032 033 034 public JbootUndertowConfig(Class<?> jfinalConfigClass) { 035 super(jfinalConfigClass); 036 } 037 038 public JbootUndertowConfig(String jfinalConfigClass) { 039 super(jfinalConfigClass); 040 } 041 042 public JbootUndertowConfig(Class<?> jfinalConfigClass, String undertowConfig) { 043 super(jfinalConfigClass, undertowConfig); 044 } 045 046 public JbootUndertowConfig(String jfinalConfigClass, String undertowConfig) { 047 super(jfinalConfigClass, undertowConfig); 048 } 049 050 @Override 051 protected PropExt createPropExt(String undertowConfig) { 052 053 PropExt propExt = super.createPropExt(undertowConfig) 054 .append(new PropExt(JbootConfigManager.me().getProperties())); 055 056 String port = propExt.get(UNDERTOW_PORT); 057 058 //当不配置端口号时,默认为 8080 059 if (port == null || port.trim().length() == 0) { 060 propExt.getProperties().put(UNDERTOW_PORT, "8080"); 061 JbootConfigManager.setBootArg(UNDERTOW_PORT, "8080"); 062 } 063 064 //当配置为 -1 或者 * 时,默认为随机端口号 065 else if ((port.trim().equals("*") || port.trim().equals("-1"))) { 066 Integer availablePort = getAvailablePort(); 067 if (availablePort != null) { 068 propExt.getProperties().put(UNDERTOW_PORT, availablePort.toString()); 069 JbootConfigManager.setBootArg(UNDERTOW_PORT, availablePort.toString()); 070 } 071 } 072 073 //当不配置 undertow 开发模式时,默认开发模式为 devMode 074 String devMode = propExt.get(DEV_MODE); 075 if (devMode == null || devMode.trim().length() == 0) { 076 propExt.getProperties().put(DEV_MODE, JbootConfigManager.me().isDevMode()); 077 } 078 079 //当不配置 host 时,为其配置默认的 host 080 String host = propExt.get(UNDERTOW_HOST); 081 if (host == null || host.trim().length() == 0) { 082 if (isAppDevMode()) { 083 propExt.getProperties().put(UNDERTOW_HOST, "localhost"); 084 JbootConfigManager.setBootArg(UNDERTOW_HOST, "localhost"); 085 } else { 086 propExt.getProperties().put(UNDERTOW_HOST, "0.0.0.0"); 087 JbootConfigManager.setBootArg(UNDERTOW_HOST, "0.0.0.0"); 088 } 089 } 090 091 //当不配置资源路径时,默认为 classpath 下的 webapp 092 String resPath = propExt.get(UNDERTOW_RESOURCEPATH); 093 if (resPath == null || resPath.trim().length() == 0) { 094 propExt.getProperties().put(UNDERTOW_RESOURCEPATH, "classpath:webapp," + this.resourcePath); 095 } 096 097 return propExt; 098 } 099 100 /** 101 * 获取随机可用的端口号 102 * 103 * @return 104 */ 105 private static Integer getAvailablePort() { 106 ServerSocket serverSocket = null; 107 try { 108 serverSocket = new ServerSocket(0); 109 return serverSocket.getLocalPort(); 110 } catch (IOException e) { 111 } finally { 112 if (serverSocket != null) { 113 try { 114 serverSocket.close(); 115 } catch (IOException e) { 116 } 117 } 118 } 119 return null; 120 } 121 122 123 private static boolean isAppDevMode() { 124 String appMode = JbootConfigManager.me().getConfigValue("jboot.app.mode"); 125 return (null == appMode || "".equals(appMode.trim()) || "dev".equalsIgnoreCase(appMode.trim())); 126 } 127 128 129 @Override 130 public HotSwapResolver getHotSwapResolver() { 131 if (hotSwapResolver == null) { 132 hotSwapResolver = new JbootHotSwapResolver(getClassPathDirs()); 133 // 后续将此代码转移至 HotSwapResolver 中去,保持 UndertowConfig 的简洁 134 if (hotSwapClassPrefix != null) { 135 for (String prefix : hotSwapClassPrefix.split(",")) { 136 if (notBlank(prefix)) { 137 hotSwapResolver.addHotSwapClassPrefix(prefix); 138 } 139 } 140 } 141 } 142 return hotSwapResolver; 143 } 144} 145