從零開發一個Java Web項目要點

  • 2019 年 11 月 11 日
  • 筆記

原文:www.jianshu.com/p/ab6a9eaacaf3 文章編輯自:Java團長

前言

本文章詳細的列出了開發一個傳統JavaWeb項目需要注意的要點,從環境準備開始到三層架構搭建,需要注意的地方全部羅列出來。

第一部分:環境準備

1. Maven命令創建web骨架

mvn archetype:create -DgroupId=net.rocketa -DartifactId=mywebapp -DarchetypeArtifactId=maven-archetype-webapp

注意web servlet版本(web.xml,3.1),Junit版本指定為4.X(這樣Spring好通過註解的方式來運行單元測試)

2. 注意在IDEA中需要設置好MAVEN工程的Sources/Tests/Resources/Test Resources屬性。

3. 日誌依賴

slf4j:規範和接口 具體的日誌實現有: log4j、logback、common-logging 因此我們一般是使用slf4j接口+一種具體的日誌實現+slf4j和這個具體日誌實現的依賴整合

4. 數據庫依賴

有2個依賴,需要注意,一個是驅動,一個是數據庫連接池(C3P0,DBCP…)。 驅動JAR包是運行期需要包含,編譯期不需要的。

5. 持久層框架依賴

說白了,DAO層的框架依賴:MyBatis or Hibernate or …. 比如除MyBatis本身的依賴需要引入之外,還需要引入MyBatis和Spring的整合依賴。

6. Web層依賴

比如,JSP中使用到的一些JSTL、標籤、Ajax訪問JSON等,還有需要注意的是,在編譯期需要引入servlet-api。

7. Spring核心依賴

spring-core、spring-beans、spring-context

8. Spring和DB之間的整合依賴

Spring是需要介入DB的管理的,比如它的聲明式事務。 spring-jdbc、spring-tx

9. Spring對Web的一些整合依賴

spring-web、spring-webmvc

10. Spring對Junit的支持依賴

spring-test

NOSQL對事務的支持不是很好,它主要追求的是性能、高可用、分佈式。 MySQL等關係型數據庫對事務的支持是很成熟的,也是很可靠的落地方案。

第二部分:DAO層

NOSQL對事務的支持不是很好,它主要追求的是性能、高可用、分佈式。 MySQL等關係型數據庫對事務的支持是很成熟的,也是很可靠的落地方案。

1.

可以在項目中建立一個SQL文件,便於SQL的管理。 注意,表的存儲引擎(事務的支持:innodb)、自動增長的特性、編碼、主鍵和索引。 一個良好的習慣是:為所有的表都添加一個創建時間字段,用於記錄,方便排查。 應該為表名、列名添加註釋,方便其他工程師查閱。 應該注意SQL技巧,比如插入存在唯一約束的表中,如果出現衝突不想報錯的話,可以:insert ignore into ….(可以通過返回的影響行數來進行判斷)

2. Dao層實體

一些業務對象的建立,setter/getter/toString等就不說了,需要特別注意的是,除了表的字段之外,還需要什麼屬性?這裡涉及到一個一對一、一對多,多對多的概念!

3. Dao層接口和mapper sql

MyBatis的特點:從SQL(參數+sql)映射到Entity/List(定製SQL、自由傳遞參數、結果集自動賦值) 使用MyBatis的方式:SQL寫在XML中,或者註解提供SQL。更加推薦的是XML,因為更加靈活,XML提供的動態拼接功能也是比註解簡單的多。 一個全局的mybatis配置文件+具體的SQL文件+DAO接口:讓我們只需要設計接口,關注業務邏輯,解放出來。 在全局mybatis配置文件中重點注意:是否開啟駝峰轉換,獲取數據庫自增主鍵,列別名替換列名等。 注意DAO接口和具體的SQL文件之間的對應關係。 具體SQL寫法中,比如#{},<![CDATA[…]]>等需要引起注意。 輸入參數類型parameterType,如果是多個基本類型,那麼不用給出來。 即便返回的是List對象,我們的resultType依然指定的是集合中的對象類型。 在Mybatis的SQL文件中是可以通過OGNL表達式來對對象中的一些對象類型的屬性進行賦值的! 表名.xxx 或者 表名.xxx as yyy 對於Mybatis而言,會忽略表名.前綴,也會忽略as。 另外,注意在Dao接口中,如果方法有多個基本類型參數,別忘了通過@Param來進行運行期參數標記! 總結:Dao層的工作逐漸演變成接口設計和SQL編寫了,這種代碼和SQL的分離方式,便於我們進行review,而Dao的拼接將在Service層完成。

4. 一些優化配置

比如,對帶包路徑的類型進行簡化,通過配置掃描包。 比如,批量掃描SQL文件,通過自動掃描配置文件。

5. mybatis和spring需要整合

spring需要接管數據庫 JDBC的一些連接信息,數據庫連接池的一些配置信息,就是配置DataSource的過程。 spring和mybatis整合的核心 SqlSessionFactory是MyBatis的配置核心,把DataSource注入,並指明MyBatis的全局配置文件位置,typeAliasesPackage掃描,mapper文件位置掃描等。 spring通過動態代理幫助生成Dao的代理實現類(MapperScannerConfigurer) 注入SqlSessionFactory(通過sqlSessionFactoryBeanName),指明Dao接口的包路徑basePackage 總之,配置的一項原則是:約定優於配置!!!

第三部分:進行Spring Junit單元測試

當我們進行了一些配置,寫了一些SQL,Dao接口後,應該要進行Spring Junit單元測試,可以通過IDEA快速的生成測試用例(很好用的一個功能,因為IDEA可以幫助我們快速在test下建立與dao/service接口的同級目錄下生成用例) 在用例中,我們只需要在類上打上註解: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"classpath:spring配置文件"}) 加載Spring容器後,我們就可以在用例中注入對象,開始測試了!!!

第四部分:Service層

Service層需要關注幾個要點: 業務對象的封裝、web和service之間進行數據傳遞的DTO、異常的處理(業務異常) 注意Spring事務回退的默認機制是:運行時異常。 因此,我們在service層默認定義的業務異常一般extends RuntimeException。 一般而言,通過:

try{    }catch(業務異常1 e1){    }catch(業務異常2 e2){    }catch(Exception e){    throw new 業務異常(...);    }

要知道,service層可能會發生業務異常,也可能發生一些其他異常,為了Spring都可以感知到,這裡會把Exception異常轉化成運行時異常

第五部分:Controller層

1. Restful

一種優雅的URI表述方式;資源的狀態;狀態的轉移 Restful示例: GET /product/list 查詢操作 GET /product/{productId}/detail GET /product/time/now POST /product/{productId}/execution 添加、修改操作【非冪等性】 POST /product/{productId}/{userId}/order DELETE /product/{productId}/delete 刪除操作 PUT 修改操作【冪等性】 URL設計: /模塊/資源/{標示}/集合1/…

2.Controller中請求方法的細節處理

考慮幾個方面:請求參數綁定、請求方式限制、轉發與重定向、數據模型賦值、JSON數據返回、Cookie訪問

@RequestMapping(value="/{productId:\d+}/detail",method=RequestMethod.GET,produces={"application/json;charset=UTF-8"})  @ResponseBody  public String detail(  @PathVariable("productId") Long  productId,@CookieValue(value="userId",required=false) Long userId,Model model){  # return "rediect:/xxx/yyy"  # return "forward:/xxx/yyy"  # return "view"  }

3.整合配置Spring MVC

在web.xml中配置DispatcherServlet攔截請求,並指出Spring相關的配置文件。 開啟Spring MVC的註解模式: <mvc:annotation-driven/> 靜態資源請求採用默認的servlet配置 <mvc:default-servlet-handler/> 配置JSP、ViewResolver的prefix「如/WEB-INF/jsp」suffix「如.jsp」 掃描web相關的Controller: <context:component-scan base-package="">

OK,先整理到這裡。