積極推進科技行業反壟斷,美國 FTC 新主席任命多名高階官員
在上一節中,我們看到,一個完整的Web應用程式的開發流程如下:
- 編寫Servlet;
- 打包為war檔案;
- 複製到Tomcat的webapps目錄下;
- 啟動Tomcat。
這個過程是不是很繁瑣?如果我們想在IDE中斷點除錯,還需要開啟Tomcat的遠端除錯埠並且連線上去。
許多初學者經常卡在如何在IDE中啟動Tomcat並載入webapp,更不要說斷點除錯了。
我們需要一種簡單可靠,能直接在IDE中啟動並除錯webapp的方法。
因為Tomcat實際上也是一個Java程式,我們看看Tomcat的啟動流程:
- 啟動JVM並執行Tomcat的
main()
方法; - 載入war並初始化Servlet;
- 正常服務。
啟動Tomcat無非就是設定好classpath並執行Tomcat某個jar包的main()
方法,我們完全可以把Tomcat的jar包全部引入進來,然後自己編寫一個main()
方法,先啟動Tomcat,然後讓它載入我們的webapp就行。
我們新建一個web-servlet-embedded
工程,編寫pom.xml
如下:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.itranswarp.learnjava</groupId>
<artifactId>web-servlet-embedded</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<java.version>11</java.version>
<tomcat.version>9.0.26</tomcat.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-core</artifactId>
<version>${tomcat.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<version>${tomcat.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
其中,<packaging>
型別仍然為war
,引入依賴tomcat-embed-core
和tomcat-embed-jasper
,引入的Tomcat版本<tomcat.version>
為9.0.26
。
不必引入Servlet API,因為引入Tomcat依賴後自動引入了Servlet API。因此,我們可以正常編寫Servlet如下:
@WebServlet(urlPatterns = "/")
public class HelloServlet extends HttpServlet {
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html");
String name = req.getParameter("name");
if (name == null) {
name = "world";
}
PrintWriter pw = resp.getWriter();
pw.write("<h1>Hello, " + name + "!</h1>");
pw.flush();
}
}
然後,我們編寫一個main()
方法,啟動Tomcat伺服器:
public class Main {
public static void main(String[] args) throws Exception {
// 啟動Tomcat:
Tomcat tomcat = new Tomcat();
tomcat.setPort(Integer.getInteger("port", 8080));
tomcat.getConnector();
// 建立webapp:
Context ctx = tomcat.addWebapp("", new File("src/main/webapp").getAbsolutePath());
WebResourceRoot resources = new StandardRoot(ctx);
resources.addPreResources(
new DirResourceSet(resources, "/WEB-INF/classes", new File("target/classes").getAbsolutePath(), "/"));
ctx.setResources(resources);
tomcat.start();
tomcat.getServer().await();
}
}
這樣,我們直接執行main()
方法,即可啟動嵌入式Tomcat伺服器,然後,通過預設的tomcat.addWebapp("", new File("src/main/webapp")
,Tomcat會自動載入當前工程作為根webapp,可直接在瀏覽器訪問http://localhost:8080/
:
通過main()
方法啟動Tomcat伺服器並載入我們自己的webapp有如下好處:
- 啟動簡單,無需下載Tomcat或安裝任何IDE外掛;
- 除錯方便,可在IDE中使用斷點除錯;
- 使用Maven建立war包後,也可以正常部署到獨立的Tomcat伺服器中。
對SpringBoot有所瞭解的童鞋可能知道,SpringBoot也支援在main()
方法中一行程式碼直接啟動Tomcat,並且還能方便地更換成Jetty等其他伺服器。它的啟動方式和我們介紹的是基本一樣的,後續涉及到SpringBoot的部分我們還會詳細講解。
練習
從下載練習:使用嵌入式Tomcat執行Servlet(推薦使用IDE練習外掛快速下載)
注意:引入的Tomcat的scope為provided
,在Idea下執行時,需要設定Run/Debug Configurations
,選擇Application - Main
,鉤上Include dependencies with "Provided" scope
,這樣才能讓Idea在執行時把Tomcat相關依賴包自動新增到classpath中。
小結
開發Servlet時,推薦使用main()
方法啟動嵌入式Tomcat伺服器並載入當前工程的webapp,便於開發除錯,且不影響打包部署,能極大地提升開發效率。