我的Java Web之路 - Servlet(1) - 第一个Java Web应用

介绍

上篇介绍了Java类的继承,本篇我们就能够使用继承来编写我们的第一个Java Web应用了。为了简单起见,我们写一个跟Tomcat自带的HelloWorld应用示例基本一样的应用。

所谓麻雀虽小五脏俱全,我们需要掌握的是Java Web应用的基本要素和开发流程。以后无论是多么复杂的Web应用,只要是基于Java Servlet技术的,其底层的这些基本要素和开发流程都不会变,变的是不断在这些基本要素和开发流程之上进行抽象、封装、分离、简化出来的模型、框架、层次、平台等。根本目的当然就是为了消除重复、简化开发流程、细分开发职责、提高开发效率等等。

前面我们已经安装好了JDK、Tomcat和Eclipse。正如之前所述,其实不需要Eclipse也可以进行Java应用程序的开发,Java Web应用也是如此,这些IDE工具只是提高了我们的开发效率而已,正是因为如此,我们才需要使用工具嘛。

新建Java Web工程

在之前文章我的Java Web之路 - Eclipse(1)中介绍过如何创建一个Java工程,基本步骤都差不多,只不过工程类型不一样而已。

首先,我们通过下面两种方式:

  • 菜单栏中的菜单:File -> New -> Project…
  • 工程导航视图的右键菜单:New -> Project…

打开新建工程对话框:
新建Java Web工程.png
之前我们建立的是Java类别里的Java Project,现在我们要选择Web类别里的Dynamic Web Project,为什么叫动态Web呢?因为网页即HTML页面,确切的说是页面中的某些数据,是由Servlet动态生成的。选择后点击Next按钮:
新建Java Web工程2.png
这里只要输入你喜欢的工程名,我输入的是MyFirstJavaWeb,当然也可以是HelloWorld等等,只要符合你的规范即可。

其他使用默认值,这里重点要注意的是Target runtimeDynamic web module version,前者就是配置我们开发的这个Java Web应用所要运行的目标环境,当然指的就是Servlet容器了,当然我们是使用Tomcat这个Servlet容器,还有很多其他的Servlet容器,比如WebSphere、WebLogic、JBoss等等。后者其实配置的就是Servlet技术或者规范的版本,在后面提到的部署描述符里就有该版本号。这两个后面都可以单独配置,现在使用默认值就可以了。

点击Next之后,是配置Java源代码和编译后的class文件的存放位置,使用默认值就可以。

再点击Next之后,是配置Web应用的URL根路径以及Web应用的资源路径,使用默认的即可:
新建Java Web工程3.png
但我们要勾选上Generate web.xml deployment descriptor。这个是是什么意思呢?通俗一点就是为这个Web应用生成一个配置文件(文件名就是web.xml),这个配置文件有个称呼叫部署描述符。顾名思义,它就是描述该Web应用部署时的相关配置,比如你为该Web应用开发的各个Servlet以及它们映射到该Web应用的URL是什么,以后还有过滤器、监听器、安全约束等等,总之就是该Web应用的配置就是了。

那这个配置文件给谁来读取啊?当然就是目标运行环境啊,就是加载该Web应用的Servlet容器啊。

最后点击Finish就成功建立了我们的第一个Java Web工程。

Java Web工程结构

Java Web工程建立好之后,Project Explorer视图(可以在菜单栏Window->Show View中打开)类似这样:
Java Web工程结构.png

  • 第一个是加载的部署描述符,跟最后一个web.xml是相同的;
  • 第二个暂时不理;
  • 第三个就是我们的Java代码,实际上就存在src目录,底下就可以建立我们的各种各样的Java类,包括Servlet类;
  • 第四个暂时不理;
  • build是编译输出目录;
  • WebContent是Web应用的资源目录,底下比较重要的是WEB-INF目录、lib目录和部署描述符。

大家也可以看看文件系统上的Java Web工程的目录结构,跟你建立工程时的配置是相同的:

  • 工程目录\src 是Java源代码的存放位置;
  • 工程目录\build\classes是编译后的class文件的存放位置;
  • 工程目录\WebContent很重要,是Web应用的资源目录,它里面可以存放网页、CSS、JavaScript代码等,这些资源浏览器都可以直接访问,重要的是它里面有一个WEB-INF目录,这里的资源都是浏览器不能直接访问的,比如Java类、JAR包等;
  • 工程目录\WebContent\WEB-INF很重要,部署描述符必须在此目录中,还有一个lib目录;
  • 工程目录\WebContent\WEB-INF\lib是该Web应用Java代码所用到的JAR包,Tomcat需要加载JAR包里面的类;
  • 工程目录\WebContent\WEB-INF\classes刚开始没有,但有了你所开发的Java代码之后,编译的class文件就存放在此处,Tomcat也需要加载这里的类,包括你的Servlet。

静态Web

前面说到我们建立的工程是动态Web工程,既然有动态Web,那么就有静态Web,那么什么是静态Web?可以简单的理解为只有网页,而且网页中的数据对于所有Web用户来说是一样的,无需动态生成的,直接固化在网页中的。这样的Web应用就是静态Web应用。

OK,既然如此,那我们就写一个网页(就是HTML文件、CSS文件和JavaScript文件的组合),我们的这个Web应用应该能够运行了。的确如此,下面我们就在Web资源目录中新建一个HTML文件index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h1>Hello World!</h1>
</body>
</html>

新建文件与新建工程类似,右击WebContent节点的菜单->New菜单选择HTML文件即可,输入合适的文件名,其他默认,点击Finish即可。

Eclipse会帮你生成一部分HTML通用的内容,剩下的就需要我们学习HTML、CSS和JavaScript了。还记得我在文章我的Java Web之路 - Web基础(2)中提到过Web前端三剑客(自己瞎想的词)吗:

  • HTML:主要是负责数据的结构、框架或骨架,表示哪些数据是标题啊、主体啊、导航啊、链接啊、表格啊、段落啊、图片啊、音频、代码啊等。简而言之,就是表示数据是什么。
  • CSS:主要是负责控制数据的样式,所以其英文全称就是Cascading Style Sheets(直译为层叠样式表),就是数据呈现成什么样子,比如字体啊、大小啊、颜色啊、前景啊、背景啊之类的。简而言之,就是表示数据什么样?
  • JavaScript:又是一门语言,也是由浏览器来解释运行,主要是负责动态行为,比如跟用户的交互、跟服务器的交互,事件的捕捉,网页的动态变化等。

我现在只会加个HTML的<h1>标签,这个HTML的<h1>标签就表示里面的内容是一级标题。

这样我们就建立好了一个网页,只不过是一个很粗陋的网页,但原理是一样的,复杂的网页不过是标签更多一些,展示更漂亮一些,能与用户有更多交互而已。关键是现在我怎么把这个Web应用部署到Tomcat上,然后用我的浏览器可以访问到这个网页呢?

Eclipse中配置Tomcat

首先,我们需要在Eclipse中配置我们的Tomcat,让我们的Eclipse能够启动我们安装的Tomcat。在菜单栏中点击:Window(窗口)->Preferences(偏好设置),括号内的是我翻译过来的中文,弹出Preferences对话框:
Eclipse配置Tomcat.png
点击左侧中的Server->Runtime Environment这里就是配置我们的Servlet容器、Web容器、Web服务器、应用服务器。。。总之英文就是Server Runtime Environments,点击右侧的Add…按钮,弹出新建服务器运行环境的对话框:
Eclipse配置Tomcat2.png
我们根据安装的Tomcat版本,选择Apache Tomcat v9.0即可,点击Next:
Eclipse配置Tomcat3.png
我们输入以前安装的Tomcat的安装目录,点击Finish即可看到新建的Tomcat服务器运行环境:
Eclipse配置Tomcat4.png
我们点击Apply and Close即可,本质上就是配置Eclipse指向了Tomcat的安装目录,但我们还需要在Eclipse建立一个服务器才行:
Eclipse配置Tomcat5.png
一般打开了Java EE透视图,Eclipse主界面底部会有一个服务器视图,点击下面的蓝色提示即可建立服务器
Eclipse配置Tomcat6.png
我们只能选择Tomcat v9.0 Server,因为我们只建立了该版本的服务器运行环境,点击Next:
Eclipse配置Tomcat7.png
这里我们可以往新建的服务器中添加和删除我们的Web应用,目前我们就只有一个MyFirstJavaWeb应用,我们可以把它添加进去,就是部署,选中并点击Add:
Eclipse配置Tomcat8.png
最后点击Finish即可。

Eclipse中启动Tomcat

我们建立好了一个服务器之后,它指向了我们安装的Tomcat,现在就可以启动它了。首先我们要把我们的应用发布(英文就是Publish)到服务器上去,每当Web资源包括Java代码有变化,就需要重新发布(英文是Republish),我们右击服务器节点弹出菜单:
Eclipse配置Tomcat9.png
OK,我们点击Publish就可以了,然后点击Start就可以启动我们的Tomcat服务器。也可以在服务器视图顶部右端工具栏中启动服务器。服务器启动后,控制台视图类似这样:
Eclipse启动Tomcat.png
可以看到Tomcat启动过程中打印了很多日志,这与我们直接执行Tomcat安装目录的bin目录下的启动脚本来启动Tomcat是一样的,日志中我们也可以看到CATALINA_BASE等变量,暂不理会这些日志。

现在,我们打开浏览器,在地址栏中输入:http://localhost:8080/MyFirstJavaWeb/
Eclipse启动Tomcat2.png
现在的问题是我们在地址栏输入的只是http://localhost:8080/MyFirstJavaWeb/,并没有明确访问的是index.html这个网页啊?答案就是部署描述符web.xml中指定了我们这个Web应用的首页:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
  <display-name>MyFirstJavaWeb</display-name>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
    <welcome-file>index.htm</welcome-file>
    <welcome-file>index.jsp</welcome-file>
    <welcome-file>default.html</welcome-file>
    <welcome-file>default.htm</welcome-file>
    <welcome-file>default.jsp</welcome-file>
  </welcome-file-list>
</web-app>

同时,这里我们也看到了版本是3.0。所以,我们输入地址http://localhost:8080/MyFirstJavaWeb/index.html也是一样可以访问该网页的。

修改Web应用根路径

我们再来看一下这个URL中的MyFirstJavaWeb部分,其实这个就是我们在新建Web工程的时候配置的Context root,这个也可以修改。

我们右键点击Project Explorer视图中MyFirstJavaWeb应用,弹出右键菜单,点击最下端的Properties,弹出MyFirstJavaWeb应用的属性对话框:
Web应用的根路径.png
在左侧选中Web Project Settings,在右侧即可看到Context root的配置,假设我们把它修改为My,然后点击Apply and Close,然后发布该应用,再启动服务器,中间过程会有一些提示对话框,都是确认根路径修改的,点击肯定的按钮即可。这时浏览器上URL必须是http://localhost:8080/Myhttp://localhost:8080/My/index.html才能访问该网页。

所以,我们现在更加明确了URL的组成,前面是协议、域名和端口号,接着的是Web应用的Context root(中文就叫上下文路径或根路径等),后面的是该Web应用的资源目录中的路径(但是WEB-INF目录中的不可访问),由于index.html直接在资源路径底下,所以Context root直接加上index.html就可以访问该网页了。

所以,Web应用、Web Context、Web Module(模块)有时是通用的。

我的第一个Servlet

上面只是建立了一个静态Web应用,如果只是静态网页,一般不用Tomcat服务器,而是把静态网页部署到Apache这个Web服务器上,Tomcat主要用来加载并执行各种Servlet,说白了就是主要负责计算,所以Tomcat叫应用服务器

下面通过Servlet技术来实现我们的动态Web应用。我们参照以前的步骤新建一个类(我的建议是新建一个文本文档,然后手动编写所有代码):
新建Servlet.png
我们现在已经知道什么是类的继承了,在上图中就可以配置该类的超类Superclass)了,而且我们知道Tomcat示例里HelloWorld类继承的是HttpServlet,所以HelloWorld类也是一个Servlet,但我们点击Browse…按钮弹出的对话框似乎怎么也找不到HttpServlet。好吧,那么我们直接输入HttpServlet看看结果会是什么样子。
新建Servlet2.png
类建立好之后,就自动存放在了src目录底下,包括包的结构。

不过,结果是Eclipse提示HttpServlet不能解析为一个类型,就是找不到这个类的class文件呗!那这个类的class文件在哪呢?答案就是在Tomcat安装目录的lib目录中的servlet-api.jar这个JAR包中。

因为Tomcat既然是Servlet容器,Servlet相关的基础类当然就应该由它来提供啊,总不至于由开发人员再开发一套吧,何况Tomcat要用这些基础类的方法来实现内部流程,就是说不管是HelloWorld这个Servlet,还是HelloKitty这个Servlet,只要是HttpServlet(最顶层的是Servlet接口)的子类,这些内部流程都是通用的,而运行时传给这些流程的对象实际都是子类对象,这就是大名鼎鼎的多态。可见我们只要使用父类的方法实现流程的模板,而为以后的变化继承相应的父类,这样就无需或很少改动流程,这就是设计模式中大名鼎鼎的模板模式

添加Java库

唉,跑题了!我们如何来添加Tomcat的servlet-api.jar这个JAR包呢?我们还是可以在该Web应用的属性对话框中进行配置:
添加Java库.png
依次点击红色圈中的选项即可:
添加Java库2.png
这里选择Server Runtime(即服务器运行时库),点击Next:
添加Java库3.png
这里可以看到我们之前建立的服务器运行环境,选择它并点击Finish即可:
添加Java库4.png
我们可以点击展开刚添加进来的Tomcat库,在这个库中的确可以找到servlet-api.jar这个JAR包,最后点击Apply and Close即可。

Java Build Path这个配置选项经常会用到,以后添加JAR包或者库都是在这个地方。

我们也可以在Project Explorer视图的Java Resources->Libraries中看到多了一个Tomcat库的节点,该节点也可以展开并找到servlet-api.jar这个JAR包。

这时候的Eclipse错误提示变成:
新建Servlet3.png
我们只要在import语句加上包限定名就可以了。

import javax.servlet.http.HttpServlet;

编写Servlet内部的方法

好,现在开始准备编写HelloWorld这个Servlet内部的方法,问题是我们怎么知道要写什么方法呢?我们不是继承自HttpServlet嘛,它内部的方法就相当于制定了一个规范,我们只要覆盖它内部的方法就可以了,而doGet方法就是其中一个:

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter writer = response.getWriter();
		writer.print("<html><head></head><body>"
				+ "<h1>Hello World! Your IP is " + request.getRemoteHost()
				+ "</h1>"
				+ "</body></html>");
	}

我们可以把鼠标放到HttpServlet这个类上,自然会弹出该类的Javadoc,这就是我们以前学的Java三种注释中的其中一种,所以以后我们也要为我们开发的类提供这种注释,这样别人用我们的类时候也可以查看该类的Javadoc。

我们也可以到Java EE文档官方网站查看该类。

好,我们就先编写doGet方法,这个方法就是处理浏览器发给Tomcat的Get请求(还记得我们介绍的HTTP协议常用的Get、Post等方法吗),这里就找到对应的了吧。通常直接在浏览器地址栏直接输入URL的都是HTTP Get请求。

那一个Get请求由Tomcat收到之后,再交给这个Servlet的doGet方法处理,我们如何处理该Get请求呢?当然就是返回一个HTML网页啊,那我们写个HTML文件?这不就跟静态Web一样了吗?

当然不是,我们可以看到doGet方法有一个request和response参数。容易猜到request(即HttpServletRequest类)肯定就是封装了浏览器发过来的请求,我们可以利用Eclipse的自动提示功能,敲 request. 的时候自动弹出它的成员列表,我们选一个getRemoteHost这个方法作为对该请求的回应,所以各个不同IP主机上的浏览器看到的网页都不尽相同,这就是 动态Web 的含义!

然后怎么回应一个HTML网页呢?答案就是response参数(即HttpServletResponse类),我们也可以查看相关Javadoc,看看该类是如何使用的。我们先设置HTTP协议的ContentType这个首部为"text/html",然后通过getWriter方法获取一个writer,利用它打印HTML文档的内容即可。

这里,我们使用了Java String类型的加号连接法,将HTML文档内容各个部分分在各行有利于代码阅读且能连接成一个字符串,中间还加上了浏览器所在主机的IP地址。

好,现在代码是这样的:

package com.example;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;

public class HelloWorld extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter writer = response.getWriter();
		writer.print("<html><head></head><body>"
				+ "<h1>Hello World! Your IP is " + request.getRemoteHost()
				+ "</h1>"
				+ "</body></html>");
	}

}

我们重新发布该Web应用,并启动Tomcat,在浏览器上输入URL地址,咦?URL输入什么地址呢?还是原来的http://localhost:8080/MyFirstJavaWeb/吗?不可能啊,这就Get到了index.html这个网页了啊,肯定还是缺少了什么为HelloWorld这个Servlet指定一个URL地址,这样我们才能向HelloWorld这个Servlet发送Get请求啊!

配置Servlet

前面我们不是提到过部署描述符web.xml吗,它就是用来配置Servlet的,这样Tomcat就可以知道来了一个HTTP请求应该把它交给哪个Servlet来处理。当然还有很多其他可以配置的,暂且不说,大家也可以看看Java Servlet规范

不过,还有另外一种方式可以配置Servlet,那就是Java语言中的注解(英文叫Annotation)。这种配置就不需要XML文件了,而是直接配置在Java代码中,所以修改配置需要重新编译,这也是注解的一个不好的地方。那该怎么配置呢?像下面这样:

package com.example;

import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.WebServlet;

@WebServlet(urlPatterns = {"/hello"}) //这就是注解
public class HelloWorld extends HttpServlet {
	public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		response.setContentType("text/html");
		PrintWriter writer = response.getWriter();
		writer.print("<html><head></head><body>"
				+ "<h1>Hello World! Your IP is " + request.getRemoteHost()
				+ "</h1>"
				+ "</body></html>");
	}

}

这里,我们使用了 @WebServlet 这个注解,它在包javax.servlet.annotation中。注解也是一个类,使用时要加上 @ 符号,同时注解可能会有参数,比如 @WebServlet 这个注解就有 urlPatterns 这个参数,它就是用来配置URL与Servlet的映射关系。这个参数的值也有一定的规范,比如必须使用正斜杠 / 开头,可以使用通配符 * ,还可以映射多个URL(大括号括起来用逗号分开即可)等等。该值与Web服务器的域名端口和该Web应用的 Context root 结合起来就是完整的映射到该Servlet的URL了。

使用注解时,我们可以把这个语句理解为调用该注解的构造函数生成该注解的一个对象,而该构造函数可能有参数。当然这么理解可能不太对,不过至少形式上差不多,主要是便于记忆吧。注解的进一步讨论我们放到后面。下面让我们再一次Publish我们的这个Web应用,然后启动浏览器,这时我们知道在地址栏该输入什么了:

http://localhost:8080/MyFirstJavaWeb/hello

见证奇迹的时刻到了:
第一个Java Web应用.png
浏览器上的显示正如我们的HelloWorld Servlet的代码逻辑,能打印出浏览器所在的主机IP,这就是所谓的动态Web,每个用户看到的网页可能是不一样的。

总结

本篇内容比较多,主要是Java Servlet开发规范和Eclipse中的Java Web开发流程,前者不依赖与Eclipse等IDE工具。

  • Servlet技术就是Servlet规范,包括Servlet容器(引擎)和Servlet API;
  • Servlet API就是各种Servlet类:HttpServlet、HttpServletRequest、HttpServletResponse、ServletException等等,其实还有它们的父类或接口、父类的父类等等,这就是继承层次
  • Java Web开发主要就是通过继承Servlet类来开发实现有自己的业务逻辑的Servlet类,同时Servlet类还负责输出HTML内容,这实际上违反了类的职责单一性原则。直观上看在Servlet类中存在大量打印HTML标签的语句,实在是不美观,如果HTML复杂一些更是难以维护,而且网页的设计Java程序员也不擅长,除非你是全栈工程师。所以这也是MVC框架出现的初衷;
  • Java Web应用的目录结构有规范,所有资源都放在以应用名命名的目录下,下面可以放各种资源,分为可直接访问的和不可直接访问的,不可直接访问的放在WEB-INF目录下,WEB-INF/classes存放我们开发的包括Servlet在内的各种类class文件,WEB-INF/lib存放所使用的库;
  • 每一个Web应用的WEB-INF目录下有一个部署描述符web.xml,用来配置Servlet等内容;
  • 配置Servlet还可以使用注解@WebServlet
  • 注解也可以看做一个Java类,我们可以定义自己的注解;
  • 静态Web可说是没有Servlet,只有静态资源(网页、图片、音视频等)的Web应用;
  • 我们要经常查阅Java的官方文档,包括 SE(标准版)EE(企业版) 的,而Servlet属于EE的一部分。

下面是Eclipse中Java Web开发流程方面的总结:

  • Eclipse中创建Java Web工程是选择工程类型Dynamic Web Project;
  • Eclipse中配置Tomcat先要在菜单Window(窗口)->Preferences(偏好设置)中的Server -> Run Environments中添加你所安装的Tomcat;然后在主界面底部的服务器视图中建立Server;
  • 服务器视图可以对Server添加或删除Web应用、发布或重新发布应用、启动和停止Server等;
  • 一个Server上可以发布多个Web应用,URL中每个Web应用都有一个根路径,根路径之后的叫做资源路径,它就是以应用名命名的目录下的所有文件或目录,但不包括不可直接访问的WEB-INF目录;
  • Web应用的根路径在建立Web工程时可以指定,也可以在该Web工程属性对话框Web Project Settings修改;
  • Servlet类的开发需要配置Servlet的基础类,它由Servlet容器提供,Eclipse中是在该Web工程属性对话框Java Build PathLibraries选项卡中添加Library,其实还可以添加单个JAR包、class文件路径等。一般不能识别某些类的问题都可以看看是否添加了相应的JAR包;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值