Tomcat部署web应用
今天Max对大家培训了一下web程序在tomcat下正确的部署方式。
内容主要包括了:
1.java的classloader在tomcat下的体系结构
http://www.jaxmao.org/tomcat-docs/class-loader-howto.html
//调用Tomcat的JMX服务,如停止、启动web应用 public static boolean callWebModuleMBeanMethod(String appName,String methodName) throws Exception{ MBeanServer mBeanServer = null; if (MBeanServerFactory.findMBeanServer(null).size() > 0) { mBeanServer=(MBeanServer)MBeanServerFactory.findMBeanServer( null).get(0); } else { throw new Exception("cann't find catalina MBeanServer"); } Set names = null; try { names = mBeanServer.queryNames(new ObjectName( "*:j2eeType=WebModule,name=//localhost/"+appName+",*"), null); } catch (Exception e) { throw new Exception("cann't find "+appName+ " web moudule mbean! can't undeploy web app.\n"+e.getMessage()); } if(names==null || names.size()==0) { log.debug("can't find "+appName+ " web moudule mbean!"); return false; } ObjectName oname =null; Iterator it = names.iterator(); if (it.hasNext()) { oname=(ObjectName) it.next(); } if(oname==null) return false; try { mBeanServer.invoke(oname,methodName,null,null); return true; } catch (Exception e) { throw new Exception("can't "+methodName+" "+appName+ " web application!\n"+e.getMessage()); } } public static void main(String[] args){ callWebModuleMBeanMethod("app1","stop"); //停止web应用app1 callWebModuleMBeanMethod("app1","start"); //启动web应用app1 } ??
?
通过对上面的一些学习,了解到tomcat在类加载时候会给每个层级的classloader创建实例,并保存在PermGen中,有时候要对一些应用reload的时候,就会从新创建新的classloader实例并将旧的垃圾回收,如果把所有的lib都放在应用的级别,那么当reload的时候,旧的classloader实例往往会因为 jdbc 驱动注册 日志框架 将object放到threadlocal没有释放 启动thread但没有终止掉
或者其他程序在web应用中保留了其引用,造成不能垃圾回收,从而造成PermGen的OOME(号称tomcat7已经解决此问题)。因此,一种比较好的部署方式就是尽量吧公用的lib都放到tomcat的common目录下的lib里去,这样在reload一个web应用时,这个web应用的classloader的内存大小可能很小,大大降低PermGen的OOME的情况出现几率。
?
注意:log4j.jar不能放到common/lib下,因为log4j中读取的是当前log4j.jar所在路径下的对应的log4j.properties。
下面是log4j用XML配置的例子:http://wiki.apache.org/logging-log4j/Log4jXmlFormat
?
?
?
3.使用JNDI配置数据库资源,实现多项目共享数据库连接
在spring中:
<bean id="dbpool1" name="code"><?xml version="1.0" encoding="UTF-8"?><Context path="/EliteHttpAPS" docBase="EliteHttpAPS" debug="5" reloadable="true" crossContext="true"> <Resource name="jdbc/dbpool1" auth="Container" factory="com.elite.aps.dbservice.http.APSDataSourceFactory" type="javax.sql.DataSource" maxActive="10" maxIdle="10" minIdle="5" initialSize="5" encryptkey="rshMlJiUs+A=" dbtype="oracle" logsessionid="true" username="flex" password="letmein" driverClassName="oracle.jdbc.driver.OracleDriver" validationQuery="select 1 from dual" timeBetweenEvictionRunsMillis="60000" testWhileIdle="true" url="jdbc:oracle:thin:@127.0.0.1:1521:orcl"/></Context>
?其中crossContext="true" 代表了可以再多应用中使用
?
?
?
4.其他一些在项目中需要注意的tomcat中的配置
tomcat的server.xml中,host标签中有个属性是autoDeploy="true",在项目中使用false会比较好一些。
?