Gradle构建Java Web应用程序

本文指导如何使用Gradle的war插件和gretty插件构建、测试和部署Java Web应用程序,涵盖Servlet单元测试与功能测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Gradle包含war插件用于构建Java Web应用程序的,社区提供了一个出色的gretty插件,用于在Jetty或Tomcat上测试和部署Web应用程序。本指南演示了如何构建一个简单的Web应用程序以及如何使用该gretty插件将其部署在Jetty上。您还将学习如何使用Mockito框架为Servlet编写单元测试,以及如何使用grettyand Selenium 为Web应用程序编写功能测试。

你需要什么

  • 约21分钟

  • 文本编辑器或IDE

  • Java发行版

    • 版本7或更高版本(如果使用Gradle Groovy DSL)

    • 版本8或更高版本(如果使用Gradle Kotlin DSL)

  • 一个Gradle,版本4.10.3或更好

创建Web应用程序的结构

Gradle包含一个war插件,该插件记录在用户手册的WAR插件一章中。该war插件扩展了Java插件,以增加对Web应用程序的支持。默认情况下,它使用一个src/main/webapp与Web相关的资源的文件夹。

用户手册中的“ Web应用程序快速入门”部分仍指Jetty插件,不推荐使用该插件,而推荐使用此处使用的gretty插件。但是,特定于war插件的零件很好,该部分将很快更新。

因此,为名为的项目创建以下文件结构webdemo

示例项目布局
webdemo/
    src/
        main/
            java/
            webapp/
        test
            java/

任何servlet或其他Java类都会加入src/main/java,测试将进入src/test/java,其他Web工件将进入src/main/webapp

添加Gradle构建文件

将一个名为build.gradle(如果使用Groovy DSL)或build.gradle.kts(如果使用Kotlin DSL)的文件添加到项目的根目录,其内容如下:

build.gradle
plugins {
    id 'war'  
}

repositories {
    jcenter()
}

dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0' 
    testCompile 'junit:junit:4.12'
}
  • 使用war插件
  •  Servlet API的当前发行版

war插件添加配置providedCompileprovidedRuntime,类似于compileruntime在常规Java应用程序中进行配置,以表示本地所需的依赖关系,但不应将其添加到生成的webdemo.war文件中。

plugins语法用于应用javawar插件。两者都不需要版本,因为它们包含在Gradle发行版中。

通过执行以下wrapper任务为项目生成Gradle包装器是一个好习惯:

$ gradle wrapper --gradle-version=4.10.3
:wrapper

这将产生gradlewgradlew.bat脚本和gradle如所描述的与包装罐内部夹包装片的用户手册的。

如果您使用的是Gradle 4.0或更高版本,则控制台中的输出可能会比本指南中看到的少。在本指南中,使用命令行上的--console = plain标志显示输出。这样做是为了显示Gradle正在执行的任务.

向项目添加Servlet和元数据

定义Web应用程序元数据有两个选项。在Servlet规范3.0版之前,元数据驻留在项目文件夹中称为部署描述符web.xmlWEB-INF。从3.0开始,可以使用注释定义元数据。

org/gradle/demosrc/main/java文件夹下面创建一个包文件夹。添加一个servlet文件HelloServlet.java,内容如下:

src / main / java / org / gradle / demo / HelloServlet.java
package org.gradle.demo;

import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "HelloServlet", urlPatterns = {"hello"}, loadOnStartup = 1) 
public class HelloServlet extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        response.getWriter().print("Hello, World!");  
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        String name = request.getParameter("name");
        if (name == null) name = "World";
        request.setAttribute("user", name);
        request.getRequestDispatcher("response.jsp").forward(request, response); 
    }
}
  •  基于注释的servlet
  • GET请求返回一个简单的字符串
  • POST请求转发到JSP页面

Servlet使用@WebServlet注释进行配置。该doGet方法通过编写“ Hello,World!”来响应HTTP GET请求。字符串输出输出。它通过查找名为的请求参数name并将其request作为称为属性添加到,对HTTP POST请求做出反应user,然后转发到response.jsp页面。

war插件支持使用较早的web.xml部署描述符,默认情况下,该描述符应位于WEB-INF下方的文件夹中src/main/webapp。随意使用它作为基于注释的方法的替代方法。

现在,您有了一个简单的servlet,它可以响应HTTP GET和POST请求。

将JSP页面添加到演示应用程序

通过在文件夹中创建具有以下内容index.htmlsrc/main/webapp文件,将索引页添加到应用程序的根目录:

src / main / webapp / index.html
<html>
<head>
  <title>Web Demo</title>
</head>
<body>
<p>Say <a href="hello">Hello</a></p> 

<form method="post" action="hello">  
  <h2>Name:</h2>
  <input type="text" id="say-hello-text-input" name="name" />
  <input type="submit" id="say-hello-button" value="Say Hello" />
</form>
</body>
</html>
  • 链接提交GET请求
  •  表单使用POST请求

index.html页面使用一个链接向Servlet提交HTTP GET请求,并使用一个表单提交HTTP POST请求。该表单包含一个名为的文本字段name,该字段可由Servlet在其doPost方法中进行访问。

doPostservlet 通过其方法将控制权转发到另一个名为的JSP页面response.jsp。因此,请在src/main/webapp其中定义以下名称的文件:

src / main / webapp / response.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>Hello Page</title>
    </head>
    <body>
        <h2>Hello, ${user}!</h2>
    </body>
</html>

response页面user从请求中访问了变量,并将其呈现在h2标签中。

添加gretty插件并运行应用

gretty插件是社区支持的出色插件,可以在Gradle插件存储库中找到https://plugins.gradle.org/plugin/org.akhikhl.gretty。该插件使在Jetty或Tomcat上运行或测试Web应用程序变得容易。

通过将以下行添加到plugins构建脚本中的块中,将其添加到我们的项目中。

build.gradle
plugins {
    id 'war'
    id 'org.gretty' version '2.2.0' 
}
  • 添加gretty插件 

gretty插件向应用程序添加了大量任务,对于在Jetty或Tomcat环境中运行或测试很有用。现在,您可以使用该appRun任务将应用构建并部署到默认(Jetty)容器。

执行appRun任务
$ ./gradlew appRun
:prepareInplaceWebAppFolder
:createInplaceWebAppFolder UP-TO-DATE
:compileJava
:processResources UP-TO-DATE
:classes
:prepareInplaceWebAppClasses
:prepareInplaceWebApp
:appRun
12:25:13 INFO  Jetty 9.2.15.v20160210 started and listening on port 8080
12:25:13 INFO  webdemo runs at:
12:25:13 INFO    http://localhost:8080/webdemo
Press any key to stop the server.
> Building 87% > :appRun

BUILD SUCCESSFUL

现在,您可以在http://localhost:8080/webdemo上访问该Web应用程序,然后单击链接以执行GET请求或提交表单以执行POST请求。

尽管输出显示Press any key to stop the server,但Gradle不会拦截标准输入。要停止该过程,请按ctrl-C

使用Mockito对Servlet进行单元测试

开源Mockito框架使对Java应用程序进行单元测试变得容易。将Mockito依赖项添加到testCompile配置下的构建脚本中。

build.gradle
dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:2.7.19'  
}

添加Mockito 要对Servlet进行单元测试,请org.gradle.demo在下方创建一个package文件夹src/test/java

添加HelloServletTest.java具有以下内容的测试类文件: 

src / test / java / org / gradle / demo / HelloServletTest.java
package org.gradle.demo;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.io.StringWriter;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;

public class HelloServletTest {
    @Mock private HttpServletRequest request;
    @Mock private HttpServletResponse response;
    @Mock private RequestDispatcher requestDispatcher;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void doGet() throws Exception {
        StringWriter stringWriter = new StringWriter();
        PrintWriter printWriter = new PrintWriter(stringWriter);

        when(response.getWriter()).thenReturn(printWriter);

        new HelloServlet().doGet(request, response);

        assertEquals("Hello, World!", stringWriter.toString());
    }

    @Test
    public void doPostWithoutName() throws Exception {
        when(request.getRequestDispatcher("response.jsp"))
            .thenReturn(requestDispatcher);

        new HelloServlet().doPost(request, response);

        verify(request).setAttribute("user", "World");
        verify(requestDispatcher).forward(request,response);
    }

    @Test
    public void doPostWithName() throws Exception {
        when(request.getParameter("name")).thenReturn("Dolly");
        when(request.getRequestDispatcher("response.jsp"))
            .thenReturn(requestDispatcher);

        new HelloServlet().doPost(request, response);

        verify(request).setAttribute("user", "Dolly");
        verify(requestDispatcher).forward(request,response);
    }
}

测试创建模拟对象HttpServletRequestHttpServletResponse以及RequestDispatcher类。对于doGet测试,将创建一个PrintWriter使用a的a StringWriter,并将模拟请求对象配置为在getWriter调用该方法时将其返回。调用该doGet方法后,测试将检查返回的字符串是否正确。

对于发布请求,将模拟请求配置为返回给定名称(如果存在)或getRequestDispatcher返回null,并且该方法返回关联的模拟对象。调用该doPost方法将执行请求。然后Mockito验证是否setAttribute使用适当的参数在模拟响应上调用了该方法,并验证了forward在请求分派器上是否调用了该方法。

现在,您可以将Gradle与test任务(或任何build依赖于该任务的任务,例如)一起使用来测试servlet 。

$ ./gradlew build
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:war
:assemble
:compileTestJava
:processTestResources UP-TO-DATE
:testClasses
:test
:check
:build

BUILD SUCCESSFUL

可以通过build/reports/tests/test/index.html常规方式访问测试输出。您应该得到类似于以下结果:

检测结果

添加功能测试

gretty插件与Gradle结合使用,可以轻松地向Web应用程序添加功能测试。这样做,将以下行添加到您的生成脚本:

build.gradle
gretty {
    integrationTestTask = 'test'  
}

// ... rest from before ...

dependencies {
    providedCompile 'javax.servlet:javax.servlet-api:3.1.0'
    testCompile 'junit:junit:4.12'
    testCompile 'org.mockito:mockito-core:2.7.19'
    testCompile 'io.github.bonigarcia:webdrivermanager:1.6.1' 
    testCompile 'org.seleniumhq.selenium:selenium-java:3.3.1' 
}
  • 告诉gretty启动和停止测试服务器
  • 自动安装浏览器驱动程序
  • 使用硒进行功能测试

gretty插件需要知道哪些任务需要服务器的启动和停止。通常,这是分配给您自己的任务的,但是为了使事情简单,只需使用现有test任务即可。

Selenium是用于编写功能测试的流行开源API。2.0版基于WebDriver API。最新版本要求测试人员为他们的浏览器下载并安装WebDriver版本,这很繁琐且难以自动化。该WebDriverManager项目可以很容易地让摇篮句柄,为您办理。

src/test/java目录中,将以下功能测试添加到您的项目中:

src / test / java / org / gradle / demo / HelloServletFunctionalTest.java
package org.gradle.demo;

import io.github.bonigarcia.wdm.ChromeDriverManager;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

import static org.junit.Assert.assertEquals;

public class HelloServletFunctionalTest {
    private WebDriver driver;

    @BeforeClass
    public static void setupClass() {
        ChromeDriverManager.getInstance().setup(); 
    }

    @Before
    public void setUp() {
        driver = new ChromeDriver();               
    }

    @After
    public void tearDown() {
        if (driver != null)
            driver.quit();                         
    }

    @Test
    public void sayHello() throws Exception {      
        driver.get("http://localhost:8080/webdemo");

        driver.findElement(By.id("say-hello-text-input")).sendKeys("Dolly");
        driver.findElement(By.id("say-hello-button")).click();

        assertEquals("Hello Page", driver.getTitle());
        assertEquals("Hello, Dolly!", driver.findElement(By.tagName("h2")).getText());
    }
}
  • 必要时下载并安装浏览器驱动程序
  •  启动浏览器自动化
  • 完成后关闭浏览器
  • 使用Selenium API运行功能测试

此测试的WebDriverManager部分检查二进制文件的最新版本,并在不存在该二进制文件时下载并安装它。然后,该sayHello测试方法将Chrome浏览器驱动到我们应用程序的根目录,填写输入文本字段,单击按钮,然后验证目标页面的标题以及h2标签中是否包含预期的字符串。

WebDriverManager系统支持Chrome,Opera,Internet Explorer,Microsoft Edge,PhantomJS和Firefox。查看项目文档以获取更多详细信息。

运行功能测试

使用以下test任务运行测试:

$ ./gradlew test
:prepareInplaceWebAppFolder UP-TO-DATE
:createInplaceWebAppFolder UP-TO-DATE
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:prepareInplaceWebAppClasses UP-TO-DATE
:prepareInplaceWebApp UP-TO-DATE
:compileTestJava UP-TO-DATE
:processTestResources UP-TO-DATE
:testClasses UP-TO-DATE
:appBeforeIntegrationTest
12:57:56 INFO  Jetty 9.2.15.v20160210 started and listening on port 8080
12:57:56 INFO  webdemo runs at:
12:57:56 INFO    http://localhost:8080/webdemo
:test
:appAfterIntegrationTest
Server stopped.

BUILD SUCCESSFUL

gretty插件会在默认端口上启动Jetty 9的嵌入式版本,执行测试,然后关闭服务器。如果您观看了,您会看到Selenium系统打开一个新的浏览器,访问该站点,填写表格,单击按钮,检查新页面,最后关闭浏览器。

集成测试通常通过创建单独的源集和专用任务进行处理,但这超出了本指南的范围。有关详细信息,请参见Gretty文档

摘要

在本指南中,您学习了如何:

  • 使用warGradle构建中的插件定义Web应用程序

  • 将servlet和JSP页面添加到Web应用程序

  • 使用gretty插件部署应用程序

  • 使用Mockito框架对Servlet进行单元测试

  • 使用gretty和Selenium 对Web应用程序进行功能测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值