详解如何通过tomcat的ManagerServlet远程部署项目
介绍
之前在邮政实习时,leader让我阅读tomcat的源代码,尝试自己实现远程部署项目的功能,于是便有了这此实践。
在Tomact中有一个Manager应用程序,它是用来管理已经部署的web应用程序,在这个应用程序中,ManagerServlet是他的主servlet,通过它我们可以获取tomcat的部分指标,远程管理web应用程序,不过这个功能会受到web应用程序部署中安全约束的保护。
当你请求ManagerServlet时,它会检查getPathInfo()返回的值以及相关的查询参数,以确定被请求的操作。它支持以下操作和参数(从servlet路径开始):
请求路径
描述
/deploy?config={config-url}
根据指定的path部署并启动一个新的web应用程序(详见源码)
/deploy?config={config-url}&war={war-url}/
根据指定的pat部署并启动一个新的web应用程序(详见源码)
/deploy?path=/xxx&war={war-url}
根据指定的path部署并启动一个新的web应用程序(详见源码)
/list
列出所有web应用程序的上下文路径。格式为path:status:sessions(活动会话数)
/reload?path=/xxx
根据指定path重新加载web应用
/resources?type=xxxx
枚举可用的全局JNDI资源,可以限制指定的java类名
/serverinfo
显示系统信息和JVM信息
/sessions
此方法已过期
/expire?path=/xxx
列出path路径下的web应用的session空闲时间信息
/expire?path=/xxx&idle=mm
Expiresessionsforthecontextpath/xxxwhichwereidleforatleastmmminutes.
/sslConnectorCiphers
显示当前connector配置的SSL/TLS密码的诊断信息
/start?path=/xx
根据指定path启动web应用程序
/stop?path=/xxx
根据指定path关闭web应用程序
/threaddump
WriteaJVMthreaddump
/undeploy?path=/xxx
关闭并删除指定path的Web应用程序,然后删除底层WAR文件或文档基目录。
我们可以通过ManagerServlet中getPathInfo()提供的操作,将自己的项目远程部署到服务器上,下面将贴出我的实践代码,在实践它之前你只需要引入httpclient包和commons包。
封装统一的远程请求管理类
封装此类用于方便client请求ManagerServlet:
importjava.io.File; importjava.net.URL; importjava.net.URLEncoder; importorg.apache.commons.io.IOUtils; importorg.apache.commons.lang.StringUtils; importorg.apache.http.Header; importorg.apache.http.HttpHost; importorg.apache.http.HttpResponse; importorg.apache.http.HttpStatus; importorg.apache.http.auth.AuthScope; importorg.apache.http.auth.Credentials; importorg.apache.http.auth.UsernamePasswordCredentials; importorg.apache.http.client.AuthCache; importorg.apache.http.client.methods.HttpGet; importorg.apache.http.client.methods.HttpRequestBase; importorg.apache.http.client.protocol.ClientContext; importorg.apache.http.impl.auth.BasicScheme; importorg.apache.http.impl.client.BasicAuthCache; importorg.apache.http.impl.client.DefaultHttpClient; importorg.apache.http.impl.conn.PoolingClientConnectionManager; importorg.apache.http.protocol.BasicHttpContext; publicclassTomcatManager{ privatestaticfinalStringMANAGER_CHARSET="UTF-8"; privateStringusername; privateURLurl; privateStringpassword; privateStringcharset; privatebooleanverbose; privateDefaultHttpClienthttpClient; privateBasicHttpContextlocalContext; /**constructor*/ publicTomcatManager(URLurl,Stringusername){ this(url,username,""); } publicTomcatManager(URLurl,Stringusername,Stringpassword){ this(url,username,password,"ISO-8859-1"); } publicTomcatManager(URLurl,Stringusername,Stringpassword,Stringcharset){ this(url,username,password,charset,true); } publicTomcatManager(URLurl,Stringusername,Stringpassword,Stringcharset,booleanverbose){ this.url=url; this.username=username; this.password=password; this.charset=charset; this.verbose=verbose; //创建网络请求相关的配置 PoolingClientConnectionManagerpoolingClientConnectionManager=newPoolingClientConnectionManager(); poolingClientConnectionManager.setMaxTotal(5); this.httpClient=newDefaultHttpClient(poolingClientConnectionManager); if(StringUtils.isNotEmpty(username)){ Credentialscreds=newUsernamePasswordCredentials(username,password); Stringhost=url.getHost(); intport=url.getPort()>-1?url.getPort():AuthScope.ANY_PORT; httpClient.getCredentialsProvider().setCredentials(newAuthScope(host,port),creds); AuthCacheauthCache=newBasicAuthCache(); BasicSchemebasicAuth=newBasicScheme(); HttpHosttargetHost=newHttpHost(url.getHost(),url.getPort(),url.getProtocol()); authCache.put(targetHost,basicAuth); localContext=newBasicHttpContext(); localContext.setAttribute(ClientContext.AUTH_CACHE,authCache); } } /**根据指定的path部署并启动一个新的应用程序*/ publicTomcatManagerResponsedeploy(Stringpath,Filewar,booleanupdate)throwsException{ StringBuilderbuffer=newStringBuilder("/deploy"); buffer.append("?path=").append(URLEncoder.encode(path,charset)); if(war!=null){ buffer.append("&war=").append(URLEncoder.encode(war.toString(),charset)); } if(update){ buffer.append("&update=true"); } returninvoke(buffer.toString()); } /**获取所有已部署的web应用程序的上下文路径。格式为path:status:sessions(活动会话数)*/ publicTomcatManagerResponselist()throwsException{ StringBuilderbuffer=newStringBuilder("/list"); returninvoke(buffer.toString()); } /**获取系统信息和JVM信息*/ publicTomcatManagerResponseserverinfo()throwsException{ StringBuilderbuffer=newStringBuilder("/serverinfo"); returninvoke(buffer.toString()); } /**真正发送请求的方法*/ privateTomcatManagerResponseinvoke(Stringpath)throwsException{ HttpRequestBasehttpRequestBase=newHttpGet(url+path); HttpResponseresponse=httpClient.execute(httpRequestBase,localContext); intstatusCode=response.getStatusLine().getStatusCode(); switch(statusCode){ caseHttpStatus.SC_OK://200 caseHttpStatus.SC_CREATED://201 caseHttpStatus.SC_ACCEPTED://202 break; caseHttpStatus.SC_MOVED_PERMANENTLY://301 caseHttpStatus.SC_MOVED_TEMPORARILY://302 caseHttpStatus.SC_SEE_OTHER://303 StringredirectUrl=getRedirectUrl(response); this.url=newURL(redirectUrl); returninvoke(path); } returnnewTomcatManagerResponse().setStatusCode(response.getStatusLine().getStatusCode()) .setReasonPhrase(response.getStatusLine().getReasonPhrase()) .setHttpResponseBody(IOUtils.toString(response.getEntity().getContent())); } /**提取重定向URL*/ protectedStringgetRedirectUrl(HttpResponseresponse){ HeaderlocationHeader=response.getFirstHeader("Location"); StringlocationField=locationHeader.getValue(); //isitarelativeLocationorafull? returnlocationField.startsWith("http")?locationField:url.toString()+'/'+locationField; } }
封装响应结果集
@Data publicclassTomcatManagerResponse{ privateintstatusCode; privateStringreasonPhrase; privateStringhttpResponseBody; }
测试远程部署
在测试之前请先在配置文件放通下面用户权限:
下面是测试成功远程部署war包的代码:
importstaticorg.testng.AssertJUnit.assertEquals; importjava.io.File; importjava.net.URL; importorg.testng.annotations.Test; publicclassTestTomcatManager{ @Test publicvoidtestDeploy()throwsException{ TomcatManagertm=newTomcatManager(newURL("http://localhost:8080/manager/text"),"sqdyy","123456"); Filewar=newFile("E:\\tomcat\\simple-war-project-1.0-SNAPSHOT.war"); TomcatManagerResponseresponse=tm.deploy("/simple-war-project-1.0-SNAPSHOT",war,true); System.out.println(response.getHttpResponseBody()); assertEquals(200,response.getStatusCode()); //output: //OK-Deployedapplicationatcontextpath/simple-war-project-1.0-SNAPSHOT } @Test publicvoidtestList()throwsException{ TomcatManagertm=newTomcatManager(newURL("http://localhost:8080/manager/text"),"sqdyy","123456"); TomcatManagerResponseresponse=tm.list(); System.out.println(response.getHttpResponseBody()); assertEquals(200,response.getStatusCode()); //output: //OK-Listedapplicationsforvirtualhostlocalhost ///:running:0:ROOT ///simple-war-project-1.0-SNAPSHOT:running:0:simple-war-project-1.0-SNAPSHOT ///examples:running:0:examples ///host-manager:running:0:host-manager ///manager:running:0:manager ///docs:running:0:docs } @Test publicvoidtestServerinfo()throwsException{ TomcatManagertm=newTomcatManager(newURL("http://localhost:8080/manager/text"),"sqdyy","123456"); TomcatManagerResponseresponse=tm.serverinfo(); System.out.println(response.getHttpResponseBody()); assertEquals(200,response.getStatusCode()); //output: //OK-Serverinfo //TomcatVersion:ApacheTomcat/7.0.82 //OSName:Windows10 //OSVersion:10.0 //OSArchitecture:amd64 //JVMVersion:1.8.0_144-b01 //JVMVendor:OracleCorporation } }
参考资料
ManagerServlet源码地址
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。