目录
安装tomcat
配置windows服务
目录结构组成
修改默认端口
新增用户
部署Web应用
配置数据源
tomcat抛java.lang.OutOfMemoryError解决
本篇以Tomcat8的版本windows10环境下配置
前提安装jdk
1,下载,连接地址https://tomcat.apache.org/download-80.cgi 这里我下载的是tomcat8免安装压缩包版本
2,解压到指定目录,比如我这里是c:\soft\tomcat8
3,配置环境变量
CATALINA_HOME=c:\soft\tomcat8,然后将%CATALINA_HOME%\bin在加入path环境变量中
可选环境变量:MAVEN_OPTS 值为:-Xms128m -Xmx512m
初始化分配的最小最大内存,下面有摘抄网上经常遇到的out of memory错误解释解决方式
然后可以在cmd中startup启动,之后浏览器中查看localhost:8080
cmd进入tomcat_home的bin目录,输入service.bat install,同样service.bat remove可以移除注册服务
c:\soft\apache-tomcat-8.5.39\bin>service.bat install
Installing the service 'Tomcat8' ...
Using CATALINA_HOME: "c:\soft\apache-tomcat-8.5.39"
Using CATALINA_BASE: "c:\soft\apache-tomcat-8.5.39"
Using JAVA_HOME: "C:\soft\jdk8"
Using JRE_HOME: "C:\soft\jdk8\jre"
Using JVM: "C:\soft\jdk8\jre\bin\server\jvm.dll"
The service 'Tomcat8' has been installed.
启动服务 net Start Tomcat8
关闭服务 net stop Tomcat8
问题:有些人说怎么没有service命令呢,可能是你下载的文件中本身不包含,需要重新下载
可以在conf中的server.xml中修改
可以修改默认的8080端口,但是建议端口在1024以上避免与公共端口冲突
1,启动tomcat
2,进入控制台页面
提示要输入密码,下边配置
控制台密码是通过JAAS(Java Authentication Authorization Service Java验证和授权API)控制
打开Tomcat配置路径conf下的tomcat.xml
可以配置一个账号:
如果角色不清楚,可以在%CATALINA_HOME%\webapps\manager\WEB-INF中的web.xml中查看,其中%CATALINA_HOME%是你的tomcat根目录,然后重启tomcat服务,输入账号密码即可登录:
在这里可以管理你的应用
只需将一个Web应用复制到Tomcat的webapps下,系统就会吧该应用部署到Tomcat中,很简单复制粘贴即可
在上一步骤中进行配置
实际上具体执行的就是在tomcatwebapps中创建一个文件夹webdemo,然后将你target中的文件复制过去,其实跟第一步一致
然后访问:
其他部署不在说明
在实际开发中,我们有时候还会使用服务器提供给我们的数据库连接池,比如我们希望Tomcat服务器在启动的时候可以帮我们创建一个数据库连接池,那么我们在应用程序中就不需要手动去创建数据库连接池,直接使用Tomcat服务器创建好的数据库连接池即可
DHCP数据库连接池,这是apache的一个项目,凡是数据库连接池都要实现javax.sql.DataSource接口,换句话说,实现了这个借口的类就是一个数据库连接池,还有C3P0数据库连接池,下面配置DHCP局部数据源,对应还有全局的
不管什么数据源,都需要提供特定数据库的JDBC驱动,以MySQL为例进行操作,这里驱动使用mysql-connector-java-5.1.39-bin.jar,将此文件复制到tomcat的lib路径下
局部数据源只需要修改用户自己的Web部署文件,只与特定的应用相关,不需要修改系统的配置,这样不会造成混乱,这样就提供了更好的封装性
JNDI(Java Naming and Directory Interface),Java命名和目录接口,它对应于J2SE中的javax.naming包,
这 套API的主要作用在于:它可以把Java对象放在一个容器中(JNDI容器),并为容器中的java对象取一个名称,以后程序想获得Java对象,只需 通过名称检索即可。其核心API为Context,它代表JNDI容器,其lookup方法为检索容器中对应名称的对象
Tomcat服务器创建的数据源是以JNDI资源的形式发布的,所以说在Tomat服务器中配置一个数据源实际上就是在配置一个JNDI资源,如下是测试步骤:
Tomcat服务器创建好数据源之后是以JNDI的形式绑定到一个JNDI容器中的,我们可以把JNDI想象成一个大大的容器,我们可以往这个容器中存放一些对象,一些资源,JNDI容器中存放的对象和资源都会有一个独一无二的名称,应用程序想从JNDI容器中获取资源时,只需要告诉JNDI容器要获取的资源的名称,JNDI根据名称去找到对应的资源后返回给应用程序
创建测试页面
<%@ page contentType="text/html; charset=UTF-8" language="java" errorPage="" %>
<%@ page import="javax.naming.*,java.sql.*,javax.sql.*" %>
测试Tomcat数据源
<%
//初始化Context,使用InitialContext初始化Context
Context ctx=new InitialContext();
/*
通过JNDI查找数据源,该JNDI为java:comp/env/jdbc/dstest,分成两个部分
java:comp/env是Tomcat固定的,Tomcat提供的JNDI绑定都必须加该前缀
jdbc/dstest是定义数据源时的数据源名
*/
DataSource ds=(DataSource)ctx.lookup("java:comp/env/jdbc/datasource");
//获取数据库连接
Connection conn=ds.getConnection();
//获取Statement
Statement stmt=conn.createStatement();
//执行查询,返回ResulteSet对象
ResultSet rs=stmt.executeQuery("select * from tbl2");
while(rs.next())
{
out.println(rs.getString(1)
+ "\t" + rs.getString(2) + "
");
}
%>
测试结果:
注意:上面测试页面中有配置导入包的地方,
这个是肯定不能少的,在普通的JAVA项目,也要导入这些包类似这种形式:
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;
测试完毕!
我们平时做javaEE开发时,服务器会为我们的应用程序创建很多资源,比如request对象,response对象,服务器创建的这些资源有两种方式提供给我们的应用程序使用:一种是JNDI的方式,服务器把创建好的资源绑定到JNDI容器中去,应用程序想要使用资源时,就直接从JNDI容器中获取相应的资源即可,;一种是通过方法参数的形式传递进来,比如我们在Servlet中写的doPost和doGet方法中使用到的request对象和response对象就是服务器以参数的形式传递给我们的
以下是测试代码:
import java.io.IOException;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import me.gacl.util.JdbcUtils_JNDI;
public class JNDITest extends HttpServlet {
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Connection conn = null;
PreparedStatement st = null;
ResultSet rs = null;
try{
//获取数据库连接
conn = JdbcUtils_JNDI.getConnection();
String sql = "insert into test1(name) values(?)";
st = conn.prepareStatement(sql);
st.setString(1, "gacl");
st.executeUpdate();
//获取数据库自动生成的主键
rs = st.getGeneratedKeys();
if(rs.next()){
System.out.println(rs.getInt(1));
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//释放资源
JdbcUtils_JNDI.release(conn, st, rs);
}
}
public void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
我遇到此问题是数据库Mysql版本不对,下载正确的版本jar即可
mysql版本是8.0.11,mysql-connector-java版本是5.1.31,后来把mysql-connector-java改为最新版mysql-connector-java-5.1.46-bin.jar后,运行成功
解释: Heap size 设置 JVM堆的设置是指java程序运行过程中JVM可以调配使用的内存空间的设置.JVM在启动的时候会自动设置Heap size的值,其初始空间(即-Xms)是物理内存的1/64,最大空间(-Xmx)是物理内存的1/4。可以利用JVM提供的-Xmn -Xms -Xmx等选项可进行设置。Heap size 的大小是Young Generation 和Tenured Generaion 之和。
提示:在JVM中如果98%的时间是用于GC且可用的Heap size 不足2%的时候将抛出此异常信息。
提示:Heap Size 最大不要超过可用物理内存的80%,一般的要将-Xms和-Xmx选项设置为相同,而-Xmn为1/4的-Xmx值。
解决方法: 手动设置Heap size 修改TOMCAT_HOME/bin/catalina.bat,在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: Java代码 set JAVA_OPTS=%JAVA_OPTS% -server -Xms800m -Xmx800m -XX:MaxNewSize=256m 或修改catalina.sh 在“echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: JAVA_OPTS="$JAVA_OPTS -server -Xms800m -Xmx800m -XX:MaxNewSize=256m"
原因: PermGen space的全称是Permanent Generation space,是指内存的永久保存区域,这块内存主要是被JVM存放Class和Meta信息的,Class在被Loader时就会被放到PermGen space中,它和存放类实例(Instance)的Heap区域不同,GC(Garbage Collection)不会在主程序运行期对PermGen space进行清理,所以如果你的应用中有很CLASS的话,就很可能出现PermGen space错误,这种错误常见在web服务器对JSP进行pre compile的时候。如果你的WEB APP下都用了大量的第三方jar, 其大小超过了jvm默认的大小(4M)那么就会产生此错误信息了。
解决方法: 1. 手动设置MaxPermSize大小 修改TOMCAT_HOME/bin/catalina.bat(Linux下为catalina.sh),在Java代码 “echo "Using CATALINA_BASE: $CATALINA_BASE"”上面加入以下行: set JAVA_OPTS=%JAVA_OPTS% -server -XX:PermSize=128M -XX:MaxPermSize=512m
catalina.sh下为: Java代码 JAVA_OPTS="$JAVA_OPTS -server -XX:PermSize=128M -XX:MaxPermSize=512m"
另外看到了另外一个帖子,觉得挺好,摘抄如下:
分析java.lang.OutOfMemoryError: PermGen space 发现很多人把问题归因于: spring,hibernate,tomcat,因为他们动态产生类,导致JVM中的permanent heap溢出 。然后解决方法众说纷纭,有人说升级 tomcat版本到最新甚至干脆不用tomcat。还有人怀疑spring的问题,在spring论坛上讨论很激烈,因为spring在AOP时使用CBLIB会动态产生很多类。 但问题是为什么这些王牌的开源会出现同一个问题呢,那么是不是更基础的原因呢?tomcat在Q&A很隐晦的回答了这一点,我们知道这个问题,但这个问题是由一个更基础的问题产生。 于是有人对更基础的JVM做了检查,发现了问题的关键。原来SUN 的JVM把内存分了不同的区,其中一个就是permenter区用来存放用得非常多的类和类描述。本来SUN设计的时候认为这个区域在JVM启动的时候就固定了,但他没有想到现在动态会用得这么广泛。而且这个区域有特殊的垃圾收回机制,现在的问题是动态加载类到这个区域后,gc根本没办法回收!
对于以上两个问题,解决方式:
在catalina.bat的第一行增加:
Java代码 :set JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m
在catalina.sh的第一行增加:
Java代码 :JAVA_OPTS=-Xms64m -Xmx256m -XX:PermSize=128M -XX:MaxNewSize=256m -XX:MaxPermSize=256m