1. 程式人生 > 其它 >小白新手web開發簡單總結(三)-一個簡單的Spring專案

小白新手web開發簡單總結(三)-一個簡單的Spring專案

技術標籤:Javaweb應用開發java

目錄

一 前言

二 web應用開發

1.什麼是web應用開發

2.一個簡單的web應用

3.實際的web應用

三 web應用開發的斷點除錯

四 總結


一 前言

經過小白新手web開發簡單總結(一)-什麼是Tomcat小白新手web開發簡單總結(二)-什麼是web.xml,對一個web開發有了一點點認識,一個開發的流程應該大概是這個樣子:

  • 1.一個web專案開發最後通過maven把專案程式碼(前端頁面展示+業務邏輯)打包成war包;
  • 2.在伺服器上安裝Tomcat,那麼在安裝目錄下就會有一個webapps的資料夾,那麼我們就把第一步打包成的war包放到該目錄下。(從webapps這個命名方式上也可以看出,該Tomcat是可以啟動多個web應用);
  • 3.進入到bin的目錄下,執行.startup.sh,啟動Tomcat,那麼就會讀取war包裡面的web.xml配置檔案,按照小白新手web開發簡單總結(二)-什麼是web.xml例項化裡面的類,那麼我們就可以通過在瀏覽器中輸入url來訪問web應用了。

上面的三點總結是基於我在本地電腦上的一個操作方式總結出來的,真正的在一個網站開發過程中的操作過程,後面再去研究,但我覺得應該差不多也是這個樣子。所以對於後面在學習一個web開發,我覺得需要學習下到底Spring、Spring MVC、Tomcat之間的關係,一個請求過來,到底是怎麼完成一次請求的?

二 web應用開發

1.什麼是web應用開發

web應用開發一般都會採用B/S架構。從開發角度來分,我覺得一個web應用開發和一個APP的開發一樣,可以劃分為包括的分成這幾部分:web頁面相關的業務邏輯+網路通訊+網路提供給業務層呼叫的功能。對於使用者來說,只需要瀏覽器,web應用的相關業務邏輯和資料都存在在服務端。瀏覽器通過Http協議與伺服器進行通訊,獲取web頁面的內容,通過瀏覽器顯示給使用者。

瀏覽器在整個過程中的角色:

(1)與伺服器建立TCP連線;

(2)傳送Http請求,在該請求中會標明GET/POST;

(3)接收Http響應,將伺服器返回的內容顯示在瀏覽器中。

在請求和響應都包括Http Header和Http Body,響應體根據設定的Content-Type返回對應的網頁資料(如text/html,則會返回<html></html>),瀏覽器將這些資訊顯示出來即可。瀏覽器獲取的第一個資源就是這些Html網頁,如果裡面還含有JavaScript、CSS、圖片等資源,瀏覽器會根據對應的資源url再一次向伺服器傳送請求。

伺服器在整個過程中的角色:

(1)與瀏覽器建立TCP連線;

(2)識別Http請求,接收和處理Http請求;

(3)將處理之後的Http請求返回給瀏覽器。

從角色分工中,可以看出,伺服器已經處理和解析Http請求等網路通訊的工作,瀏覽器負責傳送和接收Http請求,而web應用只需要放到web伺服器即可。在Java EE提供HttpServlet來處理Http請求,那麼只要該伺服器去實現HttpServlet,就可以實現網路通訊的工作。

2.一個簡單的web應用

我覺得可以把HttpSerlvet理解成一個處理客戶端發過來的Http請求的類,裡面有兩個方法:

protected void doGet(HttpServletRequest req, HttpServletResponse resp)
protected void doPost(HttpServletRequest req, HttpServletResponse resp)

其中引數HttpServletRequest req, HttpServletResponse resp就代表這請求和響應。在使用這個HttpSerlvet的時候,不需要關心怎麼與TCP互動,也不需要解析Http,例如在doGet()方法只需要:從req中接收到瀏覽器發過來的請求引數,在該方法中完成業務邏輯和讀寫資料庫的操作,最後將結果寫入到resp,那麼瀏覽器就可以接收到相關的資料,在res和resp中已經封裝了請求和響應的邏輯。

通過這個HttpSerlvet來完成一個簡單的web應用開發的例項:

(1)通過IDEA建立一個Maven工程

(2)配置pom.xml,引入Servlet

    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.0.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>

這裡注意要將該依賴作為<provided>引入,這樣僅會在編譯的時候使用,最後不會打包到.war包中,因為在後面用到的Tomcat伺服器中已經有相應的Servlet API。

(3)配置打包型別為.war,同時配置最後打包成.war的名字

    <packaging>war</packaging>
    <build>
        <finalName>builder-spring</finalName>
    </build>

(4)在java的目錄下建立一個FirstServlet的java檔案,並且編寫一個簡單的顯示一句話。

@WebServlet(urlPatterns = "/")
public class FirstServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter writer = resp.getWriter();
        writer.write("<h1> Hello Web ,This is a simple web!</h1>");
        //強制輸出
        writer.flush();
    }
}

當然也可以通過getOutputStream()獲取寫入流。另外需要注意的是在寫入完畢之後,必須呼叫flush(),否則不能將這些資料及時返回給瀏覽器,而close(),是關閉的TCP連線,不能呼叫該方法。

(5)在專案工程的main/webapp/WEB-INF的目錄下,建立web應用的描述檔案web.xml

<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
    <display-name>build spring</display-name>
</web-app>

(6)通過IDEA自帶的maven進行打包,依次執行clean->compile->package,然後在target的目錄下就會生成build-spring.war包

(7)將build-spring.war包拷貝到在Tomcat的安裝目錄webapps,在返回到bin目錄下,執行.startup.sh,在終端命令視窗顯示:

MacBook-Pro:bin j1$ ./startup.sh 
Using CATALINA_BASE:   /Users/j1/Documents/java/apache-tomcat-9.0.41
Using CATALINA_HOME:   /Users/j1/Documents/java/apache-tomcat-9.0.41
Using CATALINA_TMPDIR: /Users/j1/Documents/java/apache-tomcat-9.0.41/temp
Using JRE_HOME:        /Library/Java/JavaVirtualMachines/jdk1.8.0_151.jdk/Contents/Home
Using CLASSPATH:       /Users/j1/Documents/java/apache-tomcat-9.0.41/bin/bootstrap.jar:/Users/j1/Documents/java/apache-tomcat-9.0.41/bin/tomcat-juli.jar
Using CATALINA_OPTS:   
Tomcat started.

(8)在瀏覽器中輸入http://localhost:8080/builder-spring/,就可以看到如下介面

當然也可以通過http://localhost:8080/builder-spring/?count=2來新增引數,那麼在FirstServlet可以直接通過HttpServletRequest讀取:

@WebServlet(urlPatterns = "/")
public class FirstServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        String count = req.getParameter("count");
        PrintWriter writer = resp.getWriter();
        writer.write(String.format("<h1> Hello Web %s ,This is a simple web!</h1>",count));
        //強制輸出
        writer.flush();
    }

在瀏覽器中訪問如下:

通過上面的幾個步驟,成功的建立了一個簡單的web應用。當瀏覽器在訪問"http://localhost:8080/builder-spring/"的時候,就會發送請求,然後有Tomcat(前面的小白新手web開發簡單總結(一)-什麼是Tomcat也提到了Tomcat其實就是一個Servlet容器)會將該請求交給FirstServlet來處理(@WebServlet(urlPatterns = "/")提供了對映關係)。

另外對於這個url的組成其實就是我們在pom.xml配置的<finalName>,再加上FirstServlet中的@WebServlet(urlPatterns = "/")組成的。

上述程式碼已經上傳到github,github地址為:https://github.com/wenjing-bonnie/build-spring.git

3.實際的web應用

當然在一個web應用中,是有許多個Servlet組成的,每個Servlet都會對映到一個路徑。所以在開發一個完整的web應用,在web頁面相關的業務邏輯這一部分中,其實可以細分成幾個過程:

  • (1)不同的路徑對映對應的不同的Servlet;

在每個Servlet處理業務邏輯的時候,其實也可以細分成過程:

1)從HttpServletRequest 中讀取請求引數;

2)處理複雜的業務邏輯:要有讀寫資料庫的公共操作類,要有資料庫的每張表對應著一些封裝類,要有針對這些表的操作的封裝類,更多的是在這一個Servlet可能涉及到多個數據庫表的操作,也就意味著需要引入多個表的操作類;

3)將響應資料寫入到HttpServletResponse,響應資料又可以看出是一些供瀏覽器顯示的資料(前面提到的例子中可能響應資料僅僅就是為了顯示一個字串,但在實際開發中會有更多跟頁面相關的渲染,例如jsp);

顯然在這個過程中會出現許多類例項的例項化和載入,以及這些類例項的生命週期的管理,並且在一個Servlet中還可以抽象成一種Model-View-Controller的設計模式。

  • (2)web伺服器根據路徑對映規則,將不同路徑轉發到對應的Servlet,該轉發功能通常由服務端Dispatcher完成。

那麼網路通訊以及網路提供給業務層呼叫的功能就有Tomcat來完成。對比之前在小白新手web開發簡單總結(一)-什麼是Tomcat小白新手web開發簡單總結(二)-什麼是web.xml,這些過程似乎都有了專門的對應:

  • (1)Tomcat就是一個Servlet容器,用來例項化Servlet來進行處理請求和響應。Tomcat的Connector負責與瀏覽器來建立連線,接收瀏覽器傳送過的請求以及將響應返回給瀏覽器;
  • (2)Tomcat中的Container中的Engine用來例項化Servlet,管理Servlet的生命週期,完成底層的網路通訊;
  • (3)在web.xml中註冊了DispatcherSerlvet,用來將瀏覽器傳送過來的請求對映到對應路徑的處理類中。

現在看來,對於web應用開發的一些知識點開始明朗起來。

三 web應用開發的斷點除錯

從上面一個簡單的例子看到一個web應用開發,其實就是編寫Servlet來處理瀏覽器傳送過來的Http請求,當然我們需要將最終的這些Servlet按照既定的規則打包成war包,通過Tomcat來載入war包,並執行這些Servlet。

在一個簡單的web應用例項中提到的上面的第六步和第七步,我們需要通過IDEA打包成war包,並且還要通過本地安裝的Tomcat來啟動war包,那麼如果斷點除錯呢?其實我們可以Tomcat也是一個java程式,通過.startup.sh 來啟動Tomcat,其實就是啟動JVM並執行Tomcat的main()方法,並且載入war包之後初始化Servlet,從而對瀏覽器提供服務。其實我們完全可以通過程式碼的形式來完成一個Tomcat啟動web專案。

(1)還是上面的專案程式碼,我們將javax.servlet換成Tomcat的相關依賴:

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <version>${tomcat.version}</version>
        </dependency>

(2)增加Tomcat例項化的main()方法


public class FirstServletTest {
    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);
        DirResourceSet set = new DirResourceSet(resources, "/WEB-INF/classes", new File("target/classes").getAbsolutePath(), "/");
        resources.addPreResources(set);
        context.setResources(resources);
        //啟動Tomcat
        tomcat.start();
        tomcat.getServer().await();
    }
}

(3)執行main()方法,然後在IDEA中下面就會顯示,表示嵌入式的Tomcat已經成功啟動,Tomcat會自動的將本工程放置到根目錄,可直接通過http://localhost:8080/?count=2進行訪問到對應的Servlet

二月 08, 2021 2:00:25 下午 org.apache.coyote.AbstractProtocol init
資訊: Initializing ProtocolHandler ["http-nio-8080"]
二月 08, 2021 2:00:25 下午 org.apache.catalina.core.StandardService startInternal
資訊: Starting service [Tomcat]
二月 08, 2021 2:00:25 下午 org.apache.catalina.core.StandardEngine startInternal
資訊: Starting Servlet engine: [Apache Tomcat/9.0.36]
二月 08, 2021 2:00:25 下午 org.apache.catalina.startup.ContextConfig getDefaultWebXmlFragment
資訊: No global web.xml found
二月 08, 2021 2:00:27 下午 org.apache.jasper.servlet.TldScanner scanJars
資訊: At least one JAR was scanned for TLDs yet contained no TLDs. Enable debug logging for this logger for a complete list of JARs that were scanned but no TLDs were found in them. Skipping unneeded JARs during scanning can improve startup time and JSP compilation time.
二月 08, 2021 2:00:27 下午 org.apache.coyote.AbstractProtocol start
資訊: Starting ProtocolHandler ["http-nio-8080"]

這樣就可以輕鬆的將一個專案通過 執行FirstServletTest的main()的方式來斷點除錯專案。但是在一個實際的web應用開發中,不知道是不是通過這種方式來斷點除錯,還需要自己再去學習與研究。

程式碼github地址為:https://github.com/wenjing-bonnie/build-spring.git

四 總結

通過這個簡單的web應用開發的例項,對比前面小白新手web開發簡單總結(一)-什麼是Tomcat小白新手web開發簡單總結(二)-什麼是web.xml兩篇的總結,簡單在總結下自己現在清晰的東西:

  • 1.一個web應用開發的專案通過maven打包成war包,執行在一個支援Servlet的web伺服器;
  • 2.Tomcat就是一個支援Servlet的web伺服器,每次在一個web應用服務上線的時候,應該就是將war包放到安裝到伺服器的Tomcat的相關目錄下,並且將Tomcat啟動;
  • 3.Tomcat啟動之後,就會讀取war包的web.xml檔案,然後將裡面對應的各個類例項化;
  • 4.當有瀏覽器有請求傳送過來的時候,首先會與web伺服器建立TCP連線,有瀏覽器傳送請求;
  • 5.Tomcat接收到請求之後,會有DispatcherServlet進行根據路徑匹配到對應的處理類;
  • 6.處理完之後的響應傳送給瀏覽器,瀏覽器負責將資料進行顯示
  • 7.HttpServlet不需要關心底層TCP等相關的網路邏輯,只需要從HttpServletRequest 取得請求引數,經過業務邏輯之後,將處理完之後的資料寫入到HttpServletResponse即可。

另外記錄一下關於Servlet的幾個知識點:在向HttpServletResponse寫入響應資料的時候,可以指定瀏覽器是重定向還是轉發

  • 1.重定向

當瀏覽器請求一個url,伺服器在處理完資料,返回給瀏覽器的時候,會告訴瀏覽器地址發生變化,需要瀏覽器在重新發送請求,通過下面的程式碼實現重定向:

  String redirectToUrl = "/xxxx";
   // 傳送重定向響應:
   resp.sendRedirect(redirectToUrl);

瀏覽器接收到如下響應:

HTTP/1.1 302 Found
Location: /xxxx

會根據Location返回的 url,重新發送一個新的請求。那麼在瀏覽器中看到是兩個請求。當然重定向又分為臨時重定向(302響應)和永久重定向(301響應)。兩者區別在於永久重定向,瀏覽器會換成Location傳送過來的url,在下一次在請求之前的url的時候,會直接傳送Location對應的url。在程式碼中通過

// HttpServletResponse.SC_MOVED_PERMANENTLY:301
//HttpServletResponse.SC_FOUND:302
resp.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY); 
resp.setHeader("Location", "/xxxx");
  • 2.轉發

轉發指的是內部轉發,當一個Servlet處理一個瀏覽器傳送過來的請求的時候,自己本身不去處理,而是轉發給另外一個Servlet來處理。程式碼中通過實現:

req.getRequestDispatcher("/xxxx").forward(req, resp);

後續請求處理實際是交給了"/xxxx"對應的Servlet來處理。

相比較於重定向而言,這個轉發僅僅是伺服器內部完成,對於瀏覽器來說,只會發出一個請求,本身不需要做任何處理,在瀏覽器中始終只有一個url。

這幾天每天都很充實,加油!!!!!