當前位置:首頁 » 網頁前端 » 用spring做一個web應用
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

用spring做一個web應用

發布時間: 2023-02-28 15:11:59

1. 在基於spring搭建的java web應用中,是通過什麼方式觸發spring的初始化過程的

前段時間在公司做了一個項目,項目用了spring框架實現,WEB容器是Tomct 5,雖然說把項目做完了,但是一直對spring的IoC容器在web容器如何啟動和起作用的並不清楚。所以就抽時間看一下spring的源代碼,藉此了解它的原理。
我們知道,對於使用Spring的web應用,無須手動創建Spring容器,而是通過配置文件,聲明式的創建Spring容器。因此在Web應用中創建Spring容器有如下兩種方式:
1. 直接在web.xml文件中配置創建Spring容器。
2. 利用第三方MVC框架的擴展點,創建Spring容器。
其實第一種方式是更加常見。為了讓Spring容器隨Web應用的啟動而啟動,有如下兩種方式:
1. 利用ServletContextListener實現。
2. 利用load-on-startup Servlet實現。
Spring提供ServletContextListener的一個實現類ContextLoaderListener,該類可以作為Listener 使用,它會在創建時自動查找WEB-INF下的applicationContext.xml文件,因此,如果只有一個配置文件,並且文件名為applicationContext.xml,則只需在web.xml文件中增加以下配置片段就可以了。

<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
如果有多個配置文件需要載入,則考慮使用<context-param...>元素來確定配置文件的文件名。ContextLoaderListener載入時,會查找名為contentConfigLocation的初始化參數。因此,配置<context-param...>時就指定參數名為contextConfigLocation。
帶多個配置文件的web.xml文件如下:

<context-param>
<param-name>contextLoaderListener</param-name>
<param-value>
WEB-INF/*.xml, classpath:spring/*.xml
</param-value>
</context-param>
<listener>
<listener-class>
org.springframework.web.context.ContextLoaderListener
</listener-class>
</listener>
多個配置文件之間用「,」隔開。

下面我們來看它的具體實現過程是怎樣的,首先我們從ContextLoaderListener入手,它的代碼如下:

public class ContextLoaderListener implements ServletContextListener
{

private ContextLoader contextLoader;

/**
* 這個方法就是用來初始化web application context的
*/
public void contextInitialized(ServletContextEvent event)
{
this.contextLoader = createContextLoader();
this.contextLoader.initWebApplicationContext(event.getServletContext());
}

/**
* 創建一個contextLoader.
* @return the new ContextLoader
*/
protected ContextLoader createContextLoader()
{
return new ContextLoader();
}
................

}

2. webserver

web應用伺服器是互聯網時代最為重要之一的底層支持。它處理相應的應用訪問請求,並為前端提供相應的展示數據。
不同的web應用伺服器實現性能不同,大型網站伺服器可以每秒處理幾萬到幾十萬的應用請求,中小型網站伺服器可能會因為每秒幾千次請求停機。
從架構的角度上而言,web-server的升級是一個迭代的過程,只有現在的應用伺服器無法滿足網站的訪問量,才會在此之上進行優化。對於一名好的架構師而言,落地和防災、可擴展是優先需要考慮的相關事宜。

首先要說的是軟體開發是一個確定性的事件, 有章可循,有理可溯 ,任何現象都是可以被解釋的,這是入門級程序員和高級程序員的區別之處。
我們以這種思路自頂向下去分析解決問題。

以主流的JavaEE為例,傳統的應用開發兩個較為核心的工作內容是:

這可能會涉及持續化集成、自動化測試、測試驅動開發概念。

在這之後,可能還會存在的工作是:

在這個過程中,可能會涉及封裝、基類、工具類、反射、泛型的概念。

從上面可以看出,軟體開發是一件團隊合作的事情。應該由 不同的人員去從事不同的事情 。傳統項目的分工基本如下(基於個人主觀猜測):

目前比較主流的web應用框架是以spring-boot為主的微服務框架。對於上面說的三個事情而言,重要的是 把其中任何一件事情當作一個工程去做,賦予一個合適的時間周期。 這部分內容在預研過程中非常關鍵,前期未考慮到的因素後期再修改代價可能為 指數級

以spring-boot為主,結合mysql搭建web應用伺服器的例子github上有很多,在這里不再贅述。

從客戶端傳遞到伺服器,響應時間由以下三個部分組成:

當出現應用響應時間過高這個問題時,對於相關人員,首先需要做的是:

對上面三個部分進行測試,分析它們分別所消耗的時間,然後再對此進行優化。 做到有的放矢,不要四處放槍

當我們開發完應用程序之後,該如何進行應用的部署呢?怎樣的部署才能夠保證伺服器的處理時間較短?
下面我們討論單個tomcatweb應用伺服器和多個tomcatweb應用伺服器。

通過spring boot 創建web應用有兩種方式:war包與jar包。在本文中以war包為例。

servlet解析web請求過程:

tomcat作為servlet容器的一種,管理著部署的多個web應用。tomcat運行架構圖如下:

從上圖中可以看出:

所以由於每個web應用只創建了一個servlet實例,所以需要線程安全問題。(即servlet中包含靜態變數和成員變數的時候會出現線程安全的問題。應該使用局部變數。)

tomcat 並發模型

從單個tomcat運行web應用中可以看出:

java web通過封裝servlet屏蔽了服務細節,使web開發人員專注與業務邏輯的實現。這是j2ee能在web開發中有一定地位的原因。
然而,由於servlet的創建和tomcat 多線程的並發處理全部交由tomcat來做,在這一個層次程序員無法做太多的事情,只能對tomcat和jvm進行調優。
萬幸的是cpu不是系統性能的瓶頸。但是目前有很多的游戲已經使用goroutine來實現了。因為golang的協程可以開上萬個,非常適合多線程的處理。

在一些大型網站中,對這部分性能調優的解決方案有:

第二種方案就引入了多tomcat web應用伺服器。它的思路是:

在雲計算尚未出現時,負載均衡及容器的維護往往由內部的技術部自行實現,在雲計算時代,由於K8S和Docker的出現,使這類問題解決更為容易。
K8S的彈性伸縮,把容器進行拷貝復制,並自動負責負載均衡,可以大大簡化其流程。

ps:在K8S上運行的多個tomcat容器是相同的拷貝。

淘寶的例子

從傳統的意義上講,系統的性能瓶頸並不存在於cpu的計算能力,而在於I/O。
所以大型網站架構上通常在思考如何降低I/O的時間。

最常用的降低I/O時間是使用reddis和memcached做緩存,關於這塊前輩的經驗摘引如下:

安全內容博大精深,關於安全方面相關的一些基本的認知鏈接如下:

web application security

另外,如果對於java 而言,可以使用一個apache的安全框架
shiro

此外還有一些諸如分布式文件存儲、加快伺服器腳本運算速度、頁面組件分離等都是提高伺服器響應的方法。

在web開發中,cookie和seesion經常用到。接下來進行簡單的說明。cookie和session主要是用來保存數據及狀態。

cookie 和session 的區別:

建議:

cookie和session可以解決跨頁面傳遞數據的問題。
前端跨頁面傳遞數據是一個比較繁瑣的問題,依賴於瀏覽器的架構和實現。cookie和session是一種通用的解決方案。

3. 如何開發線程安全的Spring Web應用

如果開發者正開發或維護基於Servlet的Web應用,則Servlet規范建議最好能夠看看。因為它含有的內容對於Web應用開發者理解Servlet容器的工作機理很有幫助。
規范中最有趣的一部分是給出了Servlet容器是如何處理客戶請求的。Servlet容器將會根據web.xml配置文件中定義的各個Servet而創建相應的單例(Singleton)。因此,客戶請求可能同時訪問這些單例,即多個線程同時運行你的代碼。在Web應用中保證線程安全是很重要的。開發者應該對這個問題保持警惕,而且必須確保各自的代碼必須以線程安全的方式運行。