Web容器—Tomcat
tomcat安装与启动
Tomcat是用于部署我们Web项目的一个容器。我们首先从官网下载一个Tomcat的安装包放到服务器解压,之后配置上环境变量就可以在服务器上使用了。
使用命令:
export CATALINA_HOME=/usr/local/apache-tomcat-8.5.54
echo $CATALINA_HOME
这样我们就安装好了,然后输入命令启动一下
$CATALINA_HOME/bin/startup.sh
如图所示就已经启动好了
然后我们通过服务器的ip+端口号访问一下
出现以下说明启动完了,
如果需要关闭,输入命令:$CATALINA_HOME/bin/shutdown.sh
tomcat里面的资源可以存放静态的html,也可以放动态的servlet。
tomcat结构及配置
如图所示为tomcat具体架构
server.xml文件具体格式:
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8005" shutdown="SHUTDOWN">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<GlobalNamingResources>
<Resource name="UserDatabase" auth="Container"
type="org.apache.catalina.UserDatabase"
description="User database that can be updated and saved"
factory="org.apache.catalina.users.MemoryUserDatabaseFactory"
pathname="conf/tomcat-users.xml" />
</GlobalNamingResources>
<Service name="Catalina">
<Executor name="tomcatThreadPool" namePrefix="catalina-exec-"
maxThreads="150" minSpareThreads="4"/>
<Connector port="8080" protocol="HTTP/1.1"
connectionTimeout="20000"
redirectPort="8443" />
<Engine name="Catalina" defaultHost="localhost">
<Realm className="org.apache.catalina.realm.LockOutRealm">
<Realm className="org.apache.catalina.realm.UserDatabaseRealm"
resourceName="UserDatabase"/>
</Realm>
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="localhost_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
</Host>
</Engine>
</Service>
</Server>
Connector
当一个用户的请求进来后,由connector接受后从socket中读取数据,并对请求进行解析,解析后把请求交给Container处理,Container根据用户请求的内容来决定响应什么东西或者执行一些web应用的代码或者查找一些静态资源等,然后由connector响应请求分发给用户。
Connector的配置参数
- protocol :协议,默认是http1.1,一般在性能调优的时候会用
- port :端口号,默认端口号是8080
- address :IP地址,如果不配置的话会监听服务器上所有ip,有时候因为安全问题不被允许,所以设置监听哪个ip
- connectionTimeout :客户端连接超时时间,单位是毫秒,如果一个请求一直没有响应,那么超过这个配置时间就强制关闭连接
- acceptCount :指当所有连接已经占用了,那么新的请求进来就等待排队,一般默认是100,当线程池线程已经满了后请求超过这个数值后就会被拒绝处理。
- maxConnections :指的是connector能支持的最大连接数,对于BIO的connector这个值和线程池大小有关,请求超过这个值后进去等待。
- executor :线程池,配置线程池用于接收客户请求连接
Executor
用于设置连接数量大小,管理线程
Executor的配置参数
- maxThreads : 最大线程数量
- minSpareThreads : 最小线程数量
Valve
用于开启tomcat的日志,收集错误信息等,有系统运行日志、访问日志、应用日志。
Valve的配置参数
- directory : 日志存放目录,相对路径,当对于tomcat安装目录
- prefix :访问日志文件的文件名前缀
- suffix :访问日志文件的文件名后缀
- pattern : 日志打印的格式 例如:pattern=“method : %m, client ip: %a, time: %t "%r" statusCode: %s, byteSend: %b, User-Agent: %{User-Agent}i”
- fileDateFormat : 用来做日志滚动的,默认是“yyyy-MM-dd.”,一般和totatable一起使用。
- rotatable:按上面的时间来开启日志切割,默认是true
JDBC
JDBC查询数据
jdbc是Java提供的一套基于不同数据库下进行开发的工具。我们通过写一段代码来认识JDBC。
public class JdbcTest {
static final String JDBC_DRIVER="com.mysql.cj.jdbc.Driver";
static final String DB_URL="jdbc:mysql://localhost:3306/test?serverTimezone=UTC&characterEncoding=utf8";
static final String USER="root";
static final String PASSWORD="root";
private void helloJdbc () {
Connection conn = null;
Statement st = null;
ResultSet rs = null;
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
st = conn.createStatement();
rs = st.executeQuery("select * from users where id = 3");
while (rs.next()) {
System.out.println(rs.getString("id"));
System.out.println(rs.getString("name"));
System.out.println(rs.getString("username"));
System.out.println(rs.getString("password"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != rs) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != st) {
try {
st.close();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != conn) {
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
}
}
}
}
public static void main(String[] args) {
new JdbcTest().helloJdbc();
}
JDBC进阶
游标
下面我们分析一下JDBC的一些使用注意事项:当我们需要一次查询过多的数据,这时候如果数据量过大会导致我们程序抛出内存溢出的异常,原因是我们JVM运行的内存是有限的,如果我们查出来的数据过大,已经超过JVM能承受的大小后,就会报错。这时候我们引入一个叫游标的东西,游标是一个能帮我们读取部分服务器的结果集的机制。使用游标需要在DB_URL里开启游标,而且我们的处理对象要选用preparedStatement接口对象。
下面用代码展示:
public class JdbcCursorFetchTest {
static final String JDBC_DRIVER="com.mysql.cj.jdbc.Driver";
static final String DB_URL="jdbc:mysql://localhost:3306/test?serverTimezone=UTC&useCursorFetch=true";
static final String USER="root";
static final String PASSWORD="root";
private void helloJdbc () {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
//1.装载驱动
try {
Class.forName(JDBC_DRIVER);
conn = DriverManager.getConnection(DB_URL, USER, PASSWORD);
ps = conn.prepareStatement("select * from users");
ps.setFetchSize(1);
rs = ps.executeQuery();
while (rs.next()) {
System.out.println(rs.getString("id"));
System.out.println(rs.getString("name"));
System.out.println(rs.getString("username"));
System.out.println(rs.getString("password"));
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (null != rs) {
try {
rs.close