寫在前面
上一篇文章 在 Tomcat 上部署你的第一個 Servlet 應用 使用最原始的命令行方式編譯 Servlet 類,並且部署到 tomcat 安裝目錄下的 webapps 文件夾下。但是實際情況下,我們現在的工作已經十分依賴集成開發工具 IDEA 了,本文就借助 IDEA 創建一個 Servlet ,並且在 IDEA 工具內通過 tomcat 來啟動服務和本地調試。
項目地址
git clone https://gitee.com/kendoziyu/code-servlet-parent.git
其中,develop-servlet 就是本文的項目。
1.創建項目
首先 File -> New -> Project... 打開創建項目窗口

接着就是給你的項目找一個合適的名字和合適的路徑,我的項目命名為 develop-servlet

點擊 Finish 完成創建,並且在新的窗口中打開項目。

自動創建的模板,為我們創建了以下文件:
-
/web/WEB-INF/web.xml
-
/web/index.jsp
*自定義修改
首先,這個 web 文件夾的取名,不太符合我的習慣,我更喜歡命名為 webapp。
右擊 web 文件夾 --> Refactor --> Rename...
另外,當前 3.1 是穩定版本,4.0 是 alpha 版本,所以我們稍稍改動一下 web.xml,把 servlet 版本改為 3.1
<?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>
2.添加 Servlet 依賴
在 tomcat 安裝目錄下的 lib 下有 servlet-api.jar,而我的 tomcat 安裝目錄是 D:\server\apache-tomcat-9.0.39</span>

接着我們在 idea 中添加依賴庫,我們先通過 File --> Project Structure... 打開窗口:

D:\server\apache-tomcat-9.0.39\lib\servlet-api.jar

3.創建 LoginServlet
package coderead.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* JSP 頁面的 Servlet
*
* @author kendoziyu
* @since 2020/10/21 0021
*/
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.getWriter().write("<h1> Hello World </h1>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
4. 配置 web.xml
我們聲明一個名為 loginServlet 的 servlet 對應類 coderead.servlet.LoginServlet,並且配置它的攔截 url 地址為 /Login
<?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">
<servlet>
<servlet-name>loginServlet</servlet-name>
<servlet-class>coderead.servlet.LoginServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>loginServlet</servlet-name>
<url-pattern>/Login</url-pattern>
</servlet-mapping>
</web-app>
5. 添加運行項
我們打算用 tomcat 的方式來運行我們的項目,首先我們要 Add Configuration...

然后在 Run/Debug Configuration 窗口,選擇 Tomcat Server -> Local

接着我們就需要設置應用服務器 Applicaiton Server:

點擊 Configure... 打開了 Tomcat Server 窗口,我選擇了一下本地 Tomcat 安裝目錄 D:\server\apache-tomcat-9.0.39,並選擇 Ok

此時,在 Run/Debug Configuration 窗口出現一個 Warning: No artifacts configured

點擊 Fix ,如果你的 IDEA 版本沒有出現這個警告和 Fix 按鈕,那也請不要慌張,選擇 File -> Project Structure 即可。
6. 配置 Web Module
如果你不是用 idea 直接創建的 Web Application(比如是用 git clone 下來的代碼,或者你自己手動創建的 webapp 文件夾),那你可以看一下,你的 webapp 文件夾上並沒有一些“特殊的記號”。此時我們可以先添加 Web 模塊,后創建 Artifact,這樣會快很多。

如果你的 webapp 文件夾上已經有一個“小藍點”,那你可能可以直接跳至第 7 步,前提是你確定你的配置是正確的。在 Project Structure 窗口下,選擇 Modules

添加后效果如下圖所示,接着我們要修改 Web Module Deployment Descriptor 和 Web Resource Directory。

鼠標懸浮至 + 和 - 下方的 >>,會出現編輯按鈕:

編輯 Web Module Deployment Descriptor 選擇 項目根目錄路徑\webapp\WEB-INF\web.xml,版本選擇 3.1 ,和 web.xml 中的版本一致。

編輯 Web Resource Directory,選擇項目根目錄下的 webapp 目錄

7. 創建 Artifact
如果你做了 6 步,那么你可以直接選擇 Create Artifact。

如果你不是用 Create Artifact 方式,那就需要你自己選擇 Artifact 的類型:
如果選 Web Application: Exploded,這個是以文件夾形式(War Exploded)發布項目,選擇這個,發布項目時就會自動生成文件夾在指定的 output directory;
如果選 Web Application: Archive,就是 war 包形式,每次都會重新打包全部的,將項目打成一個 war 包,放到指定位置;

8. 部署
再次選擇 Add Configuration... ,打開 Run/Debug Configurations, + -> Tomcat Server -> Local ,切換到 Deployment,發現已經把 Artifact 自動添加進去了。

這里的 develop-servlet 是由第 7 步上面的圖片 Artifact - Name 所決定的,同時也會影響 Web 項目的 ContextPath。第 7 步 Artifact 的 Output Directory 最終目錄是 develop_servlet,因此 ContextPath 也是 develop_servlet。
也就是說我們應該在瀏覽器中通過 http://localhost:8080/develop_servlet/ 訪問我們的項目。不加其他配置的情況 http://localhost:8080/ 的訪問結果為 <span style="color:#E61A1A"404 Not Found。
* 選擇輸出目錄
還是因為我是 git clone 得到的項目,沒有配置輸出目錄,彈出這個報錯:

我們可以在 Project Structure 窗口,配置 Project compiler output 為 項目根目錄\out

9. jsp 調用 Servlet
首次打開時,會進入 index.jsp,如果沒登錄,我希望通過 jsp 調用 Servlet。
<%--
User: kendoziyu
Date: 2020/10/21
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首頁</title>
</head>
<body>
<%
String loginName = (String) request.getSession().getAttribute("loginName");
%>
<%
if (loginName == null || loginName.isEmpty()) {
%>
<a href="/Login">去登錄</a>
<% } else { %>
Hello, <%=loginName%>
<% } %>
</body>
</html>
不過,此時點擊“去登錄”,直接跳轉 http://localhost:8080/Login,結果 404 找不到頁面,稍微改造一下:
方法一:可以修改鏈接地址為相對地址
<a href="Login">去登錄</a>
適用場景:當前頁面是在 WebRoot 路徑下。
方法二:目標 URL 前面加上請求 ContextPath 前綴
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>首頁</title>
</head>
<body>
<%
String loginName = (String) request.getSession().getAttribute("loginName");
String prefix = request.getContextPath();
%>
<%
if (loginName == null || loginName.isEmpty()) {
%>
<a href="<%=prefix%>/Login">去登錄</a>
<% } else { %>
Hello, <%=loginName%>
<% } %>
</body>
</html>
10. Servlet 跳轉 jsp
方法一: sendRedirect 方式
sendRedirect("/a.jsp");
可以將頁面跳轉到任何路徑,不局限於web應用中,跳轉的過程中url地址變化,無法使用request.setAttribute來傳遞。
方法二:forward 方式
request.getRequestDispatcher("/a.jsp").forward(request.response);
url地址不變,只能跳轉到本web應用中的頁面上。可以用 request.setAttibute 方法
我們改寫一下 LoginServlet
package coderead.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* JSP 頁面的 Servlet
*
* @author kendoziyu
* @since 2020/10/21 0021
*/
public class LoginServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// response.getWriter().write("<h1> Hello World </h1>");
request.getRequestDispatcher("/login.jsp").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().setAttribute("loginName", request.getParameter("username"));
response.sendRedirect("index.jsp");
}
}
login.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>登錄</title>
</head>
<body>
<form action="Login" method="post">
username: <input type="username" name="username"> <br>
password: <input type="password" name="password"> <br>
<input type="submit" value="submit">
<input type="reset" value="reset"> <br>
</form>
</body>
</html>
