Servlet简介和工程搭建

JavaEE是Java中用于构建企业级应用程序的标准化平台,JavaEE提供了一系列的API规范,用于开发和部署大型、分布式、可扩展的企业级应用程序。Servlet规范则是JavaEE中最重要的一部分,它规范了编写Java服务端应用程序处理Web请求和响应的API标准。基于这套Servlet标准开发的服务端应用程序可以部署在任何实现Servlet规范的Servlet应用容器或JavaEE应用容器中。

在Java生态里当下十分流行的Struts2等Web框架也都是在Servlet规范之上实现的,即使我们使用这些框架来编写程序也同样脱离不开Servlet规范,足以见得Servlet规范的重要性。这篇笔记我们基于JavaEE8来介绍Servlet规范和JavaWeb应用程序的开发技术,本系列笔记基于最新的Wildfly14应用容器和JavaEE8编写,由于不涉及EJB,实际上所有示例代码在Tomcat9或其它JavaEE8兼容的应用容器下也同样能够正常运行。

JavaEE应用容器和JavaWeb工程

在具体开发JavaWeb程序之前,我们必须了解什么是JavaEE应用容器和JavaWeb工程。

太阳微系统公司(Sun Microsystems)设计JavaEE时的一个聪明之处是JavaEE本身是一组规范,对应到Java代码可以简单理解为就是一组接口(Interface),而具体的功能则需要编写在实现类中,JavaEE不直接提供这些实现类,而是由JavaEE应用服务器提供。我们基于JavaEE标准编写的程序会部署到应用服务器中,一个应用服务器可以部署多个应用程序,每个应用程序存在于自己的上下文(Context)中,因此应用服务器也被称为JavaEE程序的“容器”。此外,JavaEE应用容器有时也被称为Java应用中间件(Middleware),因为它们在软件架构中处于应用程序和操作系统之间的层次,充当着连接和协调两者的桥梁。常见的JavaEE应用容器有开源的JBoss(新版本改名为Wildfly)、GlassFish,以及商业中间件Websphere(IBM)、Weblogic(Oracle)等。

由于一些历史原因,JavaEE中的EJB等规范使用相对不是那么多,而Servlet规范却是几乎所有JavaWeb程序的基石,因此出现了Tomcat这种专注于Servlet和JSP的应用服务器,它也被称为轻量级的Servlet容器。实际上,相对于前面说的那些全功能JavaEE容器,Tomcat的使用更加广泛,不过注意Tomcat并不支持EJB规范,因此如果你用到了EJB则还是需要考虑使用全功能的JavaEE容器。

基于Servlet/JSP技术编写的Web程序就是我们常说的JavaWeb工程,它们最终的构件是一个.war文件(Web Archive,俗称War包),本质是一个包含了程序字节码和配置信息的ZIP压缩包,这个War包最终会被上传到Servlet应用容器或JavaEE应用容器中并被加载执行。

Servlet规范组件

Servlet规范围绕着3个重要的组件展开。

Servlet:在Java中,对应于Applet客户端小程序Servlet可以理解为服务端小程序,它是处理Web请求最基础的组件,它获取HTTP请求内容,经过一系列处理后返回HTTP响应。

Filter:Filter即过滤器,它使用了AOP思想,能够在请求被Servlet处理前和处理后进行一些额外操作,例如认证鉴权、注入通用信息等。

Listener:Listener即监听器,它能够用于监听Web应用的生命周期和事件,比如程序启动、属性变化等。

开发JavaWeb应用程序实际上就是围绕着这3个组件进行的。

下载和安装Wildfly14

Wildfly是RedHat开源的一款开源JavaEE应用容器,它是JBOSS应用服务器的最新版本,旨在提供一个灵活、可扩展且高度可定制的运行环境,用于部署JavaEE应用程序,其Servlet容器部分使用的Undertow则以性能强大著称。

为了安装Wildfly,首先我们要保证我们的操作系统已经安装了JDK8并正确配置了环境变量。Wildfly的下载安装非常简单,我们直接进入Wildfly官方网站下载对应的.tar.gz包或.zip包,然后将其解压到一个目录即可。注意不要使用Linux的软件源安装,它会注册系统服务,通常用于生产环境部署JavaEE程序,在开发阶段还是建议使用最基础的压缩包方式安装。Wildfly安装包解压后不需要编辑任何配置文件,我们稍后会将其集成到Eclipse集成开发环境中,在开发阶段对Wildfly常用的配置都可以在IDE的图形界面中进行修改。

更多内容可以参考Wildfly相关章节。

基于Eclipse开发JavaEE程序

在实际开发中,JavaWeb工程一般使用IDE进行开发,NetBeansEclipse都是当下比较好用的Java集成开发环境,而且它们都是完全免费可商用的!当然你不是不可以使用Notepad或Vim来开发,但这些文本编辑器相对于IDE缺失很多方便的功能,何必自讨苦吃呢。

此外对于企业级Java项目,我们通常使用AntMaven管理工程的依赖库和构建配置,实际上Eclipse或Netbeans这些IDE本身的功能覆盖了这些部分,我们也可以不使用Maven这类独立的构建工具直接使用IDE导出War包,然而构建工具解耦了对于IDE的强依赖,这非常重要,因为这意味着你和你的同事可以使用不同的IDE导入同一个工程,在类似Jenkins这样的持续集成服务器上构建程序也要求你必须使用Ant或Maven这样的技术,而非基于IDE来构建。

总而言之,本章节的后续内容都是以Eclipse和Maven为标准进行介绍的。

创建JavaWeb工程

在Eclipse中创建JavaWeb工程非常简单,我们直接选择File -> New -> Maven Project创建一个Maven工程,在Maven项目骨架的选择界面选择使用maven-archetype-webapp,之后根据提示输入项目的groupId、artifactId等参数即可。当然,我们不是不可以创建空项目,只是使用骨架模板会生成JavaWeb项目通常需要的一些目录结构和配置文件内容,因此更方便一些。

一个基于Maven的JavaWeb工程的基本目录结构如下。

|_ src
    |_ main
        |_ java         # Maven程序源代码文件夹
        |_ resources    # Maven程序配置文件夹
    |_ test
        |_ java         # Maven程序单元测试源代码文件夹
        |_ resources    # Maven程序单元测试配置文件夹
    |_ webapp           # Web相关资源文件,可以被用户直接访问
        |_ META-INF     # 可选,Java程序相关元数据信息,JavaWeb程序中还可能包括Servlet容器的程序上下文(Context)参数配置等
        |_ WEB-INF      # 必须存在,包含JavaWeb程序的配置文件和运行时字节码类文件等
            |_ web.xml  # 必须存在,JavaWeb应用程序的部署描述配置文件
|_ pom.xml              # 必须存在,Maven工程的构建配置文件

注意webapp目录中包含了JavaWeb工程相关的Web资源文件,其中的内容例如HTML、CSS、JavaScript等资源都是可以被用户直接访问的,JSP则会被JSP引擎解析执行;然而WEB-INF目录则不同,其中的内容是禁止用户访问的,一些敏感的配置文件、作为MVC模板的JSP等我们不希望被用户直接访问到的文件可以放置在WEB-INF下。

为了开发Servlet程序,我们还需要在pom.xml中引入JavaEE SDK相关的Maven依赖。注意该依赖的作用域是provided的,因为它在JavaEE容器中已经提供了,这里通过Maven引入只是为了在开发阶段能够正确编译。

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>8.0.1</version>
    <scope>provided</scope>
</dependency>

如果你不使用JavaEE的所有功能仅使用Servlet,你也可以仅引入Servlet规范的Maven依赖。

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>4.0.1</version>
    <scope>provided</scope>
</dependency>

此外,工程创建后默认的web.xml使用的Servlet版本是2.3,已经非常老旧了,我们这里将其换成当前最新的Servlet4.0版本。

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
                      http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
  version="4.0"
  metadata-complete="false">
</web-app>

注意:指定metadata-complete="false"配置能够开启Servlet3.0的注解配置功能,但会稍微增加一些启动时间;如果将其设置为true,Servlet等Web组件则只能通过web.xml进行配置。

Eclipse配置JDK8和Wildfly14

Window -> Preferences中选择Java -> Installed JREs,我们在此指定JDK8的安装路径。

然后点击Java -> Compiler将编译级别修改为1.8版本。

之后我们还需要添加Wildfly应用服务器,点击Servers面板中的添加按钮,根据提示添加Wildfly的安装路径即可(该操作可能会自动安装一些插件,在新版本Eclipse中,安装插件的速度可能较慢,需要耐心等待)。如果你使用Tomcat9或其它的JavaEE/Servlet容器,配置方法也是类似的。

添加完成后,在Servers列表中的Wildfly14上点击右键,选择Add and Remove...可以添加或移除部署到该应用服务器的工程,我们这里需要将当前的工程添加到Wildfly中。

双击Servers列表中的Wildfly14可以进入配置界面,启动超时设置、启动JVM参数等都可以在这里找到。例如一些大项目启动很慢,我们就可以在这里的Timeouts配置里编辑Wildfly的启动超时时间。

最后还有一个可能用到的配置,我们点击工程面板中的工程,右键选择Properties打开工程属性面板,然后选择Web Project Settings,在这里我们可以配置工程的ContextPath。例如我这里的ContextPath名字是demoweb,那么当它部署到IDE集成的应用服务器后就需要以/demoweb作为基础路径来访问。

编写Demo程序

下面我们编写一个最简单的Servlet来作为示例。

package com.gacfox.demo.demoweb;

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 = "DemoServlet", urlPatterns = "/demo")
public class DemoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        String msg = "Served at: " + request.getContextPath();
        response.getWriter().append(msg);
    }
}

代码中我们创建了一个DemoServlet类,它继承HttpServlet类并覆写了doGet()方法,该方法用于处理HTTP的GET请求。注意我们的类上还标注了@WebServlet注解,在Servlet早期版本中所有的Servlet组件必须明确的配置到web.xml配置文件中,但Servlet3.0引入了基于注解扫描加载Servlet组件的功能,因此我们可以直接使用标注注解的方式声明Servlet,此时Servlet容器也能正确的找到Servlet类并实例化和加载。

doGet()方法内部的逻辑很简单,它调用response.getWriter().append()向HTTP的响应输出流写入了一些文本信息。

运行JavaWeb工程

运行该JavaWeb程序只需要在Eclipse的Servers面板中右键点击Wildfly9服务器,然后选择Start就行了,服务器的启动日志可以在Console面板中看到。

服务器启动成功后,我们可以使用浏览器访问http://localhost:8080/demoweb/demo路径,查看Servlet的输出内容。

注意:/demoweb是我们程序的ContextPath,它可以在项目属性面板中进行配置,如果你的项目名字和我不同,通常这个ContextPath也是不同的;/demo是Servlet配置的响应路径,在之前的代码中它通过@WebServlet注解的urlPatterns属性指定。两者合并到一起就是我们图中浏览器访问的路径。

部署JavaWeb工程到服务器

正式部署JavaWeb前,我们需要将工程打包为War文件。由于我们使用Maven作为构建工具,因此打War包需要执行Maven命令mvn package,我们可以在命令行中执行该命令,或者在Eclipse中我们也可以在项目上右键选择Run As -> Maven build...,然后输入构建目标命令package,运行后即可将JavaWeb工程构建为War包。

得到War文件后,最简单的部署方式就是将其黏贴到Wildfly的standalone/deployments目录即可,如果Wildfly服务器正确配置了热部署,我们的JavaWeb工程会自动被加载。对于一些更复杂的商业JavaEE项目则可能需要在管理控制台等位置上传War包并配置一些额外的内容,这些内容将在其它章节详细介绍。

作者:Gacfox
版权声明:本网站为非盈利性质,文章如非特殊说明均为原创,版权遵循知识共享协议CC BY-NC-ND 4.0进行授权,转载必须署名,禁止用于商业目的或演绎修改后转载。
Copyright © 2017-2024 Gacfox All Rights Reserved.
Build with NextJS | Sitemap