1. 概述
本文將介紹 Activeweb——JavaLite 提供的全棧 Web 框架,它提供了開發動態 Web 應用程序或 RESTful Web 服務的必要的一切。
2. 基本概念與原則
Activeweb 採用“約定優於配置” – 這意味着它具有可配置性,但擁有合理的默認設置,並且不需要額外的配置。 我們只需要遵循一些預定義的約定,例如以特定預定義的格式命名類、方法和字段。
它還通過重新編譯和加載源代碼到正在運行的容器(默認使用 Jetty)簡化了開發過程。
對於依賴管理,它使用 Google Guice 作為 DI 框架;要了解更多關於 Guice 的信息,請查看我們的指南 此處。
3. Maven 設置
為了開始,我們首先添加必要的依賴項:
<dependency>
<groupId>org.javalite</groupId>
<artifactId>activeweb</artifactId>
<version>1.15</version>
</dependency>
最新版本可在此處找到:這裏。
此外,為了測試應用程序,我們需要 activeweb-testing 依賴項:
<dependency>
<groupId>org.javalite</groupId>
<artifactId>activeweb-testing</artifactId>
<version>1.15</version>
<scope>test</scope>
</dependency>請查看最新版本 這裏。
4. 應用結構
正如我們討論的,應用程序的結構需要遵循一定的約定;以下是典型的 MVC 應用程序的結構:
如我們所見,controllers, service, config, 和 models 應該位於 app 包中的各自子包中。
視圖應位於 WEB-INF/views 目錄中,每個視圖應有一個基於控制器名稱的子目錄。例如,app.controllers.ArticleController 應該有一個 article/ 子目錄,其中包含該控制器的所有視圖文件。
部署描述符或 web.xml 通常包含一個
...
<filter>
<filter-name>dispatcher</filter-name>
<filter-class>org.javalite.activeweb.RequestDispatcher</filter-class>
...
</filter>
...我們還需要一個 <em>init-param>,定義應用程序的默認控制器——類似於一個 <em>home>控制器:
...
<init-param>
<param-name>root_controller</param-name>
<param-value>home</param-value>
</init-param>
...5. 控制器
控制器是 ActiveWeb 應用程序的主要組件;正如前面提到的,所有控制器都應位於 app.controllers 包內:
public class ArticleController extends AppController {
// ...
}請注意,控制器正在擴展 org.javalite.activeweb.AppController。
5.1. 控制器 URL 映射
控制器根據約定自動映射到 URL。例如,ArticleController 將映射到:
http://host:port/contextroot/article現在,這將會將其映射到控制器中的默認操作。操作僅僅是控制器中的方法。將默認方法命名為 index():。
public class ArticleController extends AppController {
// ...
public void index() {
render("articles");
}
// ...
}對於其他方法或操作,請將方法名稱追加到 URL 中:
public class ArticleController extends AppController {
// ...
public void search() {
render("search");
}
}網址:
http://host:port/contextroot/article/search我們甚至可以基於 HTTP 方法定義控制器動作。只需用 @POST、@PUT、@DELETE、@GET、@HEAD 中的任何一個註解方法即可。如果沒有註解任何動作,則默認被認為是 GET 請求。
5.2. 控制器 URL 解析
框架使用控制器名稱和子包名稱生成控制器 URL。例如,對於 <em >app.controllers.ArticleController.java</em>,URL 如下:
http://host:port/contextroot/article<p>如果控制器位於子包中,URL 將簡化為:</p>
http://host:port/contextroot/baeldung/article對於名稱包含多個單詞的控制器(例如 app.controllers.PublishedArticleController.java),URL 將使用下劃線進行分隔:
http://host:port/contextroot/published_article5.3. 獲取請求參數
在控制器中,我們使用 param() 或 params() 方法(來自 AppController 類)來訪問請求參數。該方法接受一個字符串參數,即要檢索的參數名稱:
public void search() {
String keyword = param("key");
view("search",articleService.search(keyword));
}我們可以使用它來獲取所有參數,如果需要的話:
public void search() {
Map<String, String[]> criterion = params();
// ...
}6. 視圖
在 ActiveWeb 術語中,視圖通常被稱為模板,這主要是因為它使用了 Apache FreeMarker 模板引擎,而不是 JSPs。 您可以在我們的指南中瞭解更多關於 FreeMarker 的信息,這裏。
將模板放在 WEB-INF/views 目錄下。 每個控制器都應該有一個以其名稱命名的子目錄,其中包含它所需要的的所有模板。
6.1. 控制器視圖映射
當控制器被觸發時,默認操作 <em >index()</em> 會被執行,框架會從 views/article/ 目錄中選擇 <em >index.ftl</em> 模板。同樣,對於任何其他操作,視圖將根據操作名稱進行選擇。
這並不總是我們想要的。有時我們可能希望根據內部業務邏輯返回一些視圖。在這種情況下,<strong >我們可以使用render()方法來自org.javalite.activeweb.AppController父類控制流程</strong>。
public void index() {
render("articles");
}請注意,自定義視圖的位置也應在與該控制器相同的視圖目錄中。如果不是這樣,請在模板所在的目錄前綴模板名稱,並將其傳遞給 render() 方法:
render("/common/error");6.3. 使用數據視圖
為了將數據發送到視圖,<em >org.javalite.activeweb.AppController</em></em > 提供了view() 方法:`
view("articles", articleService.getArticles());此方法接受兩個參數。第一個是模板中用於訪問對象的對象名稱,第二個是包含數據的對象。
我們還可以使用 assign() 方法將數據傳遞給視圖。視圖() 方法和 assign() 方法之間沒有任何區別——我們可以選擇任何一個。
assign("article", articleService.search(keyword));讓我們繪製模板中的數據:
<@content for="title">Articles</@content>
...
<#list articles as article>
<tr>
<td>${article.title}</td>
<td>${article.author}</td>
<td>${article.words}</td>
<td>${article.date}</td>
</tr>
</#list>
</table>7. 管理依賴項
為了管理對象和實例,ActiveWeb 使用 Google Guice 作為依賴管理框架。
假設我們需要在應用程序中創建一個服務類,以將業務邏輯與控制器分離。
首先,我們創建一個服務接口:
public interface ArticleService {
List<Article> getArticles();
Article search(String keyword);
}以下是實現方式:
public class ArticleServiceImpl implements ArticleService {
public List<Article> getArticles() {
return fetchArticles();
}
public Article search(String keyword) {
Article ar = new Article();
ar.set("title", "Article with "+keyword);
ar.set("author", "baeldung");
ar.set("words", "1250");
ar.setDate("date", Instant.now());
return ar;
}
}現在,讓我們將此服務綁定為一個 Guice 模塊:
public class ArticleServiceModule extends AbstractModule {
@Override
protected void configure() {
bind(ArticleService.class).to(ArticleServiceImpl.class)
.asEagerSingleton();
}
}最後,請將其註冊到應用程序上下文中,並將其注入到控制器中,如需要。
public class AppBootstrap extends Bootstrap {
public void init(AppContext context) {
}
public Injector getInjector() {
return Guice.createInjector(new ArticleServiceModule());
}
}請注意,此配置類名必須為 AppBootstrap,並且應位於 app.config 包中。
最後,以下是如何將其注入到控制器中:
@Inject
private ArticleService articleService;8. 測試
針對 ActiveWeb 應用,單元測試使用 JavaLite 的 JSpec 庫編寫。
我們將使用 JSpec 中的 org.javalite.activeweb.ControllerSpec 類來測試我們的控制器,並且測試類名將遵循類似的命名約定:
public class ArticleControllerSpec extends ControllerSpec {
// ...
}請注意,該名稱與它正在測試的控制器非常相似,並且以“Spec”結尾。
以下是測試用例:
@Test
public void whenReturnedArticlesThenCorrect() {
request().get("index");
a(responseContent())
.shouldContain("<td>Introduction to Mule</td>");
}請注意,request()方法模擬了對控制器的調用,而對應的HTTP方法get()則將操作名稱作為參數傳入。
我們還可以使用params()方法將參數傳遞給控制器。
@Test
public void givenKeywordWhenFoundArticleThenCorrect() {
request().param("key", "Java").get("search");
a(responseContent())
.shouldContain("<td>Article with Java</td>");
}為了傳遞多個參數,我們也可以通過鏈接方法來實現,利用這種流暢的 API。
9. 部署應用程序
可以將應用程序部署在任何servlet容器上,例如Tomcat、WildFly或Jetty。當然,使用Maven Jetty插件進行部署和測試是最簡單的方法:
...
<plugin>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>9.4.8.v20171121</version>
<configuration>
<reload>manual</reload>
<scanIntervalSeconds>10000</scanIntervalSeconds>
</configuration>
</plugin>
...最新版本的插件在此:此處。
現在,我們終於可以啓動它:
mvn jetty:run10. 結論
在本文中,我們學習了 ActiveWeb 框架的基本概念和約定。此外,該框架還擁有我們討論過的更多功能和能力。
請參閲官方 文檔 以獲取更多詳細信息。