Tomcat两个核心功能
1,处理Socket连接
2,管理servlet
因此Tomcat设计了两个核心组件连接器(Connector)和容器(Container)来分别做这两个事情,连接器负责对外交流,容器负责内部处理
在tomcat中连接器的名称coyote
在tomcat中的servlet容器名称是catalina
连接器coyote
三种连接方式
tomcat在8.5之后已经不支持BIO,在老版本的tomcat需要手动设置NIO
tomcat也支持NIO,不是默认使用,需要手动设置
APR是tomcat自带的一种通过C++实现连接方式,速度最快,但要根据不同的操作系统装不同的库
连接器组件
EndPoint:是传输层的抽象,主要是对socket的连接进行处理,需要通过连接池处理
Processor:主要是对HTTP进行处理
ProtocolHandler:对Http协议之上的具体业务协议的出来
AjpNioProtocol , AjpAprProtocol, AjpNio2Protocol , Http11NioProtocol ,Http11Nio2Protocol , Http11AprProtocol。
Adapter适配器
主要是将request转换不同的servletRequest
容器Catalina
是tomcat最核心的实现,也就是容器管理
Tomcat本质上是一款Servlet容器,因此Catalina才是tomcat的核心 其他模块 都是为Catalina 提供支撑的。 比如 : 通过Coyote 模块提供链接通信,Jasper 模块提供 JSP引擎,Naming 提供JNDI 服务,Juli 提供日志服务
Catalina内部的组件
Engine:表示整个Catalina的servlet引擎,用来管理多个虚拟站点,一个Servlce最大只有一个Engine,但是一个引擎可以包含多个Host
Host:代表一个虚拟主机,或者说一个站点,可以给tomcat配置多个虚拟主机地址,而一个虚拟主机可以包含多个Context
Context:就是一个web应用,一个主机可以配置多个应用
Wrapper:代表是servle组件
Tomcat配置
Server.xml配置
整体结构
<Server >
<Listener></Listener>
<Service name="Catalina">
<Executor>
</Executor>
</Service>
</Server>
server:提供一个接口,通过远程发送指令关闭tomcat
可以通过telent远程登录默认的8005,输入SHUTDOWN关闭tomcat
Executor:配置线程池,可以让线程使用线程池,默认不是开启的
<Connector port="8080"
protocol="HTTP/1.1"
executor="tomcatThreadPool"
maxThreads="1000"
minSpareThreads="100"
acceptCount="1000"
maxConnections="1000"
connectionTimeout="20000"
compression="on"
compressionMinSize="2048"
disableUploadTimeout="true"
redirectPort="8443"
URIEncoding="UTF‐8" />
Connector连接池
配置使用线程池
也可以配置使用NIO2进行连接
<Connector
executor="tomcatThreadPool"
port="8080"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
connectionTimeout="20000"
redirectPort="8443"
enableLookups="false"
maxPostSize="10485760"
URIEncoding="UTF-8"
acceptCount="100"
acceptorThreadCount="2"
disableUploadTimeout="true"
maxConnections="10000"
SSLEnabled="false"/>
Host:可以多个虚拟主机
通过绑定不同的域名,使得当前服务器可以绑定多个主机
<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>
<Host name="xyao.com" appBase="webapps2"
unpackWARs="true" autoDeploy="true">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs"
prefix="xyao_access_log" suffix=".txt"
pattern="%h %l %u %t "%r" %s %b" />
>
</Host>
Context:配置主机下的web应用
配置根路径访问自定义部署应用
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context docBase="test001" path="/">
</Context>
</Host>
用于配置文件上传路径
<Host name="localhost" appBase="webapps"
unpackWARs="true" autoDeploy="true">
<Context docBase="test001" path="/">
</Context>
<Context docBase="d:/upload" path="/upload"></Context>
</Host>
tomcat-users.xml配置
主要是配置tomcat管理员权限和访问页面的相关设置
http://localhost:8080/manager/
设置访问的账号和密码
<user username="admin" password="admin" roles="manager-gui"/>
文件上传
创建一个可以上传图片的表单
<form method="post" enctype="multipart/form-data" action="upload.do">
<div>
姓名:<input name="username">
</div>
<div>
请选择图片<input name="image" type="file">
</div>
<input type="submit" value="提交">
</form>
将两个相关依赖包导入到工程中
实现一个servlet获取上传文件,并且将其放到指定目录下,在数据库中保存文件的访问地址
@WebServlet("/upload.do")
public class UploadServlet extends HttpServlet {
// 上传文件存储目录
private static final String UPLOAD_DIRECTORY = "upload";
// 上传配置
private static final int MEMORY_THRESHOLD = 1024 * 1024 * 3; // 3MB
private static final int MAX_FILE_SIZE = 1024 * 1024 * 40; // 40MB
private static final int MAX_REQUEST_SIZE = 1024 * 1024 * 50; // 50MB
/**
* 上传数据及保存文件
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
// 检测是否为多媒体上传
if (!ServletFileUpload.isMultipartContent(request)) {
// 如果不是则停止
PrintWriter writer = response.getWriter();
writer.println("Error: 表单必须包含 enctype=multipart/form-data");
writer.flush();
return;
}
// 配置上传参数
DiskFileItemFactory factory = new DiskFileItemFactory();
// 设置内存临界值 - 超过后将产生临时文件并存储于临时目录中
factory.setSizeThreshold(MEMORY_THRESHOLD);
// 设置临时存储目录
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));
ServletFileUpload upload = new ServletFileUpload(factory);
// 设置最大文件上传值
upload.setFileSizeMax(MAX_FILE_SIZE);
// 设置最大请求值 (包含文件和表单数据)
upload.setSizeMax(MAX_REQUEST_SIZE);
// 中文处理
upload.setHeaderEncoding("UTF-8");
// 构造临时路径来存储上传的文件
// 这个路径相对当前应用的目录
String uploadPath = getServletContext().getRealPath("/") + File.separator + UPLOAD_DIRECTORY;
// 如果目录不存在则创建
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
try {
// 解析请求的内容提取文件数据
@SuppressWarnings("unchecked")
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
// 迭代表单数据,因为提交的表单除了文件还可以能由其他的数据
for (FileItem item : formItems) {
// 处理不在表单中的字段
if (!item.isFormField()) {//判断当前表单是文件的情况
//获取文件的名称
String fileName = new File(item.getName()).getName();
//指定的文件的路径
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
// 在控制台输出文件的上传路径
System.out.println(filePath);
// 保存文件到硬盘
item.write(storeFile);
request.setAttribute("message",
"文件上传成功!"+filePath);
}else{//字段内容
String name = item.getFieldName();
String value = item.getString();
System.out.println(value);
}
}
}
} catch (Exception ex) {
request.setAttribute("message",
"错误信息: " + ex.getMessage());
}
// 跳转到 message.jsp
request.getRequestDispatcher("/message.jsp").forward(
request, response);
}
}
Jemeter测试工具
可以模拟多线程多web项目的工具
基本使用
创建线程租
创建http请求
设置监听结果
Tomcat调优
配置调优
通过设置连接池优化连接线程数量
通过设置connector的连接方式(NIO,NIO2,APR)
JVM虚拟机调优
通过设置内存大小
通过修改垃圾回收机制策略
可以在catalina.bat中设置虚拟机的缓存和垃圾回收机制的策略
set JAVA_OPTS=-server -XX:+UseG1GC -XX:MaxGCPauseMillis=100 -Xms128m -Xmx1024m -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -Xloggc:../logs/gc.log
两个查看方法
可以在tomcat后台管理模式下进行查看
通过jconsole进行查看
-
将gc.log文件上传到gceasy.io查看gc中是否存在问题。
Ajax
ajax是三种技术的简称
asynchronized:异步
javascript
xml:一种数据格式配置文件
主要的作用是为了解决页面整体刷新不足,使页面具备了刷新
基本流程
前端使用ajax发送http请求到服务器端(asynchronized)
服务器端处理请求.将结果数据返回给浏览器
浏览器获取返回的数据,使用javascript进行局部刷新
基本使用
在前端使用jquery发送ajax请求
导入jquery
<script src="js/jquery-3.4.1.min.js"></script>
发送ajax请求
jQuery.ajax({
url:"loginajax.do",
data:{
username: document.getElementById("username").value,
password: document.getElementById("password").value
},
success:function(res){//从服务器端获取数据结果,进行页面局部刷新
if(res==0){
alert("登录失败")
}else{
alert("登录成功")
}
}
})
后台使用servlet接收数据并返回结果
@WebServlet("/loginajax.do")
public class LoginAjaxServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String password= req.getParameter("password");
String username = req.getParameter("username");
if(password.equals("123")){
resp.getWriter().write("1");
}else{
resp.getWriter().write("0");
}
}
}