内嵌 Tomcat 简易教程
编辑
17
2024-05-10
Spring Boot等微服务框架之所以能够独立运行,是因为它们默认内嵌了web服务器。下面通过一个运行Groovy脚本的小项目类来说明内嵌Tomcat的使用方式。
引入相关依赖
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>9.0.50</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-logging-juli</artifactId>
<version>9.0.0.M6</version>
</dependency>
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-annotations-api</artifactId>
<version>9.0.50</version>
</dependency>
</dependencies>
创建 Tomcat 服务
我通过继承的方式对tomcat进行了基本封装,请自行参考。ServerConfig类只是普通的Java类,不做解释,可以参考全参数的构造方法。 Groovlet最终是继承自Servlet接口,对于Tomcat来说,只要实现Servlet就可以传入。这里我创建的是一个Web服务,所以实现了HttpServlet抽象类,用于获取HttpServletRequest和HttpServletResponse。
import lombok.Getter;
import org.apache.catalina.Context;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.startup.Tomcat;
import java.io.File;
import java.util.UUID;
/**
* 用于快速创建执行GroovyServlet的Tomcat容器
* @Author Yahocen
* @Date 2021/7/30 15:27
* @Version 1.0
* @Describe
*/
public class GroovyServer extends Tomcat {
@Getter
private String servletName;
@Getter
private Boolean listeningState;
@Getter
private Groovlet servlet;
public GroovyServer(){
this(ServerConfig.DEFAULT);
}
/**
* @param config
*/
public GroovyServer(ServerConfig config) {
this(config.getBaseDir(),
config.getHostName(),
config.getPort(),
config.getContextPath(),
config.getAppBase(),
config.getDocBase(),
config.getPattern(),
config.getWelcomeFile());
}
/**
* @param basedir 工作目录
* @param hostName 主机名 本机填写:localhost
* @param port 端口号
* @param contextPath 请求根路径 比如 /api 就要使用 http://ip:port/api 来访问
* @param appBase tomcat服务项目目录,推荐:/webapps
* @param docBase 上下文的基础目录,推荐标准目录 /ROOT
* @param pattern 要映射的URL模式 web.xml 中的 url-pattern 例如:xxx.do,推荐默认 /
* @param welcomeFile 默认首页,映射 /
*/
public GroovyServer(String basedir, String hostName, int port, String contextPath, String appBase,
String docBase, String pattern, String welcomeFile){
this.listeningState = false;
//初始化项目目录
File dir = new File(basedir + appBase + docBase);
if(!dir.exists()){
dir.mkdirs();
}
// 设置工作目录
this.setBaseDir(basedir);
// 主机名, 将生成目录: {工作目录}/work/Tomcat/{主机名}/ROOT
this.setHostname(hostName);
this.setPort(port);
// contextPath要使用的上下文映射,""表示根上下文
// docBase上下文的基础目录,用于静态文件。相对于服务器主目录必须存在 ({主目录}/webapps/{docBase})
/*{webapps}/~*/
Host host = getHost();
host.setAppBase(appBase);
Context ctx = this.addContext(contextPath, docBase);
this.servletName = UUID.randomUUID().toString();
//注意此处的
this.servlet = new Groovlet(welcomeFile);
Tomcat.addServlet(ctx, servletName, this.servlet);
ctx.addServletMappingDecoded(pattern, servletName);
}
/**
* 启动服务监听
* @param await 是否等待直到收到正确的关机命令,然后返回。
* @throws LifecycleException
*/
public void start(boolean await) throws LifecycleException {
if(this.listeningState){
return;
}
super.start();
this.listeningState = true;
//Tomcat 9.0 必须调用 Tomcat#getConnector() 方法之后才会监听端口
this.getConnector();
if(!await){
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
//先停止再销毁
this.stop();
this.destroy();
} catch (LifecycleException e) {
e.printStackTrace();
}
}));
}else{
this.await();
}
}
/**
* 停止服务监听
* @throws LifecycleException
*/
@Override
public void stop() throws LifecycleException {
if(this.listeningState){
this.listeningState = false;
super.stop();
}
}
/**
* 销毁服务
* @throws LifecycleException
*/
@Override
public void destroy() throws LifecycleException {
if(this.listeningState){
this.stop();
}
super.destroy();
}
/**
* 等待直到收到正确的关机命令,然后返回。
*/
public void await(){
this.getServer().await();
}
}
- 0
- 0
-
赞助
支付宝微信 -
分享