Think as developer, 从深入理解业务实现框架开始
作者:李小磊 | 網易杭州研究院-質量保障部?
如果想釣魚,那么就像魚一樣思考。那么問題來了,你有魚鰭來游泳嗎?
首先,產品的快速迭代,可以迅速滿足用戶需求,然而卻也有一些后遺癥,比如部分需求描述偏向于口頭傳述,文檔后于實現,會給QA工作造成比較大的困難。所以在堅守一些固有可靠的測試流程之外,我們需要想一些新的辦法。
其次,測試的起點是明確測試的需求,然而有些很具體的問題,需要幫助開發定位問題,需求只定義了一些比較粗的業務目標,然而具體實現由開發掌握。那么這里的銜接過程,QA是袖手旁觀呢,還是參與其中。個人認為后者可能可以更深入的接近實現,達到最大化的質量保障。 那么從閱讀業務實現框架開始吧。
鑒于目前接觸到的大多PC端的項目,大多是war包形式走的tomcat。所以這篇文章主要是面向這類產品的一些閱讀方法和技巧總結進行的一些實踐活動。
源自
哨兵系統Web API Task模塊源碼閱讀;
FAQ智能語音JAVA層源碼閱讀。
Get到那些點
一個web項目的容器啟動的入口是什么;
深入Spring MVC + Mybatis的一些成熟的工程架構如何配置;
Spring 和SpringMVC是兩件事。
QA如何得益于此
請跳轉至最后總結。
讀了哪些
一個web項目的容器啟動的入口是什么?
記得最早的時候開始研究JAVA WEB的時候,記得看到一個人寫的一句話: “初學 Java Web 開發,請遠離各種框架,從 Servlet 開發”。(這里簡單介紹下,眾所周知這樣的字眼還是不要出現比較好)
Java web開發離不開servlet,servlet的生命周期是有Tomcat/jetty這樣的web容器接管,那么web.xml就是所有開始的入口。這里會配置servlet,filter這樣的組件。
servlet:通過doGet doPost方法處理請求,這個方法里有傳統的兩個入參:HttpServletRequest,HttpServletResponse來分別處理請求和響應。
filter:在請求被容器發到servlet之前,會先經過配置的filter。所以一般情況下,filter都是做一些白名單驗證,特定的uri要通過openid,doFilter方法在做。 這個時候web.xml里應該會有很多<servlet>和<filter>標簽,雜亂無章
加入的springMVC框架后,web.xml就變得簡化無比(只是web.xml),需要關注的有下面這些:
? ? <context-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-context-web.xml</param-value></context-param><listener><listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>以及servlet的配置:
? ?<servlet><servlet-name>sentry</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class><init-param><param-name>contextConfigLocation</param-name><param-value>classpath:spring-mvc-config.xml</param-value></init-param><load-on-startup>1</load-on-startup></servlet>又出來了兩個配置文件:spring-context-web.xml & spring-mvc-config.xml 一個是通用上下文,一個是初始化MVC上下文。如下圖
那么各有什么用處:
ContextLoaderListener初始化的上下文加載的Bean是對于整個應用程序共享的,不管是使用什么表現層技術,一般如DAO層、Service層Bean;
DispatcherServlet初始化的上下文加載的Bean是只對Spring Web MVC有效的Bean,如Controller、HandlerMapping、HandlerAdapter等等,該初始化上下文應該只加載Web相關組件。
這里就可以大致知道,之前所有<servlet>需要做的事情,都被spring的Dispatcher servlet統一接管,可以理解為一個虛擬的路由器,將請求轉發給所有的@Controller
這里碰見過一個事情:我有個外部的服務需要初始化,初始化如下:
? ?<bean id="qbsService" class="com.netease.qadev.utils.qbs.QbsServiceImpl"><constructor-arg index="0" value="${qbs.baseURL}" /><constructor-arg index="1" value="${qbs.token}" /></bean>我用它的地方是在一個controller里面,然而放在spring-mvc-config.xml就編譯失敗,說找不到這個bean。放在spring-context-web.xml就可以。這里就延伸出來另外一個話題?spring和springMVC是兩件事。
深入理解Spring MVC + Mybatis的一些成熟的工程架構如何配置,
你的項目目錄應該是這樣的:
/main/:
Controller層,Service層及DAO層,以及filter:
/Resources:
使用MyBatis的話,這些mapper文件放在這里,并使用和DAO層一樣的package。 然后根據不同的開發,測試,線上環境放入不同的配置文件。
至于配置文件如何讀取,一方面Maven編譯打包的時候resource目錄下的文件都會copy出來。另外一方面,區分環境變量,在pom,xml的<profile>配置即可,然后通過mvn的 -P參數來區分(這里在OMAD里,其實是通過ant copy覆蓋的操作來進行),如圖:
? ? ? ?<profile><id>dev</id><activation><activeByDefault>true</activeByDefault></activation><build><resources><resource><directory>src/main/resources/dev</directory></resource><resource><directory>src/main/resources/common</directory></resource></resources></build></profile><profile><id>test</id> ? ? ? ? ? ?/* 同上 */<directory>src/main/resources/test</directory></profile><profile><id>online</id>...<directory>src/main/resources/online</directory>... ? ? ? ? ? ?/* 同上 */</profile>請求如何到達Controller
這里有個關鍵注釋:<mvc:annotation-driven/>?因為之前肯定是通過<context:component-scan/>掃描過所有的Controller,但是他們只是bean被構造,需要通過<mvc:annotation-driven/>標簽告訴springMVC,請求的處理者。
請求返回:FTL返回及JSON返回
這里要在spring_mvc_config.xml中配置一個bean:ContentNegotiatingViewResolver,有兩個屬性:
<property name="defaultContentType" value="application/json" /> ..... <property name="viewResolvers"> ..... <property name="defaultViews">這兩個resolver的好處在于:Controller的函數處理,返回String就默認是FTL的路徑(也就是前端的路徑),返回void,就是json。不需要@RequestBody注解。
Controller 怎么看,怎么寫
了解一些關鍵注釋的意思,比如@RequestMapping,?@RequestParam,?@RequestHeader?,@PathVariable, 至于ResponseBody,經過上面的講解,應該就不需用了。別的話,多看代碼,多實踐,不缺這樣的資料。
前端的配置
兩個關鍵配置:
<mvc:resources mapping="/views/**" location="/views/"/>` <bean ? ? ? ? ? ?class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><property name="templateLoaderPath" value="/views"/>`因為Servlet被Spring整體接管之后,所有的請求都被接管。那么靜態文件呢?他們又沒有Controller的處理,肯定會404 not found。 第一個注釋就是解決了這個問題,配置了靜態文件的本地路徑/views/,這里根目錄是webapp, 那么所有的CSS,JS, PNG, 都將在來這里找。 第二個注釋其實就是配置frerMarker的模版路徑,一般工程也都放在webapp的/views/下。
spring和springMVC是兩件事。
這里碰見過一個事情:我有個外部的服務需要初始化,初始化如下:
? ?<bean id="qbsService"class="com.netease.qadev.utils.qbs.QbsServiceImpl"><constructor-arg index="0" value="${qbs.baseURL}" /><constructor-arg index="1" value="${qbs.token}" /></bean>我用它的地方是在一個controller里面,然而放在spring-mvc-config.xml就編譯失敗,說找不到這個bean。具體為啥,可以參考上一節。因為這些bean并不是有Spring MVC通過@Service標簽來統一注入管理。那么它的初始化過程應該要放入spring-context-web.xml,在spring mvc介入之間就需要實例化。否則當然只是一個接口。
得到什么
在我新take的一個FAQ智能語音機器人項目中,在沒有任何需求設計接口文檔的情況下,要開展測試工作,只能先從源碼開始,之前的經驗幫助了我,理清楚了所有接口的處理邏輯(畢竟是半路接手項目,只能先解決問題為先)。基本上一兩天功夫就可以把源碼讀懂。當時的幾個思維導圖之一如下:?
后面就是歡快的寫接口用例case了。
略深入理解spring及springMVC
找到快速融入團隊的切入點。
能夠迅速定位問題。
QA不僅僅要整體業務上有宏觀把控。出現微觀上bug,也能做出root cause的前瞻分析。
結語
白盒與黑盒不是測試手段,而是測試思維。 過度關注開發細節的白盒測試沒有意義,從需求出發更加的符合實際中的測試。
· EDN ·
推薦閱讀
項望烽:移動 IM 開發之登錄優化
后端Java工程師如何將編碼速度提升10倍?
網易云信|真正穩定的IM云服務
http://netease.im ?長按關注,精彩不斷
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Think as developer, 从深入理解业务实现框架开始的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 魔兽嘉年华,云信四大码魔与你不见不散
- 下一篇: 快速问医生如何快速实现 患者与医生即时问