Tomcat知识概括

本文深入探讨了Tomcat作为JavaWeb服务器的角色,解析了Tomcat与Web服务器、应用服务器的区别,以及其在JavaEE生态中的定位。详细介绍了Tomcat的目录结构、部署方法、日志管理和并发模式。同时,提到了与Nginx、Apache等服务器的对比,以及在处理并发和性能上的考量。文章还涵盖了Tomcat的配置环境变量、JMX应用,以及解决乱码问题的方法,为读者提供了全面的Tomcat知识指南。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaWeb

简介:

  • JavaWeb 是指,所有通过 Java 语言编写可以通过浏览器访问的程序的总称,叫 JavaWeb。 JavaWeb是基于请求和响应来开发的。
    在这里插入图片描述
  • web 资源按实现的技术和呈现的效果的不同,又分为静态资源和动态资源两种。
    静态资源: html、css、js、txt、mp4 视频 , jpg 图片
    动态资源: jsp 页面、Servlet 程序

web服务器和应用服务器

web服务器和应用服务器比较:

  • 通俗的讲,Web服务器传送(serves)页面使浏览器可以浏览,然而应用程序服务器提供的是客户端应用程序可以调用(call)的方法(methods)
  • 确切一点,你可以说:Web服务器专门处理HTTP请求(request)但是应用程序服务 器是通过很多协议来为应用程序提供(serves)商业逻辑(business logic)

注意:

  • 现在大多数应用程序服务器也包含了Web服务器,这就意味着可以把Web服务器当作是应用程序服务器的一个子集(subset)。
  • 虽然应用程序服务器包含了Web服务器的功能,但是开发者很少把应用程序服务器部署(deploy)成这种功能(capacity)(译者注:这种功能是指既有应用程序服务器的功能又有Web服务器的功能)。
  • 相反,如果需要,他们通常会把Web服务器独立配置,和应用程序服务器一前一后
  • 这种功能的分离有助于提高性能(简单的Web请求(request)就不会影响应用程序服务器了),分开配置(专门的Web服务器,集群(clustering)等等),而且给最佳产品的选取留有余地
  • WEB服务器一般是通用的,而应用服务器一般是专用的,如Tomcat只处理JAVA应用程序而不能处理ASPX或PHP。

HTTP服务器:

  • 基本上可以理解为web服务器,只是协议指定为HTTP/HTTPS。

常见Web服务器:

  • Nginx:Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔·赛索耶夫为俄罗斯访问量第二的Rambler.ru站点(俄文:Рамблер)开发的,第一个公开版本0.1.0发布于2004年10月4日。
  • Apache:在Web服务器中,Apache是纯粹的Web服务器,经常与Tomcat配对使用。它对HTML页面具有强大的解释能力,但是不能解释嵌入页面内的服务器端脚本代码(JSP/Servlet)。
  • Tomcat:早期的Tomcat是一个嵌入Apache内的JSP/Servlet解释引擎,Apache+Tomcat就相当于IIS+ASP后来的Tomcat已不再嵌入Apache内,Tomcat进程独立于Apache进程运行。而且,Tomcat已经是一个独立的Servlet和JSP容器,业务逻辑层代码和界面交互层代码可以分离了。因此,有人把Tomcat叫做轻量级应用服务器
  • IIS:微软早期的IIS,就是一个纯粹的Web服务器后来,它嵌入了ASP引擎,可以解释VBScript和JScript服务器端代码了,这时,它就可以兼作应用服务器。当然,它与J2EE应用服务器根本无法相比,但是,从功能上说,从原理上说,它勉强可以称之为应用服务器。确切地说,它是兼有一点应用服务器功能的Web服务器
  • 不仅仅是Apache HTTP Server和Nginx,绝大多数编程语言所包含的类库中也都实现了简单的HTTP服务器方便开发者使用使用这些类库能够非常容易的运行一个HTTP服务器,它们都能够通过绑定IP地址并监听tcp端口来提供HTTP服务
    ①HttpServer (Java HTTP Server )
    ②Python SimpleHTTPServer

常见应用服务器:

  • JBoss:开源版已更名为WildFly;JBoss是一套可以基于J2EE框架的全套解决方案,包括JBoss/Server,JBoss/spyderMQ,JBoss/Jaws,JBoss/Zola,JBoss/Zoap,JBoss/Castor,JBoss/Tomcat。
  • Glassfilsh:Sun公司推出的Java EE服务器,免费、开放源代码的应用服务。
  • WebLogic:WebLogic是bea公司出品的一个application server,确切的说是一个基于j2ee架构的中间件,webserver是用来构建网站的必要软件用来解析发布网页等功能,它是用纯java开发的。

Tomcat与应用服务器:

  • 到目前为止,Tomcat一直被认为是Servlet/JSP API的执行器,也就所谓的Servlet容器。然而,Tomcat并不仅仅如此,它还提供了JNDI和JMX API的实现机制。尽管如此,Tomcat仍然还不能算是应用服务器,因为它不提供大多数J2EE API的支持。
  • 很有意思的是,目前许多的应用服务器通常把Tomcat作为它们Servlet和JSP API的容器。由于Tomcat允许开发者只需通过加入一行致谢,就可以把Tomcat嵌入到它们的应用中。遗憾的是,许多商业应用服务器并没有遵守此规则。
  • 对于开发者来说,如果是为了寻找利用Servlet、JSP、JNDI和JMX技术来生成Java Web应用的话,选择Tomcat是一个优秀的解决方案但是为了寻找支持其他的J2EEAPI,那么寻找一个应用服务器或者把Tomcat作为应用服务器的辅助,将是一个不错的解决方案;第三种方式是找到独立的J2EE API实现,然后把它们跟Tomcat结合起来使用。虽然整合会带来相关的问题,但是这种方式是最为有效的。
    应用服务器提供更多的J2EE特征,如EJB,JMS,JAAS等,支持Servlet。
    而Tomcat则功能没有那么强大,它不提供EJB等支持。但如果与JBoss(一个开源的应用服务器)集成到一块,则可以实现J2EE的全部功能。
    很多中小应用不需要采用EJB等技术,Servlet已经足够,这时如果用应用服务器就有些浪费。而Tomcat短小精悍,配置方便,能满足需求

为什么说Tomcat是一个Web服务器而不是一个应用服务器:

  • 如果你把你的企业级应用程序(就是指使用到JPA,EJB或者其他JavaEE组件功能的应用程序)部署到一个符合JavaEE规范的服务器上,那么真正的应用服务器本身是不需要你的部署包包含对JavaEE组件进行实现的类库的。如果部署的时候你必须要通过自己的应用程序中自带jar文件来支持这些JavaEE组件,那你用的就是Web服务器,就像是Tomcat。
  • 举个例子,如果你在你的程序里使用了JPA,然后你打算把程序部署到JBoss AS7服务器上,你的程序本身是不需要包含支持JPA实现的jar包的。但是如果你想把程序部署到Tomcat服务器上,你就必须要把实现JPA功能的jar包放到你的lib库中,然后再一起部署过去。这就是为什么JBoss AS7是应用服务器而Tomcat是Web服务器的原因。另一个关键的区别是,Tomcat上不能部署EAR文件,而只能部署WAR文件。
    Ear文件(扩展名为.Ear,Enterprise Application Archive)包含全部企业应用程序。在这种情形下,一个企业应用程序被定义为多个jar文件、资源、类和Web应用程序的集合

Tomcat与Web服务器:

  • Tomcat是提供一个支持Servlet和JSP运行的容器。Servlet和JSP能根据实时需要,产生动态网页内容而对于Web服务器来说,Apache仅仅支持静态网页,对于支持动态网页就会显得无能为力Tomcat则既能为动态网页服务,同时也能为静态网页提供支持。尽管它没有通常的Web服务器快、功能也不如Web服务器丰富,但是Tomcat逐渐为支持静态内容不断扩充大多数的Web服务器都是用底层语言编写如C,利用了相应平台的特征,因此用纯Java编写的Tomcat执行速度不可能与它们相提并论
  • 一般来说,大的站点都是将Tomcat与Apache的结合,Apache负责接受所有来自客户端的HTTP请求,然后将Servlets和JSP的请求转发给Tomcat来处理。Tomcat完成处理后,将响应传回给Apache,最后Apache将响应返回给客户端。 
    两者都有HTTP服务的功能。
  • 而且为了提高性能,可以一台apache连接多台tomcat实现负载平衡

综上:

  • Web服务器主要是处理静态页面处理和作为 Servlet容器,解释和执行servlet/JSP,

  • 而应用服务器是运行业务逻辑的,主要是EJB、 JNDI和JMX API等J2EEAPI方面的,还包含事务处理、数据库连接等功能,所以在企业级应用中,应用服务器提供的功能比WEB服务器强大的多。

  • Apache是纯粹的web服务器而Tomcat和IIS因为具有了解释执行服务器端代码的能力,可以称作为轻量级应用服务器或带有服务器功能的Web服务器

  • Weblogic、WebSphere因为能提供强大的J2EE功能,毫无疑问是绝对的应用服务器

  • 对于处于中间位置的Tomcat,它可以配合纯Web服务器Apache一起使用,也可以作为应用服务器的辅助与应用服务器一起部署

  • 此外对于web服务器(或者说使用Http协议的webweb服务器也就是http服务器)不支持生成动态页面。因此需要通过其他模块来支持(例如通过Shell、PHP、Python脚本程序来动态生成内容)

  • 如果想要使用Java程序来动态生成资源内容,使用这一类HTTP服务器很难做到Java Servlet技术以及衍生的Java Server Pages技术可以让Java程序也具有处理HTTP请求并且返回内容(由程序动态控制)的能力,Tomcat正是支持运行Servlet/JSP应用程序的容器(Container)因此tomcat也叫web应用服务器

  • 而对于Jboss这类应用服务器主要针对于分布式,对于一般中小项目使用分布式太浪费资源,而对于大型项目使用Jboss太繁重了,一般使用springcloud和Dubbo
    ①现在流行的分布式架构中的消息中间件一般使用ActiveMQ、RabbitMQ,Kafka等等
    而EJB形式的消息中间件主要在EJB容器中例如weblogic服务器的jms模块

  • 链接:
    一文总结应用、Web、HTTP服务器,Apache、Nginx,Tomcat、IIS、JBoss、Glassfish等区别
    tomcat 与 nginx,apache的区别是什么?

Netty

servlet 本质:

  • servlet是一个规范,实现servlet规范的类处理请求逻辑。
  • tomcat才是与客户端直接打交道的家伙,他监听了端口,请求过来后,根据url等信息,确定要将请求交给哪个servlet去处理,然后调用那个servlet的service方法,service方法返回一个response对象,tomcat再把这个response返回给客户端。

Socket与Servlet的关系

  • Socket:使用TCP/IP或者UDP协议在服务器与客户端之间进行传输的技术,是网络编程的基础
  • Servlet:使用http协议在服务器与客户端之间通信的技术。是Socket的一种应用。
  • 而socket本质就是传输,也就是IO,而IO分为NIO,BIO,AIO。

tomcat 源码为啥不采用netty 处理并发?

  • 因为servlet规范,tomcat要实现servlet规范所以不能最大发挥NIO的特性,servlet3.0之前完全是同步阻塞模型,在read http body 以及 response的情况下,即使tomcat选择 NIO的connector也是模拟阻塞的行为,因为servlet规范规定的就是这样。

Netty也可以做servlet容器:

  • 实现大体思路
    ①排除掉tomcat依赖
    ②解决掉报错,保证spring mvc的上下文正常启动
    ③启动netty容器,最后一个handler负责将servlet request交给dispatcherServlet处理

Netty是什么?

  • 本质:JBoss做的一个Jar包
  • 目的:快速开发高性能、高可靠性的网络服务器和客户端程序
  • 优点:提供异步的、事件驱动的网络应用程序框架和工具通俗的说:一个好使的处理Socket的东西。

如果没有Netty?

  • 远古:java.net + java.io
  • 近代:java.nio
  • 其他:Mina,Grizzly

与Mina相比有什么优势?

  • 都是Trustin Lee的作品,Netty更晚;
  • Mina将内核和一些特性的联系过于紧密,使得用户在不需要这些特性的时候无法脱离,相比下性能会有所下降,Netty解决了这个设计问题;
  • Netty的文档更清晰,很多Mina的特性在Netty里都有;
  • Netty更新周期更短,新版本的发布比较快;
  • 它们的架构差别不大,Mina靠apache生存,而Netty靠jboss,和jboss的结合度非常高,Netty有对googleprotocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi);
  • Netty比Mina使用起来更简单,Netty里你可以自定义的处理upstream events 或/和 downstream
    events,可以使用decoder和encoder来解码和编码发送内容;
  • Netty和Mina在处理UDP时有一些不同,Netty将UDP无连接的特性暴露出来;而Mina对UDP进行了高级层次的抽象,可以把UDP当成"面向连接"的协议,而要Netty做到这一点比较困难。

Netty的特性:

  • 设计:
    ①统一的API,适用于不同的协议(阻塞和非阻塞)
    ②基于灵活、可扩展的事件驱动模型
    ③高度可定制的线程模型
    ④可靠的无连接数据Socket支持(UDP)
  • 性能
    ①更好的吞吐量,低延迟
    ②更省资源
    ③尽量减少不必要的内存拷贝
  • 安全
    ①完整的SSL/TLS和STARTTLS的支持
    ②能在Applet与Android的限制环境运行良好
  • 健壮性
    ①不再因过快、过慢或超负载连接导致OutOfMemoryError
    ②不再有在高速网络环境下NIO读写频率不一致的问题
  • 易用
    ①完善的JavaDoc,用户指南和样例
    ②简洁简单
    ③仅信赖于JDK1.5

Netty 在哪些行业得到了应用?

  • 互联网行业:
    ①随着网站规模的不断扩大,系统并发访问量也越来越高,传统基于 Tomcat 等 Web容器的垂直架构已经无法满足需求,需要拆分应用进行服务化,以提高开发和维护效率。从组网情况看,垂直的架构拆分之后,系统采用分布式部署,各个节点之间需要远程服务调用,高性能的RPC 框架必不可少,Netty 作为异步高性能的通信框架,往往作为基础通信组件被这些 RPC 框架使用。
    ②典型的应用有:阿里分布式服务框架 Dubbo 的 RPC 框架使用 Dubbo 协议进行节点间通信,Dubbo 协议默认使用 Netty 作为基础通信组件,用于实现各进程节点之间的内部通信。它的架构图如下:在这里插入图片描述
    ③其中,服务提供者和服务消费者之间,服务提供者、服务消费者和性能统计节点之间使用 Netty 进行异步/同步通信。  
    ④除了 Dubbo 之外,淘宝的消息中间件 RocketMQ 的消息生产者和消息消费者之间,也采用 Netty 进行高性能、异步通信。  
    ⑤除了阿里系和淘宝系之外,很多其它的大型互联网公司或者电商内部也已经大量使用 Netty 构建高性能、分布式的网络服务器。

  • 游戏行业:无论是手游服务端、还是大型的网络游戏,Java 语言得到了越来越广泛的应用。Netty 作为高性能的基础通信组件,它本身提供了TCP/UDP 和 HTTP 协议栈,非常方便定制和开发私有协议栈。账号登陆服务器、地图服务器之间可以方便的通过 Netty进行高性能的通信,架构示意图如下:在这里插入图片描述

  • 大数据领域:经典的 Hadoop 的高性能通信和序列化组件 Avro 的 RPC 框架,默认采用 Netty 进行跨节点通信,它的Netty Service 基于 Netty 框架二次封装实现。
    ①大数据计算往往采用多个计算节点和一个/N个汇总节点进行分布式部署,各节点之间存在海量的数据交换。由于 Netty 的综合性能是目前各个成熟 NIO 框架中最高的,因此,往往会被选中用作大数据各节点间的通信。

  • 企业软件:企业和 IT 集成需要 ESB,Netty 对多协议支持、私有协议定制的简洁性和高性能是 ESB RPC框架的首选通信组件。事实上,很多企业总线厂商会选择 Netty 作为基础通信组件,用于企业的 IT 集成。

  • 通信行业:Netty 的异步高性能、高可靠性和高成熟度的优点,使它在通信行业得到了大量的应用。

Netty和Tomcat有什么区别?

  • Netty和Tomcat最大的区别就在于通信协议,Tomcat是基于Http协议的,他的实质是一个基于http协议的web容器,但是Netty不一样,他能通过编程自定义各种协议,因为netty能够通过codec自己来编码/解码字节流,完成类似redis访问的功能,这就是netty和tomcat最大的不同。
  • 有人说netty的性能就一定比tomcat性能高,其实不然,tomcat从6.x开始就支持了nio模式,并且后续还有arp模式——一种通过jni调用apache网络库的模式,相比于旧的bio模式,并发性能得到了很大提高,特别是arp模式,而netty是否比tomcat性能更高,则要取决于netty程序作者的技术实力了。

为什么Netty受欢迎?

  • netty是一款收到大公司青睐的框架,在我看来,netty能够受到青睐的原因有三:
    ①并发高
    ②传输快
    ③封装好

Netty为什么并发高?

  • Netty是一款基于NIO(Nonblocking I/O,非阻塞IO)开发的网络通信框架,对比于BIO(BlockingI/O,阻塞IO),他的并发性能得到了很大提高。

Tomcat目录与使用

目录介绍:

  • bin 专门用来存放 Tomcat 服务器的可执行程序
  • conf 专门用来存放 Tocmat 服务器的配置文件
  • lib 专门用来存放 Tomcat 服务器的 jar 包
  • logs 专门用来存放 Tomcat 服务器运行时输出的日记信息
  • temp 专门用来存放 Tomcdat 运行时产生的临时数据
  • webapps 专门用来存放部署的 Web 工程。
  • work 是 Tomcat 工作时的目录,用来存放 Tomcat 运行时 jsp 翻译为 Servlet 的源码,和 Session钝化的目录。

webapps目录下提供了几个web应用:

  • docs:tomcat文档页面
  • examples:tomcat案例页面
  • host-manager:web主机管理页面
  • manager:web应用管理页面
  • ROOT:tomcat主页页面
    在这里插入图片描述

tomcat启动和停止:

  • 找到 Tomcat 目录下的 bin 目录下的 startup.bat 文件,双击,就可以启动 Tomcat 服务器。(出现以下页面则成功!)
    在这里插入图片描述

  • 找到 Tomcat 的 bin 目录下的 shutdown.bat 双击,就可以停止 Tomcat 服务器

修改端口号:

  • 找到 Tomcat 目录下的 conf 目录,找到 server.xml 配置文件。在这里插入图片描述

Tomcat部署

部暑 web 工程到 Tomcat 中(静态部署):

  • 第一种部署方法:只需要把 web 工程的目录打成“war包“拷贝到Tomcat 的 webapps 目录下即可。
    ①访问路径:ip+prot+项目名
    和第二种方法一样,是不过是war包是经过压缩的而已,启动后tomcat会自动帮你解压。
  • 第二种部署方法:只需要把 web 工程的目录拷贝到Tomcat 的 webapps 目录下即可。
    ①访问路径:ip+prot+项目名
  • 第三种部署方法:找到 Tomcat 下的 conf 目录\Catalina\localhost\ 下,创建如下的xml配置文件
    ①访问路径:ip+prot+项目名
<!-- Context 表示一个工程上下文 path 表示工程的访问路径:/abc 
docBase 表示你的工程目录在哪里 -->
 <Context path="/abc" docBase="E:\book" />
  • 第四种部署方法:配置Server.xml部署Web工程。修改配置文件无需我们打war,这样方便开发。添加如下:
    ①访问路径:ip+prot+项目名
<Context docBase="D:\test\dubbo-admin-2.5.10" path="/test" reloadable="false" />
 <!-- 访问路径为path内容。docBase 表示你的工程目录在哪里-->
  • 第三,第四种与第一,第二种的区别是可以把项目或jar包放在任意目录。

  • context属性详解:
    ①path:是访问时的根地址,表示访问的路径;
    ②reloadable:表示可以在运行时在classes与lib文件夹下自动加载类包。其中reloadable="false"表示当应用程序 中的内容发生更改之后服务器不会自动加载(开启的话简称热部署)这个属性在开发阶段通常都设为true,方便开发,在发布阶段应该设置为false,提高应用程序的访问速度。
    ③docbase:表示应用程序的路径,注意斜杠的方向“/”。 docBase可以使用绝对路径,也可以使用相对路径,相对路径相对于webapps。
    ④workdir:表示缓存文件的放置地址

  • 注意:
    Tomcat中webapps目录下不能直接存放网页格式的文件,否则无法访问到该文件,必须有子目录才能访问该网页文件。
    ②例如:我们直接将index.html放在webapps目录中,通过浏览器http://localhost:8080/index.html 是无法访问到index.html的。而必须要webapps/petweb/index.html才可以通过http://localhost:8080/petweb/index.html 访问到index.html页面。

  • 链接:
    tomcat部署详解
    tomcat部署简介

Web应用打包成war文件:

  • 可以将WEB程序打包成一个war包放在目录下,服务器会自动解开这个war包,并在这个目录下生成一个同名的文件夹。一个war包就是有特性格式的jar包,它是将一个Web程序的所有内容进行压缩得到。
  • 打包请参考如下步骤:
    ①在命令提示符中进入项目文件夹
    ②键入如下命令:jar cvf XXX.war。这样在项目文件夹下应该有war文件。 (也可以打包到指定的地方,命令如下:jar cvf d:/XXX.war )
  • 服务器将war文件解开,并且在webapps下面又生成了一个文件夹,然后把war的内容拷贝到里面去了。我们可以通过以下方式取消自动解压缩,将xml配置文件中的unpackWAR
    属性设置为"false" 即可。

部暑 web 工程到 Tomcat 中(动态部署):

  • 动态部署是指可以在服务器启动之后部署web应用程序,而不用重新启动服务器。动态部署要用到服务器提供的manager.war文件,如果在$CATALINA_HOME/webapps/下没有该文件,你必须去重新下载tomcat,否则不能完成以下的功能。要想使用该管理程序必须首先编辑$CATALINA_HOME/conf/tomcat-users.xml文件。
<tomcat-users>
<role rolename="tomcat"/>
<role rolename="role1"/>
<role rolename="manager"/>
<user username="george" password="george" roles="manager"/>
<user username="tomcat" password="tomcat" roles="tomcat"/>
<user username="both" password="tomcat" roles="tomcat,role1"/>
<user username="role1" password="tomcat" roles="role1"/>
</tomcat-users>
  • 然后在浏览器中键入如下地址:http://localhost:8080/ ,应该看到一个加菲猫了吧。点击左边的TomcatManager链接,提示输入用户名和密码,本文都是george,然后可以看到以下页面:在这里插入图片描述
    ①Context Path(option): 中输入/项目名
    ②XML Configration file URL 中要指定一个.xml文件,比如我们在F:/下建立一个tomconfig.xml文件,内容如下:<Context reloadable =“false” / > 。docBase 不用写了,因为要在下一个文本框中填入。
    ③WAR or Directory URL: 中键入F:/项目名或者F:/项目名.war都可以,然后点击Deploy按钮,看看上面是不是已经看到了你web应用程序,名字就是你Context Path(option):中的名字。
    ④如果你部署.war文件还有更加简单的方式,下面还有个Select WAR file upload 点击浏览选择.war文件,然后点击Deploy也可以。

IDEA是如何部署tomcat项目:

  • 在localhost里面配置上了xml文件映射项目的context。每搭建一个项目就生成单独的一个文件夹,多个项目之间彼此不干涉,也不干涉tomcat本身的文件夹。在这里插入图片描述
  • 链接:IDEA是如何部署tomcat项目的

手托 html 页面到浏览器和在浏览器中输入 http://ip:端 口号/工程名/访问的区别:

  • 手托 html 页面的原理:
    在这里插入图片描述
  • 输入访问地址访问的原因:
    在这里插入图片描述

ROOT 的工程的访问,以及 默认 index.html 页面的访问:

  • 当我们在浏览器地址栏中输入访问地址如下: http://ip:port/没有工程名的时候,默认访问的是 ROOT 工程(三脚猫)
  • 当我们在浏览器地址栏中输入的访问地址如下: http://ip:port/工程名/没有资源名,默认访问 index.html页面

tomcat的webapps目录下度的ROOT目录介绍:

  • tomcat的webapps目录下有个默认的ROOT目录,也可以把项目war包解压放入ROOT目录,同样可以运行项目。但放在ROOT目录下之后访问项目方式就会变为:ip+端口号
  • 所以项目放在webapps目录和放在ROOT目录的区别是webapps不需要解压,ROOT需要解压webapps访问项目需要加项目名,ROOT不需要加项目名。
  • tomcat默认看到的cat页面的文件就是在放ROOT文件夹下的。(三脚猫),如果ROOT目录删除后,tomcat启动后还是会生成的。

什么是catalina.out:

  • catalina.out即标准输出和标准输出,所有输出都会进入catalina.out。这里包含tomcat运行自己输出的日志以及应用里向console输出的日志。
  • Catalina.out里都是有tomcat自己的日志以及控制台输出的内容根据项目不同自己定义进行。

注意:

  • 其实,一般很少在本地启动Tomcat,大多数都是在开发工具(eclipse或者Idea)中集成外部本地Tomcat,无须配置环境变量,因为idea内部已经直接找到了Tomcat的根目录中。

Tomcat底层架构

Tomcat架构俯视图:
在这里插入图片描述
Tomcat架构平视图:
在这里插入图片描述
Tomcat容器对比:
在这里插入图片描述
Tomcat总结:

  • Tomcat并不仅仅只是Servlet容器,它包含了Servlet容器和连接处理器
  • Tomcat利用了Socket来接收请求,同时实现了Http协议
  • 操作系统实现了TCP协议,并提供了方便上层应用程序调用的接口—Socket
  • Java中在建立Socket连接时,先调用的JDK中的方法,JDK中再调用操作系统中的方法

Tomcat底层原理

Tomcat架构简述:

  • Tomcat中最顶层的容器是Server,代表着整个服务器,是管理tomcat实例的组件一个Server可以包含至少一个Service,用于具体提供服务。
  • Service主要包含两个部分:Connector和Container。Tomcat 的心脏就是这两个组件,他们的作用如下:
    Connector用于处理连接相关的事情,并提供Socket与Request和Response相关的转化;
    Container用于封装和管理Servlet,以及具体处理Request请求;

Service简述:

  • 可以认为一个service就启动一个JVM,更严格地说,一个engine组件才对应一个JVM(定义负载均衡时,jvmRoute就定义在Engine组件上用来标识这个JVM),只不过connector也工作在JVM中。
  • 一个Service只有一个Container,但是可以有多个Connectors,
  • 这是因为一个服务可以有多个连接,如同时提供Http和Https链接,也可以提供向相同协议不同端口的连接,
    在这里插入图片描述
  • 多个 Connector 和一个 Container 就形成了一个 Service,有了 Service 就可以对外提供服务了,但是Service 还要一个生存的环境,必须要有人能够给她生命、掌握其生死大权,那就非 Server 莫属了!所以整个 Tomcat的生命周期由 Server 控制。
  • 另外,上述的包含关系或者说是父子关系,都可以在tomcat的conf目录下的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" />
  <Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
  <Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
  <Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
  
  <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">  
    <!-- 第一个连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。   -->
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8" />
	<!-- 第二个连接器监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器-->
    <Connector port="8009" protocol="AJP/1.3" 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 &quot;%r&quot; %s %b" />
      </Host>
      
    </Engine>
    
  </Service>
  
</Server>
  • 除了配置文件,还可以通过下边的一张结构图更清楚的理解:
    Server标签设置的端口号为8005,shutdown=”SHUTDOWN” ,表示在8005端口监听“SHUTDOWN”命令,如果接收到了就会关闭Tomcat。(从此端口上可以远程向该实例发送shutdown关闭命令。)
    ②一个Server下为一个Service,Service左边是一个Container,Service下边两个Connector。
    <1>第一个连接器监听8080端口,负责建立HTTP连接。在通过浏览器访问Tomcat服务器的Web应用时,使用的就是这个连接器。
    <2>第二个连接器监听8009端口,负责和其他的HTTP服务器建立连接。在把Tomcat与其他HTTP服务器集成时,就需要用到这个连接器
    在这里插入图片描述

Connector架构分析:

  • Connector用于接受请求并将请求封装成Request和Response,然后交给Container进行处理,Container处理完之后在交给Connector返回给客户端。
  • Connector就是使用ProtocolHandler来处理请求的,不同的ProtocolHandler代表不同的连接类型,比如:Http11Protocol使用的是普通Socket来连接的,Http11NioProtocol使用的是NioSocket来连接的。
  • 其中ProtocolHandler由包含了三个部件:Endpoint、Processor、Adapter。
    Endpoint用来处理底层Socket的网络连接Processor用于将Endpoint接收到的Socket封装成RequestAdapter用于将Request交给Container进行具体的处理
    ②Endpoint由于是处理底层的Socket网络连接,因此Endpoint是用来实现TCP/IP协议的,而Processor用来实现HTTP协议的,Adapter将请求适配到Servlet容器进行具体的处理。
    ③Endpoint的抽象实现AbstractEndpoint里面定义的Acceptor和AsyncTimeout两个内部类和一个Handler接口。Acceptor用于监听请求,AsyncTimeout用于检查异步Request的超时,Handler用于处理接收到的Socket,在内部调用Processor进行处理。
    在这里插入图片描述

Container架构分析:

  • Container用于封装和管理Servlet,以及具体处理Request请求,在Connector内部包含了4个子容器,结构图如下:在这里插入图片描述
  • 4个子容器的作用分别是:
    Engine:引擎,用来管理多个站点,一个Container最多只能有一个Engine
    Host代表一个站点,也可以叫虚拟主机,通过配置Host就可以添加站点;一个Engine能有多个Host
    Context代表一个应用程序,对应着平时开发的一套程序,或者一个WEB-INF目录以及下面的web.xml文件;一个Host能有多个Context
    Wrapper每一Wrapper封装着一类Servlet;(一类servlet可以用多个servlet实例)。一个Context能有多个Wrapper
  • 下面找一个Tomcat的文件目录对照一下,如下图所示:在这里插入图片描述
  • Context和Host的区别是Context表示一个应用,我们的Tomcat中默认的配置下webapps下的每一个文件夹目录都是一个Context,其中ROOT目录中存放着主应用,其他目录存放着子应用,而整个webapps就是一个Host站点。
  • 我们访问应用Context的时候,如果是ROOT下的则直接使用域名就可以访问,例如:www.ledouit.com,如果是Host(webapps)下的其他应用,则可以使用http://www.ledouit.com/docs进行访问,当然默认指定的根应用(ROOT)是可以进行设定的,只不过Host站点下默认的主营用是ROOT目录下的。

Container如何处理请求的:

  • Container处理请求是使用Pipeline-Valve管道来处理的!(Valve是阀门之意)
  • Pipeline-Valve是责任链模式,责任链模式是指在一个请求处理的过程中有很多处理者依次对请求进行处理,每个处理者负责做自己相应的处理,处理完之后将处理后的请求返回,再让下一个处理着继续处理。如图所示:在这里插入图片描述
  • 但是!Pipeline-Valve使用的责任链模式和普通的责任链模式有些不同!区别主要有以下两点:
    ①每个Pipeline都有特定的Valve,而且是在管道的最后一个执行,这个Valve叫做BaseValve,BaseValve是不可删除的;
    ②在上层容器的管道的BaseValve中会调用下层容器的管道。
  • 我们知道Container包含四个子容器,而这四个子容器对应的BaseValve分别在:StandardEngineValve、StandardHostValve、StandardContextValve、StandardWrapperValve。
  • Pipeline的处理流程图如下:
    ①Connector在接收到请求后会首先调用最顶层容器的Pipeline来处理,这里的最顶层容器的Pipeline就是EnginePipeline(Engine的管道);
    ②在Engine的管道中依次会执行EngineValve1、EngineValve2等等,最后会执行StandardEngineValve,在StandardEngineValve中会调用Host管道,然后再依次执行Host的HostValve1、HostValve2等,最后在执行StandardHostValve然后再依次调用Context的管道和Wrapper的管道,最后执行到StandardWrapperValve
    当执行到StandardWrapperValve的时候,会在StandardWrapperValve中创建FilterChain,并调用其doFilter方法来处理请求,这个FilterChain包含着我们配置的与请求相匹配的Filter和Servlet,其doFilter方法会依次调用所有的Filter的doFilter方法和Servlet的service方法,这样请求就得到了处理!
    ④当所有的Pipeline-Valve都执行完之后,并且处理完了具体的请求,这个时候就可以将返回的结果交给Connector了,Connector在通过Socket的方式将结果返回给客户端
    在这里插入图片描述

Tomcat底层架构中注意的点:

  • 链接:
    tomcat处理连接的详细过程
    Tomcat就是这么简单
  • 每个Connector中都有两个端口:
    port:监听浏览器发送请求,该端口设置为80后在访问的时候就可以省略端口(http://localhost);
    redirectPort:重定向端口,当用户用http请求某个资源,而该资源本身又被设置了必须要https方式访问,此时Tomcat会自动重定向到这个redirectPort设置的https端口,即处理https请求的端口。
  • 域名对应着 ip:
    ①域名会被 dns 转成相应的 ip,端口是服务提供的,http 协议的默认端口是 80,https 的默认端口是 443。如果你的 http 服务提供的端口不是 80,那就要加端口才能访问。想要不加端口访问非 80 的 http 服务,你就需要有个反向代理来帮你把端口映射到 80 上面,但你这个时候用 ip 直接访问是无效的。
    ②域名靠 DNS 解析,也就是域名经过 DNS 会解析成 ip,加不加端口都一样,因为不加默认 80,如果是 https 默认 443
    ③流程:输入地址->本机查解析缓存->DNS 解析->访问指定 ip 服务器->(服务器负载均衡或 CDN 回源等各种处理)->提供服务的服务器根据访问请求 host 和端口匹配 Vhost->应用提供服务
  • 在Tomcat下配置一个应用服务(service)中,配置多个端口号。即一个service配置多个端口,项目可以通过多个端口访问。
    修改tomcat-home\conf下的server.xml,在Service下配置多个<Connector>即可。
  • 设置虚拟主机:多个不同域名的网站共存于一个Tomcat中,也就是一个Engine中配置多个host。在这里插入图片描述
  • 设置多应用直接将Web工程目录放进webapp目录即可,或者设置server.xml文件,或者在conf 目录\Catalina\localhost\ 下创建xml文件。在下面部署这一章节有讲。
  • war包和jar包:
    ①说实话没啥区别 ,因为web. xml可以用注解实现,然后静态文件暂且不理会。
    那么tomcat内部如何判断jar包还是wai包呢?-------内部直接写死在这里插入图片描述
  • RequestFacade和ResponseFacade。
    ①Tomcat 为什么使用Facade模式对Request对象进行包装?
    <1>为了屏蔽内部的catalina容器的相关方法,使用户免受非sevlet标准方法的干扰。
    ②tomcat中request的包装结构:在这里插入图片描述
    <1>其中org.apache.coyote.Request是应用层拿到的Request对象的底层实现,不便使用
    <2>org.apache.catalina.connector.Request类封装了org.apache.coyote.Request类,实现了HttpServletRequest接口,已经具备了实际使用能力,不过它还包含了很多Catalina的方法,这些方法不应该暴露给应用层,以免引起与其他容器实现的兼容性问题
    <3>org.apache.catalina.connector.RequestFacade类实现了HttpServletRequest接口,并在其中包含了一个org.apache.catalina.connector.Request对象,将所有HttpServletRequest接口的调用都代理给org.apache.catalina.connector.Request对象来处理,这样就屏蔽了Catalina的相关的内部方法,使用户可以专注于servlet的标准方法。
    总结来说就是除了Servlet标准之外,tomcat自己的request对象内部还有很多成员变量和方法,但是这些都是不需要暴漏出去的,所以搞了一层包装。
  • tomcat同一端口不同应用
    一个端口只能被一个程序占用,这个程序就是Tomcat。
    ②而helloapp和bookstore是两个项目,这两个项目共同被Tomcat管理。
    在这里插入图片描述

Tomcat日志

Tomcat日志框架简介:

  • Tomcat 的日志管理功能是借助于 Apache Commons Logging库来实现的,该库是对当今几个流行的日志框架的精简和封装,从而使得 Tomcat 日志管理不必依赖于某一个具体的日志框架。
  • 从 Tomcat 6.0开始,Tomcat 内的Apache Commons Logging 日志库默认使用 java.util.logging 日志框架实现,如果你想要使用其他的日志框架,只需用对应框架的 jar 替换掉Tomcat原来的jar即可,日志框架的选择支持以下三种方式:
    使用系统自带的logging API: java.util.logging
    使用java servlet规范提供的logging API: javax.servlet.ServletContext.log(..)
    选择使用其他的日志框架,如log4j

Tomcat日志框架详解:

  • 调用 Java Servlets logging API打印的日志会被 Tomcat内部日志系统接管,开发者不能设置日志的打印级别:
    ①调用 ServletContext.log(String) 或者 GenericServlet.log(String) 打印的日志级别为 INFO
    ②调用 ServletContext.log(String, Throwable) 或者 GenericServlet.log(String, Throwable) 打印的日志级别为 SEVERE

  • 使用java.util.logging(默认)
    由于 JDK 自带的java.util.logging实现提供的日志管理能力极为有限,不支持应用级别日志管理。因此,Tomcat 默认的日志库对java.util.logging API 进行了重新实现,这些实现被称为 "JULI",里面包含了一些特有的定制类,其中最重要的是一个自定义的LogManager类它能够区别出运行在 Tomcat 容器中的多个不同的Web应用以及它们的类加载器,从而可以支持不同的应用使用各自独立的日志配置。
    ②你可以从 Tomcat 全局 Web 应用两个层面对 Tomcat 默认的JULI进行日志配置:
    <1>全局配置通常使用 ${catalina.base}/conf/logging.properties文件进行配置,如果该文件未配置或不可读,Tomcat将会使用JRE 中的${java.home}/lib/logging.properties 配置文件。
    <2>应用配置则是使用 WEB-INF/classes/logging.properties文件进行配置;
    JRE 默认的 logging.properties 仅指定了一个 ConsoleHandler 用于将日志内容打印至控制台。
    Tomcat 默认的 conf/logging.properties 指定的处理器除 ConsoleHandler 外还包含了几个文件处理器用来将日志内容输出到文件。
    处理器默认的日志级别是 INFO,可选的日志级别从高到低依次为:SEVERE > WARNING > INFO > CONFIG >FINE > FINER > FINEST > ALL > OFF。
    ⑥你还可以设置指定包的日志级别,例如打印 Tomcat 调试级别日志可使用如下配置:
    org.apache.catalina.level=FINEST
    JULI的日志配置和JDK 中 java.util.logging的配置极为相似,同时,为了实现更高的日志配置灵活性做了少许的扩展:
    <1>为了实现能够实例化同一个类的多个处理器,需要在处理器全限定名之前加上一个以数字开头、以"." 结束的前缀,例如:"1catalina." 。
    <2>使用${属性名}来代表某属性所对应的属性值。
    <3>使用loggerName.handlers 属性来为指定名称的 Logger 定义一个处理器集合。
    <4>使用 .handlers属性来为根 Logger 定义一个处理器集合。
    <5>默认情况下,Logger如果包含有相关的处理器是不会将日志管理的工作委派给它的父Logger的,可以使用 loggerName.useParentHandlers= true/false属性来配置。
    <6>默认情况下,日志的记录文件是会被永久保存在服务器上的,可以使用 handlerName.maxDays 属性来配置日志文件可保留的最大天数,设置<=0则会永久保存。
    <7>org.apache.juli.FileHandler支持使用缓冲输出日志,默认不使用缓冲,可以使用bufferSize 属性设置缓冲流大小,设置 0 会使用默认8K,设置负数则不使用缓冲。

  • 使用Log4j
    ①如果你想要在你的Web项目中使用 Log4j 对日志进行管理,只需要把 log4j.jar 和 log4j.properties 两个文件分别添加到你Web应用的WEB-INF/lib 和 WEB-INF/classes目录下。
    如果你想要使用 Log4j 替换 Tomcat 默认的JULI,需要执行以下几步操作:
    <1> 下载与Tomcat版本对应的Log4j实现的 tomcat-juli.jar 和 tomcat-juli-adapters.jar ,注意此 tomcat-juli.jar 与Tomcat 自带的JULI包虽然名称相同但实现不同。下载地址:http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.64/bin/extras/
    <2> 下载Log4j.jar。下载地址:https://logging.apache.org/log4j/2.x/download.html
    <3> 将 log4j.jar 和 tomcat-juli-adapters.jar 拷贝到 $CATALINA_HOME/lib 目录, 使用新下载的 tomcat-juli.jar 替换掉Tomcat 自带的 $CATALINA_HOME/bin/tomcat-juli.jar 。
    <4>在 $CATALINA_HOME/lib 目录下创建一个 log4j.properties 日志配置文件。
    <5> 删除掉 $CATALINA_HOME/conf/ 目录下的 logging.properties 文件防止 java.util.logging 生成 0 字节大小的日志文件。
    <6>重启 Tomcat 。

Tomcat日志文件:

  • Host manager(主机管理)日志:针对主机管理相关配置的日志。
  • manager(应用管理)日志:针对应用管理相关配置的日志。
  • catalina(引擎)日志:tomcat自己运行的一些日志。
  • localhost_access_log(访问)日志:存放访问tomcat的请求的所有地址以及请求的路径、时间,请求协议以及返回码等信息。
  • localhost.log日志:应用初始化未处理的异常最后被tomcat捕获而输出的日志。
  • commons-daemon.log(守护)日志:这个日期是利用服务方式启动tomcat作为守护进程的日志记录,因为我的tomcat启动方式是以服务的方式启动的,索引产生这个日志文件记录了服务的启动状态。
  • catalina.out:catalina.out其实是tomcat的标准输出(stdout)和标准出错(stderr),这是在tomcat的启动脚本里指定的。如果没有修改的话stdout和stderr会重定向到这里。所以我们在应用里使用System.out打印的东西都会到这里来。
    tomcat7-stderr.log(错误)日志:这个是tomcat的标准错误日志。
    tomcat7-stdout.log(输出)日志:这个是tomcat的标准输出日志。
    -

关于cataliana.{yyyy-MM-dd}.log和localhost.{yyyy-MM-dd}.log:

  • 这两个日志都是通过logging.properties配置的(默认情况下,启动脚本里指定了java.util.logging.config.file和java.util.logging.manager两个变量)。一个典型的logging.properties可能如下所示:
handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler
.handlers = 1catalina.org.apache.juli.FileHandler, java.util.logging.ConsoleHandler

1catalina.org.apache.juli.FileHandler.level = INFO
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.prefix = catalina.

2localhost.org.apache.juli.FileHandler.level = FINE
2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
2localhost.org.apache.juli.FileHandler.prefix = localhost.

java.util.logging.ConsoleHandler.level = INFO
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter

org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
  • 这个文件大致的意思是,root输出到catalina和console。而这里的catalina按照配置对应的是catalina.{yyyy-MM-dd}.log,这里的console最终会输出到catalina.out。这就是我们看到catalina.{yyyy-MM-dd}.log和catalina.out的日志很多都是一样的原因。
  • 配置文件中还有一个localhost,所有logname或parent logname为org.apache.catalina.core.ContainerBase.[Catalina].[localhost]的都会输出到localhost.{yyyy-MM-dd}.log文件。而这个logname又代表着什么呢?在tomcat中有一个server.xml的配置文件,其中有这么一个片段:
<Engine name="Catalina" defaultHost="localhost">
  <Host name="localhost"  appBase="webapps"
        unpackWARs="false" autoDeploy="false">
  </Host>
</Engine>
  • 我们可以这么简单的理解: 一个Tomcat进程对应着一个Engine,一个Engine下可以有多个Host(Virtual Host),一个Host里可以有多个Context,比如我们常常将应用部署在ROOT下还是webapps里其他目录,这个就是Context。
    ①这其中Engine对应着tomcat里的StandardEngine类,Host对应着StandardHost类,而Context对应着StandardContext。这几个类都是从ContainerBase派生。这些类里打的一些跟应用代码相关的日志都是使用ContainerBase里的getLogger,而这个这个logger的logger name就是: org.apache.catalina.core.ContainerBase.[current container name].[current container name]…
    ②而我们一个webapp里listener, filter, servlet的初始化就是在StandardContext里进行的,比如ROOT里有一个listener初始化出异常了,打印日志则logger name是org.apache.catalina.core.ContainerBase.[Catalina].[localhost].[/]。
    这其中Catalina和localhost是上面xml片段里的Engine和Host的name,而[/]是ROOT对应的StandardContext的name。所以listener, filter, servlet初始化时的日志是需要看localhost.{yyyy-MM-dd}.log这个日志的。
    ④比如现在我们使用Spring,Spring的初始化我们往往是使用Spring提供的一个listener进行的,而如果Spring初始化时因为某个bean初始化失败,导致整个应用没有启动,这个时候的异常日志是输出到localhost中的,而不是cataina.out中。
    所以有的时候我们应用无法启动了,然后找catalina.out日志,但最后也没有定位根本原因是什么,就是因为我们找的日志不对。
    但有的时候catalina.out里也有我们想要的日志,那是因为我们的应用或使用的一些组件自己捕获了异常,然后将其打印了,这个时候如果恰好这些日志被我们配置成输出到console,则这些日志也会在catalina.out里出现了。

Tomcat日志总结:

  • catalina.out:即标准输出和标准出错,所有输出到这两个位置的都会进入catalina.out,这里包含tomcat运行自己输出的日志以及应用里向console输出的日志。
  • catalina.{yyyy-MM-dd}.log:是tomcat自己运行的一些日志,这些日志还会输出到catalina.out,但是应用向console输出的日志不会输出到catalina.{yyyy-MM-dd}.log。
  • localhost.{yyyy-MM-dd}.log:主要是应用初始化(listener, filter,servlet)未处理的异常最后被tomcat捕获而输出的日志,而这些未处理异常最终会导致应用无法启动。
  • 链接:tomcat中的几种log

Tomcat日志乱码问题:

  • 昨天本来准备更新一下Tomcat版本,但是发现新版本的日志打印中文会出现乱码(Tomcat自身打印的日志),不管是使用bat脚本启动还是在Idea中启动,都是乱码。研究了一个晚上,百度上的那些方式都试遍了,都是设置各种JVM启动参数,发现并没有卵用。
  • 在使用bat文件启动Tomcat时,Tomcat目录下的logs文件夹会生成相应的日志文件,发现旧版本生成的日志文件编码是GBK,而Windows控制台的编码也是GBK,所以不会乱码。而新版本生成的日志文件编码是UTF-8,所以就造成了中文乱码问题。
  • 定位到问题以后,就去看Tomcat的日志配置文件,tomcat/conf/logging.properties这个文件就是tomcat的日志配置文件,通过使用BCompare对新老版本的配置文件进行对比,发现tomcat在新版的日志配置文件中加了指定编码为UTF-8的配置。这就是乱码的根源了。
    在这里插入图片描述

Tomcat三种运行模式

Connector详解:

  • 对tomcat来说,每一个进来的请求(request)都需要一个线程,直到该请求结束。如果同时进来的请求多于当前可用的请求处理线程数,额外的线程就会被创建,直到到达配置的最大线程数(maxThreads属性值)
  • 如果仍就同时接收到更多请求,这些来不及处理的请求就会在Connector创建的ServerSocket中堆积起来,直到到达最大的配置值(acceptCount属性值)
  • 至此,任何再来的请求将会收到connectionrefused错误,直到有可用的资源来处理它们。
  • 链接:
    详解Tomcat三种运行模式(BIO, NIO, APR)
    Connector 详解
  • 在tomcat配置文件server.xml中的配置中,和连接数相关的参数有:
minProcessors:最小空闲连接线程数,用于提高系统处理性能,默认值为10
maxProcessors:最大连接线程数,即:并发处理的最大请求数,默认值为75
acceptCount:允许的最大连接数,应大于等于maxProcessors,默认值为100
enableLookups:是否反查域名,取值为:true或false。为了提高处理能力,应设置为false
connectionTimeout:网络连接超时,单位:毫秒。设置为0表示永不超时,这样设置有隐患的。通常可设置为30000毫秒。
其中和最大连接数相关的参数为maxProcessors和acceptCount。如果要加大并发连接数,应同时加大这两个参数。

tomcat的http connector有三种bio、nio、apr:

  • bio:没经过任何优化和处理,几百并发性能极低下。
    同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。
    ②server.xml
<Connector port="8080" protocol="HTTP/1.1" 
 connectionTimeout="20000" 
 redirectPort="8443"  
URIEncoding="UTF-8"/> 
  • nio:利用java的异步io技术,no blocking IO技术.
    同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。
    ②server.xml
<Connector port="8080" protocol="org.apache.coyote.http11.Http11NioProtocol" 
 connectionTimeout="20000" 
 redirectPort="8443"  
URIEncoding="UTF-8"/> 

在这里插入图片描述

  • apr模式:安装最困难,操作系统级别的控制,但也是在Tomcat上运行高并发应用的首选模式。
    apr也叫aio,异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理
    ②配置apr模式之后还需要安装 apr 、 apr-utils 、tomcat-native包
    ③server.xml
<Connector port="8080" protocol="org.apache.coyote.http11.Http11AprProtocol" 
 connectionTimeout="20000" 
 redirectPort="8443"  
URIEncoding="UTF-8"/> 

BIO、NIO、AIO(也叫APR)适用场景分析:

  • BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。
  • NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。
  • AIO(也叫APR)方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

这三种模式的不同之处如下:

  • BIO:一个线程处理一个请求。缺点:并发量高时,线程数较多,浪费资源。
    Tomcat7或以下,在Linux系统中默认使用这种方式。
  • NIO: 利用Java的异步IO处理,可以通过少量的线程处理大量的请求。
    Tomcat8在Linux系统中默认使用这种方式。
  • APR: 即Apache Portable Runtime,从操作系统层面解决io阻塞问题。
    Tomcat7或Tomcat8在Win7或以上的系统中启动默认使用这种方式。

Web工程目录介绍

在这里插入图片描述

tomcat和配置环境变量

tomcat是否有必要配置环境变量?
tomcat是否有必要配置环境变量?

  • 用文本编辑工具打开用于启动Tomcat的批处理文件startup.bat,仔细阅读。在这个文件中,首先判断CATALINA_HOME环境变量是否为空,如果为空,就将当前目录设为CATALINA_HOME的值。
  • 接着判断当前目录下是否存在bin\catalina.bat,如果文件不存在,将当前目录的父目录设为CATALINA_HOME的值。
  • 根据机器上Tomcat安装目录的层次结构,最后CATALINA_HOME的值被设为Tomcat的安装目录。如果环境变量CATALINA_HOME已经存在,则通过这个环境变量调用bin目录下的“catalina.bat start”命令。
  • 通过这段分析,我们了解到两个信息,一是Tomcat启动时,需要查找CATALINA_HOME这个环境变量,如果在Tomcat的bin目录下调用startup.bat,Tomcat会自动并正确设置CATALINA_HOME;
  • 二是执行startup.bat命令,实际上执行的是“catalina.bat start”命令。
  • 如果我们不是在Tomcat的bin目录作为当前目录时调用startup.bat,就会出现如下图所示的错误信息(在bin目录的父目录下调用除外)。
    在这里插入图片描述
  • 如果要想在任意目录下都能启动Tomcat,就需要设置CATALINA_HOME环境变量,你可以将CATALINA_HOME添加到WindowsXP系统的环境变量中,其值就是Tomcat的安装目录。

JMX在Tomcat的应用

JMX 简单介绍:

  • Tomcat 从 5.0 版本开始引入 JMX,力图使 JMX 成为 Tomcat 未来版本的管理工具和平台。首先,让我们来对 JMX做一个简单了解。 JMX 是 Java Management Extension 的缩写,可译为 Java 管理工具扩展,扩展的意思就是JMX 不包含在标准的 J2SE 中,我们必须要另外下载 JMX RI 的实现。不过,这种把 JMX 排除在 J2SE之外的情况已经成为历史了, J2SE5.0 和 J2SE6.0 都已经包含了 JMX 的标准实现。这说明, JMX 已经成为 J2SE不可分割的一部分,另外一方面, JMX 已经成为 Java 平台上管理工具的事实标准,在业界广泛使用。例如, JBOSS 就是以 JMX为微内核, Web 应用模块和其它功能模块都可热插拨到这个微内核,将 JMX 的管理功能发挥得淋漓尽致。从当前业界使用情况看, JMX中的 X(Extension ,扩展 ) 应该去掉,改名为 Java Management Standard Platform (JMSP, Java 管理标准平台 ) 更加合适。为了向下兼容,我们姑且还是称之为 JMX 吧。
  • JMX 要管理的对象是什么呢,是资源。什么是资源,资源是指企业中的的各种应用软件和平台,举例来说,一个公司内部可能有许多应用服务器、若干Web 服务器、一台至多台的数据库服务器及文件服务器等等,那么,如果我们想监视数据库服务器的内存使用情况,或者我们想更改应用服务器上JDBC 最大连接池的数目,但我们又不想重启数据库和应用服务器,这就是典型意义上的资源管理,即对我们的资源进行监视 (Monitoring,查看 ) 和管理 (Management ,更改 ) ,这种监视和更改不妨碍当前资源的正常运行。
  • 对资源进行适当的监测和管理,可以让我们的 IT 资源尽可能的平稳运行,可以为我们的客户提供真正意思上的 24 × 7服务。在资源耗尽或者在硬件出故障之前,我们就可以通过管理工具监测到,并通过管理工具进行热调整和插拔。独孤九剑,料敌机先,适当的资源管理就是我们料敌机先的工具,可以让我们立于 IT 服务的不败之地。在 Sun 公司提出 JMX(JSR174) 以前,人们通常都是使用 SNMP 对网络上的资源进行管理。 SNMP的主要问题是入门门槛太高,不容易使用。所以 Sun 提出了 JSR174 倡议并且提供了一套 JMX 的参考实现。
  • 从技术上说, JMX 整体架构可分为三层,即资源植入层(Instrumentation Level ,可能有更好的译法? ) 、代理层(Agent Level) 和管理层 (Manager Level) ,简述如下:
  • 资源植入层 (Instrumentation Level) :该层包含 MBeans 及这些 MBeans 所管理的资源, MBeans是一个 Java 对象,它必须实现 JMX 规范中规定的接口。按照 JMX 规范,在 MBeans对象的接口中,我们可以指定管理层可以访问资源的哪些属性,可以调用资源的哪些方法,并且,在资源的属性发生变化是,我们的 MBeans可以发出消息,通知对这些属性变化感兴趣的其它对象。 JMX 规范定义了四种 MBeans ,它们分别是标准 MBeans(Standard MBeans) 、动态 MBeans(Dynamic MBeans) 、开放 MBeans(Open MBeans) 和模态MBeans(Model MBeans) 。
  • 代理层 (Agent Level) :代理层的目的就是要把 MBeans 中实现的接口暴露给管理层,该层通常由 MBean Server和 Agent Services 构成, MBean Server 就是一个 MBeans 对象注册器,所有的资源 MBeans都注册到这个 MBean Server ,对象管理器或者其它的管理层应用程序可以通过访问 MBean Server ,从而可以访问MBean Server 中注册的 MBeans ,当然也就可以监视和管理和这些 MBeans 绑定的资源。
  • 管理层 (Manager Level) :又称之为分布式服务层 (Distributed Services),顾名思义,该层主要包含一些管理应用程序,这些程序可以访问和操作 JMX 代理层 (Agent Level) 。这些管理应用程序可以是一个Web 应用,也可能是一个 Java SWT 应用程序。

jar包问题

pom文件:

<!-- serlvet -->
<dependency>  
	<groupId>javax.servlet</groupId>  
	<artifactId>javax.servlet-api</artifactId>  
	<version>3.0.1</version>
	<scope>provided</scope>  
</dependency> 
<!-- https://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
<dependency>
	<groupId>javax.servlet.jsp</groupId>
	<artifactId>jsp-api</artifactId>
	<version>2.2</version>
	<scope>provided</scope>
</dependency>

问题详解:

  • 你如果编写过servlet就知道要用到HttpServletRequest和HttpServletResponse等对象,这些对象都是要靠javax.servlet-api包才能使用的。
    我们在使用servlet对象后需要编译成class文件,若没有jar包则编译不通过,因此需要加上此jar包。
  • 我们在index.jsp写一个表达式:<%=pageContext.request.contextPath%>时,pageContext是属于jsp-api.jar包的。
    我们在使用jsp时一般都是部署到tomcat里使用,即使在本地上报错也不会影响,因此一般来说jsp-api.jar比较少添加。
  • 我们在index.jsp写一个EL表达式:${pageContext.request.contextPath }时不添加EL表达式的依赖也无所谓,因为用Tomcat作为部署容器,Tomcat已经集成了EL,而jsp在构建阶段(mvn clean package)是不会被编译的,所以使用Tomcat作为部署容器时,不需要加入EL表达式的依赖。

问题解决办法:

  • Tomcat的lib目录下都有这些jar包,因此我们需要把他的作用域设置为provided,避免jar包冲突!

在springboot中使用jsp:

  • 需要在pom.xml中加入tomcat-embed-jasper依赖用以编译jsp,因为springboot的内置tomcat去除了tomcat-embed-jasper这个包。
<!-- 用于编译jsp springboot tomcat jsp 支持开启-->
<dependency>
    <groupId>org.apache.tomcat.embed</groupId>
    <artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!--jstl的支持,c标签-->
<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>jstl</artifactId>
    <scope>compile</scope>
</dependency>

Tomcat应用乱码

简述:

  • html页面设置为 utf-8 在页面头部添加<meta>标签:
    在这里插入图片描述
  • tomcat的server.xml配置:
(1) 添加 URIEncoding=“UTF-8”
<Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               redirectPort="8443" URIEncoding="UTF-8" />

(2)
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" URIEncoding="UTF-8"/>
  • 设置 tomcat中 catalina.bat (jvm的编码):
    ①在catalina.bat 中set “JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%” 下面 添加 : -Dfile.encoding=UTF8 -Dsun.jnu.encoding=UTF8
    ②如下所示:
set "JAVA_OPTS=%JAVA_OPTS% %JSSE_OPTS%"
-Dfile.encoding=UTF8 -Dsun.jnu.encoding=UTF8
  • 设置tomcat的 web.xml (我的是108行左右)修改为下面所示:
<servlet>
        <servlet-name>default</servlet-name>
        <servlet-class>org.apache.catalina.servlets.DefaultServlet</servlet-class>
        <init-param>
            <param-name>debug</param-name>
            <param-value>0</param-value>
        </init-param>
        <init-param>
        	<param-name>fileEncoding</param-name>
        	<param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>listings</param-name>
            <param-value>false</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值