Java EE: Tomcat
Tomcat
依赖
1 | <dependency> |
结构介绍
Tomcat是Apache开发的开源Servlet容器其中,
WEB-INF目录是受保护的,客户端无法访问这个目录下的资源,保存应用的信息这个目录下面还有
classes/、lib/以及web.xmlclasses/存放Java程序的编译结果、lib/存放一系列第三方jar包其余应是一系列静态资源,例如
js/、css/、views/等常见的命名使用
maven管理项目的情况下,lib/不需要手动寻找、配置传统部署:指
Tomcat服务器包含开发者开发的.war包这样的Web应用,Servlet应用开发好后打包成.war包并复制到Tomcat服务器中,然后启动服务器传统部署中,
classes/与lib/由Tomcat解包.war文件得到内嵌
tomcat:指Tomcat API作为java程序的一部分而存在,若使用maven的情况下调用Tomcat实例的addWebapp()方法,实例会从指定的路径中找到WEB-INF/web.xml文件并解析,然后生成classes/与lib/等在target/下
web.xml映射
这是一种比较传统的映射方式,仅了解即可
web.xml应位于webapp/WEB-INF目录下,其中webapp为自定义的网页应用的名字,web.xml里的所有的配置会覆盖注解形式的映射声明为
webapp:1
2
3
4
5
6<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" id="WebApp_ID" version="4.0">
</web-app>声明一个
Servlet:1
2
3
4<servlet>
<servlet-name>Servlet_name</servlet-name>
<servlet-class>类路径</servlet-class>
</servlet>将
Servlet映射到某个路径上:1
2
3
4<servlet-mapping>
<servlet-name>Servlet_name</servlet-name>
<url-pattern>/路径</url-pattern>
</servlet-mapping>初始化某个
Servlet或某个Filter的参数(ServletConfig):1
2
3
4<init-param>
<param-name>param_name</param-name>
<param-value>xml文件、字符串等</param-value>
</init-param>设置
ServletContext的配置:1
2
3
4<context-param>
<param-name>name</param-name>
<param-value>value</param-value>
</context-param>设置欢迎文件:
1
2
3<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>设置
session的生效时间1
2
3<session-config>
<session-timeout>30</session-timeout>
</session-config>
注解映射
@WebServlet注解:在Servlet 3.0前,需要在web.xml中配置大量信息,在WebServlet注解出现后,所有的配置被分散到各个服务类上,最重要且必要的属性是urlPatterns,是String集合,表示这些URI均映射到这个Servlet类上在传统部署时,它们的解析是全自动的
内嵌Tomcat
内嵌部署
Tomcat显得更加灵活,由开发者完全控制Tomcat的配置,但因此注解映射、静态资源需要由开发者亲自解析、引入,因此在不借用Spring boot框架的情况下,直接配置web.xml并调用addWebapp()或手动通过Tomcat对象注册服务以及配置映射是更常用的可以理解为:通过
web.xml配置的底层实现就是让addWebapp()解析该xml文件,并间接地在内部调用addServlet()、addMapping()等方法由
new Tomcat()直接构造一个Tomcat实例,调用start()启动该服务器(会抛出LifecycleException受检异常),调用getServer().await()使该服务器不断地等待请求Tomcat实例方法:setHostname(String):设置服务器地址setPort(int):设置服务器端口setBaseDir(String):设置基准目录,表示Tomcat实例工作时,临时文件等存放的根目录,这里的临时文件不是classes/与lib/等,而是运行时生成的文件,例如jsp翻译后生成的文件推荐设置为
target/下的某个目录getConnector():获取其绑定的连接器,这个方法在首次调用时会进行一系列的初始化操作,包括应用在此前设置的baseDir等参数这个方法应尽量晚些调用
Context addWebapp(String contextPath, String docBase):添加Web应用并获取它的上下文实例contextPath指上下文的根所映射的URL路径,例如传入""则该上下文会映射到"/"docBase指要引入的资源的本地路径,提供的路径下必须含有WEB-INF目录及web.xml文件等价于将整个
Web应用加载到服务器上,使用addWebapp()会自动生成并注册一个默认的Servlet服务,当客户端访问那些在用户自定义Servlet服务中找不到的服务时,会转向这个默认服务默认服务会试图在
docBase下的静态资源中查询是否有对应的资源,若找到则返回,否则返回404响应Context addContext(String contextPath, String docBase):添加一个空白的上下文实例,参数意义同上addServlet(String contextPath, String servletName, Servlet serv):登记一个名为servletName的微服务,对应到路径为contextPath的上下文有静态方法的版本,其中
contextPath应替换为Context对象同时需要使用
Context实例的addServletMappingDecoded(String pattern, String name)将微服务映射到URL的某个路径上这两步等价于在
web.xml中声明Servlet服务和映射该方法返回的
Wrapper对象可链式调用addMapping(String pattern),它等价于使用Context实例的addServletMappingDecoded()方法
上下文类
Context抽象的是整个Web容器,和ServletContext不同,一般作用于容器启动前,而后者作用于Web应用运行中处理业务,Context常用的实例方法有:addWelcomeFile(String):设置当客户端访问根路径时,返回的资源文件即将
String指向的资源文件映射到"/"addServletMappingDecoded(String pattern, String name):将微服务映射到某个URL上addFilterDef(FilterDef):登记一个Filter,由FilterDef封装其信息FilterDef常用方法:setFilter(Filter)、setFilterName(String)、addInitParameter(String, Object)分别为登记
Filter对象、登记Filter服务名、初始化Filter参数addFilterMap(FilterMap):登记从Filter到URL的映射,由FilterMap封装映射信息FilterMap常用方法:addURLPatternDecoded(String)、addServletName(String)、setFilterName(String)分别为登记其应用的
URL、登记其应用的Servlet、设置其绑定的Filter服务名
例子
基本配置:
1
2
3
4
5
6
7
8
9
10
11
12Tomcat tomcat = new Tomcat();
tomcat.setHostname("localhost");
tomcat.setPort(8080);
tomcat.setBaseDir("/target/tomcat/");
//
// ...其它配置...
//
tomcat.getConnector();
tomcat.init();
tomcat.start();
tomcat.getServer().await();Servlet等配置:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24String contextPath = "/api";
// String docBase = new File("/src/main/webapp").getAbsolutePath();
String docBase = Path.of("/src/main/webapp").toAbsolutePath().toString();
Context context = tomcat.addContext(contextPath, docBase);
String servletName = "ServletDemo";
tomcat.addServlet(contextPath, servletName, new ServletDemo()).addMapping("/*");
// context.addServletMappingDecoded("/*", servletName);
FilterDef filterDef = new FilterDef();
filterDef.setFilter((req, resp, chain) -> {
// 过滤 ...
// 链式处理
chain.doFilter(req, resp);
});
filterDef.setFilterName("FilterDemo");
FilterMap filterMap = new FilterMap();
filterMap.addURLPatternDecoded("/*");
filterMap.addServletName(servletName);
filterMap.setFilterName("FilterDemo");
context.addFilterDef(filterDef);
context.addFilterMap(filterMap);上述配置与以下配置是近乎等价的,只是以下配置会有多出一个默认的
Servlet服务,用于检索静态资源1
tomcat.addWebapp("/api", "src/main/webapp/");
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30<!-- web.xml -->
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
id="WebApp_ID" version="4.0">
<servlet>
<servlet-name>ServletDemo</servlet-name>
<servlet-class>demo.servlet.ServletDemo</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<filter>
<filter-name>FilterDemo</filter-name>
<filter-class>无法用lambda表达式声明的接口实现</filter-class>
</filter>
<filter-mapping>
<filter-name>FilterDemo</filter-name>
<!-- 针对/*这个URL路径设置Filter -->
<url-pattern>/*</url-pattern>
<!-- 针对ServletDemo这个服务单独设置Filter -->
<servlet-name>ServletDemo</servlet-name>
</filter-mapping>
</web-app>