【JavaEE】_servlet程序的编写方法

目录

[1. 创建项目](#1. 创建项目)

[2. 引入依赖](#2. 引入依赖)

[3. 创建目录结构](#3. 创建目录结构)

[3.1 在main目录下创建一个webapp目录](#3.1 在main目录下创建一个webapp目录)

[3.2 在webapp目录下创建一个WEB-INF目录](#3.2 在webapp目录下创建一个WEB-INF目录)

[3.3 在WEB-INF目录下创建一个web.xml文件](#3.3 在WEB-INF目录下创建一个web.xml文件)

[3.4 在web.xml中进行代码编写](#3.4 在web.xml中进行代码编写)

[4. 编写代码](#4. 编写代码)

[4.1 在java目录下创建类](#4.1 在java目录下创建类)

[4.2 打印"hello world"](#4.2 打印"hello world")

[4.2.1 在服务器控制台上打印](#4.2.1 在服务器控制台上打印)

[4.2.2 在客户端打印](#4.2.2 在客户端打印)

[4.2.3 在新建类的首行添加注解](#4.2.3 在新建类的首行添加注解)

[5. 打包程序](#5. 打包程序)

[6. 部署程序](#6. 部署程序)

[7. 验证](#7. 验证)

[8. 总结](#8. 总结)

[8.1 使用项目模板创建项目](#8.1 使用项目模板创建项目)

[8.2 使用IDEA的Tomcat插件自动打包](#8.2 使用IDEA的Tomcat插件自动打包)

[8.3 smart tomcat的工作原理](#8.3 smart tomcat的工作原理)

[8.4 关于context path](#8.4 关于context path)

[8.5 404页面](#8.5 404页面)

[8.6 405页面](#8.6 405页面)

[8.7 500页面](#8.7 500页面)


Servlet是一种实现动态页面的技术,是一组tomcat提供的进行web开发API;

注:页面是分为动态页面与静态页面:

静态页面:页面内容始终固定不变,纯HTML;

动态页面:页面内容随输入参数的不同而改变,HTML+数据构成;

写一个Servlet程序,部署到tomcat上,通过浏览器访问得到一个"hello world"字符串:

该程序需要7个步骤:

1. 创建项目

此处需要创建一个maven程序了,maven是一个"工程管理"工具,其主要作用如下:

① 规范目录结构; ② 管理依赖 (如处理使用的第三方库);③ 构建;④ 打包;⑤ 测试;

注意查看maven的项目结构:

2. 引入依赖

引入依赖即引入servlet对应的jar包;

首先进入maven仓库,搜索servlet:https://mvnrepository.com/

选中maven,复制代码将其粘贴至pom.xml文件中:

注意:

(1)复制粘贴的代码是不包含dependencies标签的,需要在project顶级标签下创建dependencies标签后,将复制来的代码粘贴至该标签内

html 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>hello_servlet</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>


</project>

也把这一段配置称为该依赖在maven仓库的坐标

(2)首次使用时字体颜色为红色,说明尚未下载完成,一般只要粘贴进来,idea的maven就会自动刚出发依赖下载,下载结束后则不再是红色字体,如果长时间红色字体仍未变更,可在右侧面板进行强制刷新

3. 创建目录结构

虽然maven已经帮助我们自动地创建了一些目录,但是还不够,此处需要使用maven开发一个web程序,还需要别的目录:

3.1 在main目录下创建一个webapp目录

(Directory)

3.2 在webapp目录下创建一个WEB-INF目录

(方法同上)(Directory)

3.3 在WEB-INF目录下创建一个web.xml文件

(File)

创建完毕后的src目录结构如下:

3.4 在web.xml中进行代码编写

html 复制代码
<!DOCTYPE web-app PUBLIC
        "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
        "http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
    <display-name>Archetype Created Web Application</display-name>
</web-app>

这段代码可以视为固定代码,当前不需要进行调整;

注:(1)servlet程序和以往的代码相比,有一个非常大的区别:没有main方法;

servlet程序类似没有发动机的车厢,想要运行就要靠车头有带动,而tomcat就是车头;

将写好的servlet程序复制粘贴至webapps目录下,就相当于是把车厢挂到车头后了。

tomcat识别其webapps目录下哪些车厢需要靠车头带动,哪些不需要带动,就是靠目录下的WEB-INF/web.xml;

即:web.xml文件的作用是让tomcat能够识别的当前代码为webapp,并进行加载

(2)pom.xml的标红才是插件下载问题,web.xml文件的标红很有可能是idea的误判,判定代码是否正确的唯一方法是运行后查看结果;

4. 编写代码

4.1 在java目录下创建类

此处以HelloServlet为例:

注:① HttpServlet类是servlet api里提供的现成的类,写servlet代码一般都继承该类,继承的主要目的是可以令新建的类针对HttpServelt进行功能扩展,通过重写父类方法的方式实现;

② doGet方法就是一个根据请求计算响应的方法,我们写的这个doGet方法,不需要我们进行手动调用,而是交给tomcat调用,当tomcat收到get请求,就会触发doGet请求

tomcat会构造好两个参数:req和resp,其中:

req就是TCP socket中读出的字符串按照HTTP协议解析得到的对象,这个对象中的属性与HTTP请求报文格式相对应,是tomcat针对请求已经解析好,构造好了的。

resp对象是一个空对象(不是null,只是new了个对象),程序员的任务就是在doGet方法内部实现:根据请求(req)计算响应(resp),resp本质上是一个输出型参数;

③ 在新类继承HttpServlet类后,输入doget并按下Tab键会自动生成一个默认格式,此时在方法内部有super.doGet(req,resp)语句,父类的doGet方法没有实际作用,只是返回了一个错误页面,故而这句需要注释掉

4.2 打印"hello world"

4.2.1 在服务器控制台上打印

java 复制代码
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("hello world");
    }

4.2.2 在客户端打印

java 复制代码
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("hello world");
    }

注:(1)此处的resp.getWriter会获取到一个writer对象,此处的writer对象是从属于resp对象的,此时进行的write操作其实是在往resp的body部分进行写入,等resp对象整个构造好了,tomcat会统一转成HTTP响应的格式,再写socket;

(2)java中分字节流与字符流两类,writer属于字符流的写操作。

流对象不不一定要写入网卡或硬盘,也可以写入内存缓冲区,取决于代码实现的细节;

4.2.3 在新建类的首行添加注解

在新建类首行增加@WebServlet("/hello")注解;

整体编写完毕的完整代码如下:

java 复制代码
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/hello")
// 令当前的HelloServlet类继承自HttpServlet类:
public class HelloServlet extends HttpServlet {
    @Override
//    重写HttpServlet类的doGet方法:
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 该语句只能实现在服务器的控制台中打印:
        System.out.println("hello world");
        // 在客户端实现打印:
        resp.getWriter().write("hello world");
    }
}

注:(1)注解是java中的特殊类,注解可以针对一个类或放阿飞进行额外的解释说明,赋予这个类或方法额外的功能或含义

(2)此处WebServlet注解的作用是:把当前的类和一个HTTP请求的路径关联起来

(3)之前"doGet是tomcat收到GET请求的时候就会调用"这种说法其实并不准确,具体是否要调用doGet,还是得看当前GET请求的路径,不同的路径可以触发不同的代码(即关联到不同的类上);

(4)一个Servlet程序中可以有很多Servlet类,每个Serlet类都可以关联到不同的路径(对应到不同资源),因此此处的多个Servlet就实现了不同的功能

(5)路径与Servlet之间是一一对应的;

5. 打包程序

(1)打包程序即:把程序编辑好,得到一些.class文件(此例中只有一个文件,一个.java文件对应一个.class文件),将这些.class文件打成压缩包即可;

注:jar就是一种.class构成的压缩包,但此处要打的是war包;

① jar包只是一个普通的java程序;

war则是tomcat专属的用来描述webapp的程序

(2)借助maven直接点击即可:

第一步:点击右侧maven展开maven面板选中package,直接双击或右键运行均可:

如果出现错误,则页面会显示具体的错误信息,如果运行一切顺利,则页面如下:

第二步:打包完毕后,包会生成在target目录下,可在左侧目录栏查看:

(3)默认情况下,maven打的是jar包,此处需要打war包,故而需要微调一下pom.xml:

点击pom.xml,在project顶级标签下,增加一个packaging标签和一个build标签:

html 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>hello_servlet</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>

    <dependencies>
        <!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>
<!--以下内容至末尾project标签前均为新增内容-->
    <packaging>war</packaging>
    <build>
        <finalName>hello_servlet</finalName>
    </build>

</project>

其中,packaging标签就是描述打哪种包

build标签中嵌套一个finalName标签,该标签描述的是war包的名字,(可不指定,但默认生成的名字会较复杂);

此时重新操作maven的package选项,在左侧目录栏可见一个新生成的war包:

注:这种手动打包和手动部署的操作也体现了开发与运行分离的思想,直接使用IDEA的三角符号进行运行是本地运行,而不是在另一个服务器上运行;

6. 部署程序

部署程序即:把刚打包好的war包拷贝到tomcat的webapps目录中即可

无论tomcat是在本机还是跨服务器,都是这样拷贝,拷贝完毕后启动tomcat即可;

注:(1)在windows环境下,如果tomcat正在运行,直接拷贝,tomcat也能识别,但是有可能存在bug。实际开发中,tomcat基本都是在linux上运行的,在linux上不存在bug。

(2)tomcat可以自动识别war包并进行解压缩

7. 验证

启动tomcat后,在浏览器中输入url,注意路径的写法:

访问成功后页面如图:

注:(1)在浏览器中输入url后,浏览器就偶早了一个对应的HTTP GET请求,发给了tomcat,tomcat根据第一级路径,确定了具体的webapp,根据第二级路径,确定了调用哪个类,再通过GET / POST方法确定调用HelloServlet的哪个方法:doGet或doPost等等;

(2)也可以在服务器代码处看到日志(tomcat处):

8. 总结

上述步骤是使用Servlet最朴素的步骤,也可以通过一些操作来简化上述过程:

8.1 使用项目模板创建项目

时可以使用项目模板,后续则不必手动创建目录结构了;

但网络限制可能会导致模板下载不完整;

8.2 使用IDEA的Tomcat插件自动打包

  1. 打包与部署程序可以使用IDEA的Tomcat插件,把Tomcat集成到IDEA中,省去手动打包与部署的过程,只需点击运行即可自动打包部署;

基于tomcat插件自动打包部署适用于开发阶段,频繁修改代码频繁验证;

手动打包手动部署适用于上线阶段,发布程序;

  1. IDEA提供了一些API,可以让程序员开发插件,对IDEA的功能进行扩展;

  2. tomcat插件的安装方式如下:

  1. 首次使用smart tomcat需要配置:

(1)点击页面右上角的Add Configuration新增一个配置:

(2)设置tomcat所在路径:

确定后可看到右上角界面新增的配置:

(3)点击三角符号运行即可;

注:(1)IDEA社区版按照上述方式即可安装tomcat插件,IDEA专业版内置了Tomcat Server插件,和Smart Tomcat功能差不多,但不是一个插件,但Smart Tomcat使用更方便;

(2)如果由于网络问题在IDEA中无法直接安装插件,可以去IDEA官网进行下载:

  1. 正常情况下,点击运行后IDEA就会调用tomcat来运行程序了,但是当前代码启动失败:

可通过cmd查看端口情况:

可通过任务管理器(ctrl+shift+esc)查看进程Pid:

关闭tomcat后再通过cmd查看8080端口情况:

即8080端口当前没有进程占用;

此时再运行smart tomcat,即可运行成功:

按照原路径打开,即可显示hello world:

注:(1)不要通过IDEA控制台上的地址访问页面:

该链接不包含servlet path,直接点击访问是404页面

8.3 smart tomcat的工作原理

  1. 查看tomcat的webapps目录下,并没有因为使用smart tomcat就重新生成一个war 包,原目录下的war包是先前使用tomcat打包的。

smart tomcat的工作原理不是自动拷贝war包,即webapps目录内不变,而是通过另一种方式启动tomcat。

2. tomcat支持启动时显式指定一个特定的webapp目录,相当于让tomcat加载单个webapp运行

tomcat直接调用tomcat,让tomcat加载当前项目中的webapp目录

这个过程没有打war包、拷贝、解压缩的过程。

  1. 此时程序是可以正常运行,但像之前一些webapps下的一些已有的内容(如欢迎页面)就不存在了:

8.4 关于context path

访问页面时在127.0.0.1:8080/后增加的第一级路径,

如果是使用tomcat,即直接拷贝war包的方式部署,context path就是war包名(目录名);

如果是smart tomcat的方式部署,context path是可以进行配置的,默认是项目名:

8.5 404页面

布置servlet程序的过程较为繁琐,任何一步出现差错都会导致404页面,易错点有:

(1)url 的 context path 缺失或不匹配;

(2)url 的 servlet path 缺失或不匹配;

(3)web.xml文件内容错误;

(4)webapp没有正确部署;

(5)目录结构以及目录名、文件名错误;

8.6 405页面

405页面表示对应的HTTP方法未实现:

第一种情况:

比如浏览器发了GET请求,但代码中没有重写doGet,就会出现405页面;

在当前HelloServlet.java中注释掉doGet方法后运行,再输入url访问页面就会出现405页面:

第二种情况:

super.doGet()没有注释掉,运行后再按照原url访问页面,也会出现405页面:

因为super.doGet方法的内部实现就是返回405页面:

8.7 500页面

500页面常常是由于Servlet程序抛异常导致的,出现500页面时,日志会明确说明异常调用栈;

比如运行以下代码:

java 复制代码
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String s = null;
        System.out.println(s.length());
    }
}

刷新页面:

注:还有一些其他的出错情况,如:

(1)空白页面:

如果没有写resp.getWriter().writre()方法,即没有给前端返回任何东西,就会出现空白页面;

(2)无法访问此网站:

没有启动tomcat,按原url访问页面就会提示无法访问此网站;

相关推荐
智慧老师几秒前
Spring基础分析13-Spring Security框架
java·后端·spring
lxyzcm2 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
V+zmm1013435 分钟前
基于微信小程序的乡村政务服务系统springboot+论文源码调试讲解
java·微信小程序·小程序·毕业设计·ssm
Oneforlove_twoforjob1 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
xmh-sxh-13141 小时前
常用的缓存技术都有哪些
java
AiFlutter1 小时前
Flutter-底部分享弹窗(showModalBottomSheet)
java·前端·flutter
J不A秃V头A2 小时前
IntelliJ IDEA中设置激活的profile
java·intellij-idea
DARLING Zero two♡2 小时前
【优选算法】Pointer-Slice:双指针的算法切片(下)
java·数据结构·c++·算法·leetcode
小池先生2 小时前
springboot启动不了 因一个spring-boot-starter-web底下的tomcat-embed-core依赖丢失
java·spring boot·后端
CodeClimb2 小时前
【华为OD-E卷-木板 100分(python、java、c++、js、c)】
java·javascript·c++·python·华为od