Maven項目+內嵌tomcat+Servlet


寫在前面

上篇文章 使用 Intellij IDEA 新建一個 Servlet 項目 ,文章中如何在 Intellij IDEA 中啟動 Tomcat 並加載 webapp,但是配置的過程十分繁瑣。至少需要進行以下三項的設置:

  1. Add Configuration
  2. Project Structure -> Modules -> Web
  3. Project Structure -> Artifacts -> Add Artifact
  4. Project Structure -> Libraries -> Add Java Library

這個繁瑣的過程,不是一個初學者,尤其是想要立馬開始敲代碼的開發者想要的。因此,我們需要一種簡單可靠,能直接在 IDE 中啟動並調試 webapp 的方法。

項目地址

git clone https://gitee.com/kendoziyu/code-servlet-parent.git

其中,maven-tomcat-servlet-example 是本文的項目示例。

Maven 配置文件

我們新建一個 maven-tomcat-servlet-example 工程,編寫pom.xml如下:

<?xml version="1.0" encoding="UTF-8"?>
<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>coderead.servlet</groupId>
    <artifactId>maven-tomcat-servlet-example</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <properties>
        <servlet-api.version>3.1.0</servlet-api.version>
        <tomcat.version>9.0.39</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>

    <build>
        <finalName>Hello</finalName>
    </build>
</project>

其中,<packaging> 類型為 war,引入依賴 tomcat-embed-coretomcat-embed-jasper,引入的 Tomcat 版本 <tomcat.version>9.0.39

tomcat-embed-core 依賴包含 javax.servlet 下的內容,因此需要再額外引入依賴 javax.servlet-api

<scope>指定為 provided,表示編譯時使用,但不會打包到.war文件中,因為運行期 Web服務器本身已經提供了 Servlet API 相關的 jar 包。

我們目光轉到 <finalName> 這個標簽,這個標簽將決定你所打包的 war 包的名稱。在本文的后續的 Tomcat 部署 war 章節,會為大家展示打包操作。

使用 WebServlet 注解

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet(urlPatterns = "/")
public class HelloServlet extends HttpServlet {

    @Override
    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();
    }
}

使用@WebServlet注解,可以簡化繁瑣的 xml 配置。使用注解前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_3_1.xsd"
         version="3.1">

    <servlet>
        <servlet-name>helloServlet</servlet-name>
        <servlet-class>coderead.servlet.HelloServlet</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>helloServlet</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>
</web-app>

改為使用注解以后web.xml 配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<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_3_1.xsd"
         version="3.1">

</web-app>

1 行的 Java 注解,可以減少 8 行 xml 配置,何樂而不為呢?

Main 函數啟動

因為Tomcat實際上也是一個Java程序,我們看看Tomcat的啟動流程:

  1. 啟動 JVM 並執行 Tomcat 的 main() 方法;
  2. 加載 war 並初始化 Servlet;
  3. 正常服務。

啟動Tomcat無非就是設置好 classpath 並執行 Tomcat 某個 jar 包的 main() 方法,我們完全可以把 Tomcat 的 jar 包全部引入進來,然后自己編寫一個 main() 方法,先啟動 Tomcat,然后讓它加載我們的 webapp 就行。

Main.java

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.WebResourceRoot;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.webresources.DirResourceSet;
import org.apache.catalina.webresources.StandardRoot;

import java.io.File;

public class Main {

    public static void main(String[] args) throws LifecycleException {
        // 啟動 tomcat
        Tomcat tomcat = new Tomcat();
        tomcat.setPort(Integer.getInteger("port", 8080));
        tomcat.getConnector();
        // 創建 WebApp
        Context context = tomcat.addWebapp("", new File("src/main/webapp").getAbsolutePath());
        WebResourceRoot resources = new StandardRoot(context);
        resources.addPreResources(
                new DirResourceSet(resources, "/WEB-INF/classes",
                        new File("target/classes").getAbsolutePath(), "/"));
        context.setResources(resources);

        tomcat.start();
        tomcat.getServer().await();
    }
}

小插曲:我在第一次寫 Demo 的時候,遇到了一個 WebServlet 不生效的問題,我最后發現,我沒有為 context 設置資源。也就是沒寫 context.setResources(resources); 這句話。囧

至此,我們已經搞定了一個啟動方便,且可以本地調試的 Servlet 程序。接着我們就來講講 war 包部署到 Tomcat 容器。

運維篇:war 包部署

本文還是選擇在 Windows 上演示,作為開發,有時候不會真的上手部署項目到 Tomcat 容器上,但是我們還是可以了解一下大致的流程。

打包 war 包

如果使用 Intellij Idea,打包位置如下:

這個對應的命令就是 mvn package,也可以在項目根目錄下執行該命令。輸出結果如下

紅色框1部分Hello 文件夾 其實就是 war 包里面的內容, Hello.war 相當於是壓縮包,只不過后綴是 .war

拷貝 war 包

Hello.war 拷貝到 Tomcat 安裝目錄的 webapps 文件夾下(如果你的 Tomcat 版本不支持的話,你還是解壓一下吧)。然后,我們就可以在瀏覽器中通過 http://localhost:8080/Hello/ 訪問該項目了。

如果想直接用 http://localhost:8080/ 訪問我們的項目,

  • 首先把 webapps 備份一下,我把它改名為 webapps_backup
  • 重新創建一個全新的文件夾 webapps,並創建一個子文件夾 ROOT,然后把 Hello.war 解壓一下

經過上面兩步驟就可以直接用 localhost:端口號 訪問了~

參考博客

廖雪峰的官方網站之Servlet開發
Create a Java Web Application Using Embedded Tomcat


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM