提示: 本材料只做个人学习参考,不作为系统的学习流程,请注意识别!!!
《Tomcat 进阶 二》
《Tomcat 进阶二》3.Jasper
3.1 Jasper 简介3.2 JSP 编译方式
3.2.1 运行时编译
3.2.1.1 编译过程3.2.1.2 编译结果 3.2.2 预编译 3.3 JSP编译原理
3.3.1 代码分析3.3.2 编译流程 4.Tomcat 服务器配置
4.1 server.xml
4.1.1 Server4.1.2 Service4.1.3 Executor4.1.4 Connector4.1.5 Engine4.1.6 Host4.1.7 Context Context 4.2 tomcat-users.xml 5.Web 应用配置
5.1 ServletContext 初始化参数5.2 会话配置5.3 Servlet配置5.4 Listener配置5.5 Filter配置5.6 欢迎页面配置5.7 错误页面配置 6.Tomcat 管理配置
6.1 host-manager6.2 manager
3.Jasper 3.1 Jasper 简介
对于基于JSP 的web应用来说,我们可以直接在JSP页面中编写 Java代码,添加第三方的标签库,以及使用EL表达式。但是无论经过何种形式的处理,最终输出到客户端的都是标准的HTML页面(包含js ,css…),并不包含任何的java相关的语法。 也就是说, 我 们可以把jsp看做是一种运行在服务端的脚本。 那么服务器是如何将 JSP页面转换为 HTML页面的呢?
Jasper模块是Tomcat的JSP核心引擎,我们知道JSP本质上是一个Servlet。Tomcat使用 Jasper对JSP语法进行解析,生成Servlet并生成Class字节码,用户在进行访问jsp时,会访问Servlet,最终将访问的结果直接响应在浏览器端 。另外,在运行的时候,Jasper还会检测JSP文件是否修改,如果修改,则会重新编译JSP文件。
3.2 JSP 编译方式 3.2.1 运行时编译Tomcat 并不会在启动Web应用的时候自动编译JSP文件, 而是在客户端第一次请求时, 才编译需要访问的JSP文件。
创建一个web项目, 并编写JSP代码 :
<%@ page import="java.text.DateFormat" %> <%@ page import="java.text.SimpleDateFormat" %> <%@ page import="java.util.Date" %> <%@ page contentType="text/html;charset=UTF‐8" language="java" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>3.2.1.1 编译过程$Title$ <%DateFormat dateFormat = new SimpleDateFormat("yyyy‐MM‐dd HH:mm:ss"); String format = dateFormat.format(new Date()); %> Hello , Java Server Page 。。。。
<%= format %>
Tomcat 在默认的web.xml 中配置了一个org.apache.jasper.servlet.JspServlet,用于处理所有的.jsp 或 .jspx 结尾的请求,该Servlet 实现即是运行时编译的入口。
JspServlet 处理流程图:
1) 如果在 tomcat/conf/web.xml 中配置了参数scratchdir , 则jsp编译后的结果,就会存储在该目录下 。
2) 如果没有配置该选项, 则会将编译后的结果,存储在Tomcat安装目录下的 work/Catalina(Engine名称)/localhost(Host名称)/Context名称 。 假设项目名称为 jsp_demo_01。
3) 如果使用的是 IDEA 开发工具集成Tomcat 访问web工程中的jsp , 编译后的结果, 存放在 :
除了运行时编译,我们还可以直接在Web应用启动时, 一次性将Web应用中的所有的JSP 页面一次性编译完成。在这种情况下,Web应用运行过程中,便可以不必再进行实时编 译,而是直接调用JSP页面对应的Servlet 完成请求处理, 从而提升系统性能。 Tomcat 提供了一个Shell程序JspC,用于支持JSP预编译,而且在Tomcat的安装目录下提供了一个 catalina-tasks.xml 文件声明了Tomcat 支持的Ant任务, 因此,我们很容易使用 Ant 来执行JSP 预编译 。(要想使用这种方式,必须得确保在此之前已经下载并安装 了Apache Ant)。
3.3 JSP编译原理 3.3.1 代码分析编译后的.class 字节码文件及源码 :
由编译后的源码解读, 可以分析出以下几点 :
1) 其类名为 index_jsp , 继承自 org.apache.jasper.runtime.HttpJspbase , 该类是 HttpServlet 的子类 , 所以jsp 本质就是一个Servlet 。
2) 通过属性 _jspx_dependants 保存了当前JSP页面依赖的资源, 包含引入的外部的JSP 页面、导入的标签、标签所在的jar包等,便于后续处理过程中使用(如重新编译检测, 因此它以Map形式保存了每个资源的上次修改时间)。
3) 通过属性 _jspx_imports_packages 存放导入的 java 包, 默认导入 javax.servlet , javax.servlet.http, javax.servlet.jsp 。
4) 通过属性 _jspx_imports_classes 存放导入的类, 通过import 指令导入的 DateFormat 、SimpleDateFormat 、Date 都会包含在该集合中。 _jspx_imports_packages 和 _jspx_imports_classes 属性主要用于配置 EL 引擎上下文 。
5) 请求处理由方法 _jspService 完成 , 而在父类 HttpJspbase 中的service 方法通过模 板方法模式 , 调用了子类的 _jspService 方法。
6) _jspService 方法中定义了几个重要的局部变量 : pageContext 、Session、 application、config、out、page。由于整个页面的输出有 _jspService 方法完成,因此 这些变量和参数会对整个JSP页面生效。 这也是我们为什么可以在JSP页面使用这些变量 的原因。
7) 指定文档类型的指令 (page) 最终转换为 response.setContentType() 方法调用。
8) 对于每一行的静态内容(HTML) , 调用 out.write 输出。
9) 对于 <% … %> 中的java 代码 , 将直接转换为 Servlet 类中的代码。 如果在 Java 代码中嵌入了静态文件, 则同样调用 out.write 输出。
3.3.2 编译流程JSP 编译过程如下:
Compiler 编译工作主要包含代码生成和编译两部分 :
代码生成
1) Compiler 通过一个 PageInfo 对象保存JSP 页面编译过程中的各种配置,这些配置可能来源于 Web 应用初始化参数, 也可能来源于JSP页面的指令配置(如 page , include)。
2) 调用ParserController 解析指令节点, 验证其是否合法,同时将配置信息保存到 PageInfo 中, 用于控制代码生成。
3) 调用ParserController 解析整个页面, 由于 JSP 是逐行解析, 所以对于每一行会创建一个具体的Node 对象。如 静态文本(TemplateText)、Java代码(scriptlet)、定制标签(CustomTag)、Include指令(IncludeDirective)。
4) 验证除指令外其他所有节点的合法性, 如 脚本、定制标签、EL表达式等。
5) 收集除指令外其他节点的页面配置信息。
6) 编译并加载当前 JSP 页面依赖的标签
7) 对于JSP页面的EL表达式,生成对应的映射函数。
8) 生成JSP页面对应的Servlet 类源代码
编译
代码生成完成后, Compiler 还会生成 SMAP 信息。 如果配置生成 SMAP 信息, Compiler 则会在编译阶段将SMAP 信息写到class 文件中 。
在编译阶段, Compiler 的两个实现 AntCompiler 和 JDTCompiler 分别调用先关框架的 API 进行源代码编译。
对于 AntCompiler 来说, 构造一个 Ant 的javac 的任务完成编译。
对于 JDTCompiler 来说, 调用 org.eclipse.jdt.internal.compiler.Compiler 完成编译。
4.Tomcat 服务器配置Tomcat 服务器的配置主要集中于 tomcat/conf 下的 catalina.policy、 catalina.properties、context.xml、server.xml、tomcat-users.xml、web.xml 文件。
4.1 server.xmlserver.xml 是tomcat 服务器的核心配置文件,包含了Tomcat的 Servlet 容器 (Catalina)的所有配置。由于配置的属性特别多,我们在这里主要讲解其中的一部分重要配置。
4.1.1 ServerServer是server.xml的根元素,用于创建一个Server实例,默认使用的实现类是 org.apache.catalina.core.StandardServer。
port : Tomcat 监听的关闭服务器的端口。
shutdown: 关闭服务器的指令字符串。
Server内嵌的子元素为 Listener、GlobalNamingResources、Service。
默认配置的5个Listener 的含义:
GlobalNamingResources 中定义了全局命名服务:
4.1.2 Service
该元素用于创建 Service 实例,默认使用 org.apache.catalina.core.StandardService。 默认情况下,Tomcat 仅指定了Service 的名称, 值为 “Catalina”。Service 可以内嵌的元素为 : Listener、Executor、Connector、Engine,其中 : Listener 用于为Service 添加生命周期监听器, Executor 用于配置Service 共享线程池,Connector 用于配置 Service 包含的链接器, Engine 用于配置Service中链接器对应的Servlet 容器引擎。
...
一个Server服务器,可以包含多个Service服务。
4.1.3 Executor默认情况下,Service 并未添加共享线程池配置。 如果我们想添加一个线程池, 可以在下添加如下配置:
属性说明:
| 属性 | 含义 |
|---|---|
| name | 线程池名称,用于 Connector中指定。 |
| namePrefix | 所创建的每个线程的名称前缀,一个单独的线程名称为 namePrefix+threadNumber。 |
| maxThreads | 池中最大线程数。 |
| minSpareThreads | 活跃线程数,也就是核心池线程数,这些线程不会被销毁,会一直存在。 |
| maxIdleTime | 线程空闲时间,超过该时间后,空闲线程会被销毁,默认值为6000(1分钟),单位毫秒。 |
| maxQueueSize | 在被执行前最大线程排队数目,默认为Int的最大值,也就是广义的无限。除非特殊情况,这个值不需要更改, 否则会有请求不会被处理的情况发生。 |
| prestartminSpareThreads | 启动线程池时是否启动 minSpareThreads部分线程。 默认值为false,即不启动。 |
| threadPriority | 线程池中线程优先级,默认值为5,值从1到10。 |
| className | 线程池实现类,未指定情况下,默认实现类为 org.apache.catalina.core.StandardThreadExecutor。 如果想使用自定义线程池首先需要实现 org.apache.catalina.Executor接口。 |
如果不配置共享线程池,那么Catalina 各组件在用到线程池时会独立创建。
Connector 用于创建链接器实例。默认情况下,server.xml 配置了两个链接器,一个支持HTTP协议,一个支持AJP协议。因此大多数情况下,我们并不需要新增链接器配置, 只是根据需要对已有链接器进行优化。
属性说明:
1) port: 端口号,Connector 用于创建服务端Socket 并进行监听, 以等待客户端请求链接。如果该属性设置为0,Tomcat将会随机选择一个可用的端口号给当前Connector 使用。
2) protocol : 当前Connector 支持的访问协议。 默认为 HTTP/1.1 , 并采用自动切换机制选择一个基于 JAVA NIO 的链接器或者基于本地APR的链接器(根据本地是否含有 Tomcat的本地库判定)。 如果不希望采用上述自动切换的机制, 而是明确指定协议, 可以使用以下值。
Http协议:
org.apache.coyote.http11.Http11NioProtocol , 非阻塞式 Java NIO 链接器 org.apache.coyote.http11.Http11Nio2Protocol , 非阻塞式 JAVA NIO2 链接器 org.apache.coyote.http11.Http11AprProtocol , APR 链接器
AJP协议 :
org.apache.coyote.ajp.AjpNioProtocol , 非阻塞式 Java NIO 链接器 org.apache.coyote.ajp.AjpNio2Protocol ,非阻塞式 JAVA NIO2 链接器 org.apache.coyote.ajp.AjpAprProtocol , APR 链接器
3) connectionTimeOut : Connector 接收链接后的等待超时时间, 单位为毫秒。 -1 表示不超时。
4) redirectPort:当前Connector 不支持SSL请求, 接收到了一个请求, 并且也符合 security-constraint 约束, 需要SSL传输,Catalina自动将请求重定向到指定的端口。
5) executor : 指定共享线程池的名称, 也可以通过maxThreads、minSpareThreads 等属性配置内部线程池。
6) URIEncoding : 用于指定编码URI的字符编码, Tomcat8.x版本默认的编码为 UTF-8 , Tomcat7.x版本默认为ISO-8859-1。 完整的配置如下:
4.1.5 Engine
Engine 作为Servlet 引擎的顶级元素,内部可以嵌入: Cluster、Listener、Realm、 Valve和Host。
...
属性说明:
1) name: 用于指定Engine 的名称, 默认为Catalina 。该名称会影响一部分Tomcat的 存储路径(如临时文件)。
2) defaultHost : 默认使用的虚拟主机名称, 当客户端请求指向的主机无效时, 将交 由默认的虚拟主机处理, 默认为localhost。
4.1.6 HostHost 元素用于配置一个虚拟主机, 它支持以下嵌入元素:Alias、Cluster、Listener、 Valve、Realm、Context。如果在Engine下配置Realm, 那么此配置将在当前Engine下的所有Host中共享。 同样,如果在Host中配置Realm , 则在当前Host下的所有Context 中共享。Context中的Realm优先级 > Host 的Realm优先级 > Engine中的Realm优先级。
...
属性说明:
1) name: 当前Host通用的网络名称, 必须与DNS服务器上的注册信息一致。 Engine中 包含的Host必须存在一个名称与Engine的defaultHost设置一致。
2) appbase: 当前Host的应用基础目录, 当前Host上部署的Web应用均在该目录下 (可以是绝对目录,相对路径)。默认为webapps。
3) unpackWARs: 设置为true, Host在启动时会将appbase目录下war包解压为目录。设置为false, Host将直接从war文件启动。
4) autoDeploy: 控制tomcat是否在运行时定期检测并自动部署新增或变更的web应用。
通过给Host添加别名,我们可以实现同一个Host拥有多个网络名称,配置如下:
www.web2.com
这个时候,我们就可以通过两个域名访问当前Host下的应用(需要确保DNS或hosts中添 加了域名的映射配置)。
4.1.7 Context Context用于配置一个Web应用,默认的配置如下:
....
属性描述:
1) docbase:Web应用目录或者War包的部署路径。可以是绝对路径,也可以是相对于 Host appbase的相对路径。
2) path:Web应用的Context 路径。如果我们Host名为localhost, 则该web应用访问 的根路径为: http://localhost:8080/myApp。
它支持的内嵌元素为:cookieProcessor, Loader, Manager,Realm,Resources, WatchedResource,JarScanner,Valve。
4.2 tomcat-users.xml
该配置文件中,主要配置的是Tomcat的用户,角色等信息,用来控制Tomcat中 manager, host-manager的访问权限。
5.Web 应用配置web.xml 是web应用的描述文件, 它支持的元素及属性来自于Servlet 规范定义 。 在 Tomcat 中, Web 应用的描述信息包括 tomcat/conf/web.xml 中默认配置以及 Web 应用 WEB-INF/web.xml 下的定制配置。
我们可以通过 添加ServletContext 初始化参数,它配置了一个键值对,这样我们可以在应用程序中使用 javax.servlet.ServletContext.getInitParameter()方法获取参数。
5.2 会话配置contextConfigLocation classpath:applicationContext‐*.xml Spring Config File Location
用于配置Web应用会话,包括超时时间、cookie配置以及会话追踪模式。它将覆盖 server.xml 和 context.xml 中的配置。
30 JESSIONID www.itcast.cn / Session cookie true false 3600 cookie
配置解析:
5.3 Servlet配置session‐timeout : 会话超时时间,单位分钟cookie‐config: 用于配置会话追踪cookie
name:cookie的名称
domain:cookie的域名
path:cookie的路径
comment:注释
http‐only:cookie只能通过HTTP方式进行访问,JS无法读取或修改,此项可以增 加网站访问的安全性。
secure:此cookie只能通过HTTPS连接传递到服务器,而HTTP 连接则不会传递该 信息。注意是从浏览器传递到服务器,服务器端的cookie对象不受此项影响。
max‐age:以秒为单位表示cookie的生存期,默认为‐1表示是会话cookie,浏览器 关闭时就会消失。tracking‐mode :用于配置会话追踪模式,Servlet3.0版本中支持的追踪模式: cookie、URL、SSL
A. cookie : 通过HTTP cookie 追踪会话是最常用的会话追踪机制, 而且 Servlet规范也要求所有的Servlet规范都需要支持cookie追踪。
B. URL : URL重写是最基本的会话追踪机制。当客户端不支持cookie时,可以采 用URL重写的方式。当采用URL追踪模式时,请求路径需要包含会话标识信息,Servlet容器 会根据路径中的会话标识设置请求的会话信息。如: http://www.myserver.com/user/index.html;jessionid=1234567890。
C. SSL : 对于SSL请求, 通过SSL会话标识确定请求会话标识。
Servlet 的配置主要是两部分, servlet 和 servlet-mapping :
myServlet cn.itcast.web.MyServlet fileName init.conf 1 true myServlet *.do /myservet/*
配置说明:
1) servlet‐name : 指定servlet的名称, 该属性在web.xml中唯一。
2) servlet‐class : 用于指定servlet类名
3) init‐param: 用于指定servlet的初始化参数, 在应用中可以通过 HttpServlet.getInitParameter 获取。
4) load‐on‐startup: 用于控制在Web应用启动时,Servlet的加载顺序。 值小于0, web应用启动时,不加载该servlet, 第一次访问时加载。
5) enabled: true , false 。 若为false ,表示Servlet不处理任何请求。
6) url‐pattern: 用于指定URL表达式,一个 servlet‐mapping可以同时配置多个 url‐ pattern。
Servlet 中文件上传配置:
uploadServlet cn.itcast.web.UploadServlet C://path 10485760 10485760 0
配置说明:
5.4 Listener配置1) location:存放生成的文件地址。
2) max‐file‐size:允许上传的文件最大值。 默认值为‐1, 表示没有限制。
3) max‐request‐size:针对该 multi/form‐data 请求的最大数量,默认值为‐1, 表示 无限制。
4) file‐size‐threshold:当数量量大于该值时, 内容会被写入文件。
Listener用于监听servlet中的事件,例如context、request、session对象的创建、修改、删除,并触发响应事件。Listener是观察者模式的实现,在servlet中主要用于对 context、request、session对象的生命周期进行监控。在servlet2.5规范中共定义了8中 Listener。在启动时,ServletContextListener 的执行顺序与web.xml 中的配置顺序一 致, 停止时执行顺序相反。
5.5 Filter配置org.springframework.web.context.ContextLoaderListener
filter 用于配置web应用过滤器, 用来过滤资源请求及响应。 经常用于认证、日志、加 密、数据转换等操作, 配置如下:
myFilter cn.itcast.web.MyFilter true language CN myFilter /*
配置说明:
5.6 欢迎页面配置1) filter‐name: 用于指定过滤器名称,在web.xml中,过滤器名称必须唯一。
2) filter‐class : 过滤器的全限定类名, 该类必须实现Filter接口。
3) async‐supported: 该过滤器是否支持异步
4) init‐param :用于配置Filter的初始化参数, 可以配置多个, 可以通过 FilterConfig.getInitParameter获取
5) url‐pattern: 指定该过滤器需要拦截的URL。
welcome-file-list 用于指定web应用的欢迎文件列表。
index.html index.htm index.jsp
尝试请求的顺序,从上到下。
5.7 错误页面配置error-page 用于配置Web应用访问异常时定向到的页面,支持HTTP响应码和异常类两种形式。
6.Tomcat 管理配置404 /404.html 500 /500.html java.lang.Exception /error.jsp
从早期的Tomcat版本开始,就提供了Web版的管理控制台,他们是两个独立的Web应用,位于webapps目录下。Tomcat 提供的管理应用有用于管理的Host的host-manager 和用于管理Web应用的manager。
6.1 host-managerTomcat启动之后,可以通过 http://localhost:8080/host-manager/html 访问该Web应 用。 host-manager 默认添加了访问权限控制,当打开网址时,需要输入用户名和密码 (conf/tomcat-users.xml中配置) 。所以要想访问该页面,需要在conf/tomcat- users.xml 中配置,并分配对应的角色:
1) admin-gui:用于控制页面访问权限
2) admin-script:用于控制以简单文本的形式进行访问配置如下:
登录:
界面:
manager的访问地址为 http://localhost:8080/manager, 同样, manager也添加了页 面访问控制,因此我们需要为登录用户分配角色为:
界面:



