55import cn .hutool .core .io .FileUtil ;
66import cn .hutool .core .util .StrUtil ;
77import cn .hutool .log .LogFactory ;
8+ import com .xpcf .http4java .http .StandardServletConfig ;
89import com .xpcf .http4java .watcher .ContextFileChangeWatcher ;
910import com .xpcf .http4java .classloader .WebappClassLoader ;
1011import com .xpcf .http4java .exception .WebConfigDuplicatedException ;
1516import org .jsoup .nodes .Element ;
1617import org .jsoup .select .Elements ;
1718
19+ import javax .servlet .ServletConfig ;
1820import javax .servlet .ServletContext ;
21+ import javax .servlet .ServletException ;
1922import javax .servlet .http .HttpServlet ;
2023import java .io .File ;
2124import java .util .*;
@@ -55,6 +58,10 @@ public class Context {
5558
5659 private Map <Class <?>, HttpServlet > servletPool ;
5760
61+ private Map <String , Map <String , String >> servletClassNameInitParams ;
62+
63+ private List <String > loadOnStartupServletClassNames ;
64+
5865 public Context (String path , String docBase , Host host , boolean reloadable ) {
5966 TimeInterval timeInterval = DateUtil .timer ();
6067
@@ -65,7 +72,8 @@ public Context(String path, String docBase, Host host, boolean reloadable) {
6572 this .reloadable = reloadable ;
6673 this .servletContext = new ApplicationContext (this );
6774 this .servletPool = new HashMap <>();
68-
75+ this .servletClassNameInitParams = new HashMap <>();
76+ this .loadOnStartupServletClassNames = new ArrayList <>();
6977 ClassLoader commonClassLoader = Thread .currentThread ().getContextClassLoader ();
7078
7179 // reload 时重新生成classloader
@@ -82,6 +90,25 @@ public Context(String path, String docBase, Host host, boolean reloadable) {
8290
8391 }
8492
93+ public void parseLoadOnStartup (Document d ) {
94+ Elements es = d .select ("load-on-startup" );
95+ for (Element e : es ) {
96+ String loadOnStartupServletClassName = e .parent ().select ("servlet-class" ).text ();
97+ loadOnStartupServletClassNames .add (loadOnStartupServletClassName );
98+ }
99+ }
100+
101+ public void handleLoadOnStartup () {
102+ for (String loadOnStartupServletClassName : loadOnStartupServletClassNames ) {
103+ try {
104+ Class <?> clazz = webappClassLoader .loadClass (loadOnStartupServletClassName );
105+ getServlet (clazz );
106+ } catch (ClassNotFoundException | IllegalAccessException | InstantiationException | ServletException e ) {
107+ e .printStackTrace ();
108+ }
109+ }
110+ }
111+
85112 public WebappClassLoader getWebappClassLoader () {
86113 return webappClassLoader ;
87114 }
@@ -90,14 +117,14 @@ public boolean isReloadable() {
90117 return reloadable ;
91118 }
92119
93- public ServletContext getServletContext () {
94- return servletContext ;
95- }
96-
97120 public void setReloadable (boolean reloadable ) {
98121 this .reloadable = reloadable ;
99122 }
100123
124+ public ServletContext getServletContext () {
125+ return servletContext ;
126+ }
127+
101128 public String getServletClassName (String uri ) {
102129 return urlToServletClassName .get (uri );
103130 }
@@ -118,6 +145,26 @@ public void setDocBase(String docBase) {
118145 this .docBase = docBase ;
119146 }
120147
148+ private void parseServletInitParams (Document d ) {
149+ Elements servletClassNameElements = d .select ("servlet-class" );
150+ for (Element servletClassNameElement : servletClassNameElements ) {
151+ String servletClassName = servletClassNameElement .text ();
152+ Elements initElements = servletClassNameElement .parent ().select ("init-param" );
153+ if (initElements .isEmpty ()) {
154+ continue ;
155+ }
156+
157+ Map <String , String > initParams = new HashMap <>();
158+ for (Element initElement : initElements ) {
159+ String name = initElement .select ("param-name" ).get (0 ).text ();
160+ String value = initElement .select ("param-value" ).get (0 ).text ();
161+ initParams .put (name , value );
162+ }
163+
164+ servletClassNameInitParams .put (servletClassName , initParams );
165+ }
166+ }
167+
121168 private void parseServletMapping (Document d ) {
122169 Elements mappingUrlElements = d .select ("servlet-mapping url-pattern" );
123170
@@ -187,19 +234,43 @@ private void init() {
187234 // 完成重复性检验
188235 String xml = FileUtil .readUtf8String (contextWebXmlFile );
189236 Document d = Jsoup .parse (xml );
237+
190238 parseServletMapping (d );
239+
240+ parseServletInitParams (d );
241+
242+ parseLoadOnStartup (d );
243+
244+ handleLoadOnStartup ();
245+ }
246+
247+ private void destroyServlets () {
248+ Collection <HttpServlet > servlets = servletPool .values ();
249+ for (HttpServlet servlet : servlets ) {
250+ servlet .destroy ();
251+ }
191252 }
192253
193254 /**
194255 * 考虑double check lock
256+ *
195257 * @param clazz
196258 * @return
197259 */
198- public synchronized HttpServlet getServlet (Class <?> clazz ) throws IllegalAccessException , InstantiationException {
260+ public synchronized HttpServlet getServlet (Class <?> clazz ) throws IllegalAccessException , InstantiationException , ServletException {
199261 HttpServlet servlet = servletPool .get (clazz );
200262 if (null == servlet ) {
263+
201264 servlet = (HttpServlet ) clazz .newInstance ();
265+ ServletContext servletContext = getServletContext ();
266+ String className = clazz .getName ();
267+ String servletName = classNameToServletName .get (className );
268+ Map <String , String > initParameters = servletClassNameInitParams .get (className );
269+ ServletConfig servletConfig = new StandardServletConfig (servletContext , initParameters , servletName );
270+ servlet .init (servletConfig );
202271 servletPool .put (clazz , servlet );
272+
273+
203274 }
204275 return servlet ;
205276 }
@@ -217,6 +288,7 @@ private void deploy() {
217288 public void stop () {
218289 webappClassLoader .stop ();
219290 contextFileChangeWatcher .stop ();
291+ destroyServlets ();
220292 }
221293
222294 public void reload () {
0 commit comments