02-JavaWeb之Servlet及相关知识点

2023-11-17

一、Servlet 简介

Java Servlet 是运行在 Web 服务器(tomcat)或应用服务器上的程序,它可以接收来自 Web 浏览器或其他 HTTP 客户端的请求,并进行结果的响应。

使用 Servlet,可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。

记住几点:
1.servlet是一段Java程序,可以用于接收浏览器发来的请求和给浏览器作出响应。
2.servlet是一套标准和规范,需要按照官方要求进行代码开发。
3.编写servlet需要导入 servlet-api.jar

二、使用idea编写一个servlet

2.1 新建JavaWeb项目

① 新建一个java工程,在工程上右击选择 add framework support… 生成web项目目录结构
在这里插入图片描述

勾选 web application ,并创建web.xml
在这里插入图片描述

最终构建的项目结构如下:

项目名
	|-- src目录
		|-- 包
			|-- 类
	|-- web目录
		|-- 静态资源(html,css,js,图片等,可被浏览器直接访问)
		|-- WEB-INF(WEB-INF目录下的资源受保护的,无法被浏览器直接访问)
			|-- lib (lib目录存项目放所需的jar包)
			|-- web.xml

这里要注意,这是编写代码时的项目结构,项目编写完毕是需要部署到tomcat运行中运行的,部署到tomcat时结构会变化为:

项目名
	|-- 静态资源(html,css,js,图片等,可被浏览器直接访问)
	|-- WEB-INF(WEB-INF目录下的资源受保护的,无法被浏览器直接访问)
		|-- classes (classes目录存放编译后的class文件)
		|-- lib (lib目录存项目放所需的jar包)
		|-- web.xml (web项目的核心配置文件)

2.2 导入servlet的包

从tomcat的lib目录中找到 servlet 的jar包,复制到项目的lib目录中。
在这里插入图片描述

在包上右击选择 add as library ,并选择 level为:project library,设置后如果jar可以展开,就说明添加成功。
在这里插入图片描述

2.3 编写servlet

/**
 * 编写servlet的流程
 * 1.继承 javax.servlet.http.HttpServlet
 * 2.重写 service 方法
 * 3.在web.xml中配置servlet
 */
public class HelloServlet extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet执行了...");
    }
    // 还可以重写 doGet 或者 doPost方法
    // 区别是:doGet方法只能处理get请求,doPost方法只能处理post请求,service方法都可以处理
}

2.4 配置servlet

<?xml version="1.0" encoding="UTF-8"?>
<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">

    <!--配置servlet-->
    <servlet>
        <!--为servlet取别名-->
        <servlet-name>helloServlet</servlet-name>
        <!--配置servlet的全路径-->
        <servlet-class>cn.msk.HelloServlet</servlet-class>
    </servlet>
    <!--配置请求映射关系-->
    <servlet-mapping>
        <!--使用servlet别名-->
        <servlet-name>helloServlet</servlet-name>
        <!--配置url路径-->
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>

</web-app>

2.5 servlet路径写法

<!-- 1.完全匹配,只会配合 /hello 请求  -->
<url-pattern>/hello</url-pattern> 

<!-- 2.模糊匹配, /* 表示匹配所有请求 -->
<url-pattern>/*</url-pattern> 
<!--  /system/* 表示匹配以 /system开头的请求 -->
<url-pattern>/system/*</url-pattern> 

<!-- 3.后缀匹配, *.do 匹配以do结尾的请求 -->
<url-pattern>*do</url-pattern> : 

三、部署项目和测试

3.1 为idea配置tomcat环境

① 选择 add configuration…
在这里插入图片描述
② 点击 + 选择Tomcat Server中的 Local
一定一定注意是 Tomcat Server
在这里插入图片描述
③ 点击 configure… 关联tomcat
在这里插入图片描述

设置tomcat的家目录
在这里插入图片描述

④ 部署项目到tomcat中,点击 deployment -> +号 -> Artifact…
在这里插入图片描述在这里插入图片描述

3.2 启动测试

① 启动tomcat
在这里插入图片描述
② 查看日志,说明启动成功,占用 8080 端口
在这里插入图片描述
③ 测试我们写的 HelloServlet:http://localhost:8080/hello
在这里插入图片描述

四、servlet的执行流程

在这里插入图片描述

五、servlet的生命周期

Servlet 生命周期可被定义为从创建直到毁灭的整个过程。以下是 Servlet 遵循的过程:

  • Servlet 初始化后调用 init () 方法。
  • Servlet 调用 service() 方法来处理客户端的请求。
  • Servlet 销毁前调用 destroy() 方法。

为servlet添加相关方法进行测试:

public class HelloServlet extends HttpServlet {
    //被访问时提供服务的方法
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("HelloServlet执行了...");
    }
    //构造方法
    public HelloServlet(){
        System.out.println("HelloServlet实例化");
    }
    //初始化方法
    @Override
    public void init() throws ServletException {
        System.out.println("HelloServlet初始化");
    }
    //销毁方法
    @Override
    public void destroy() {
        System.out.println("HelloServlet销毁了");
    }
}

测试结论:

  • 默认情况下,servlet是在第一次被访问时实例化并初始化,调用时提供服务,tomcat停止时销毁。
  • 设置了<load-on-startup>1</load-on-startup> servlet就会在tomcat启动时就实例化并初始化,调用时提供服务,tomcat停止时销毁。该值只要大于0即可,值越小优先级越高。
    在这里插入图片描述
  • 相同点:实例化和初始化方法都只走一次,服务方法(service方法)调用就会走,销毁方法只走一次。

六、请求对象 HttpServletRequest

6.1 常用方法

//1.需要重点掌握的方法
(1) String getParameter(String name):根据参数名称,获取对应参数的值;
(2) void req.setCharacterEncoding("UTF-8"):为post请求设置编码,防止中文乱码

//2.其他需要了解的方法
(1)	String getContextPath():获取上下文路径,<Context path="上下文" ../>(2)	String getHeader(String headName):根据指定的请求头获取对应的请求头的值;
(3)	String getRequestURI():返回当期请求的资源路径URI(上下文路径/资源名);
(4)	StringBuffer getRequestURL():返回浏览器请求地址URL;
(5)	String getRemoteAddr():返回请求服务器的客户端的IP;
(6)	String getServletPath():返回请求,<url-pattern>中的值;
(7)	String[] getParameterValues(String name):根据参数名称,获取该参数的多个值;
(8)	Map<String,String[]> getParameterMap():返回请求参数组成的Map集合;
(9) void req.setCharacterEncoding("UTF-8"):能够正确获取post请求的中文参数而不出现乱码;
(10) String getProtocol()):获取协议版本HTTP/1.1
(11) String getMethod()):获取请求方式(GET or POST)
(12) int getServerPort():获取端口号

6.2 请求乱码处理

在获取请求参数时,中文会乱码,处理办法如下:
1.post的处理方式:request.setCharacterEncoding("UTF-8")
2.get的处理方式:tomcat8及以上无需处理,低版本tomcat需要在 server.xml中的Connector标签中进行设置。
在这里插入图片描述

七、响应对象 HttpServletResponse

//设置响应内容编码方式
response.setCharacterEncoding("UTF-8");
//设置响应内容的类型和编码(建议使用)
response.setContentType("text/html;charset=UTF-8");
//获取打印输出流
PrintWriter writer = response.getWriter();
//获取字节输出流
OutputStream outputStream = response.getOutputStream();

八、转发和重定向

8.1 转发-forward

请求转发是较为常用的一种跳转web资源的方式,他是在服务器内部进行的,整个过程浏览器是不知晓的,同时请求转发使用的是同一个request对象,所有他还可以进行参数的传递。
在这里插入图片描述
转发的语法:

request.getRequestDispatcher("跳转地址").forward(request,response);

1.请求转发可以访问WEB-INF下受保护的资源

request.getRequestDispatcher("/WEB-INF/xx").forward(request,response);

2.请求转发不能访问外部资源(不能跨域访问)

//跳转是失败的
request.getRequestDispatcher("http://www.baidu.com").forward(request,response);

3.请求转发可以使用request对象传递参数(使用的是同一个请求对象)

//Servlet1
request.setAttribute("name","tom");
request.getRequestDispatcher("/servlet2").forward(request,response);

Servlet2
String name = request.getAttribute("name"); //可以获取到tom

4.请求转发,浏览器地址栏不会发生变化

8.2 重定向-redirect

在这里插入图片描述

重定向的语法:

response.sendRedirect("跳转地址");

1.重定向是两次请求,所以会产生新的request对象,无法使用request对象传递参数
2.地址栏会变化
3.重定向的状态码是302
4.可以跳转外部资源(允许跨域访问)
5.无法访问WEB-INF下受保护的资源

九、cookie和session

由于http协议是一种无状态的协议(客户端和服务端互相不认识),也就是说只要客户端发来请求,地址是对的,服务端就会接收。但是这是有问题的,因为有些请求必须要用户登录才能访问,http的无状态特性导致它无法记录用户登录状态,因此,就有了cookie和session来进行补齐这个短板。

9.1 cookie

cookie存储在客户端,允许存储key-value形式的键值对,但是value只能是字符串。
cookie一般存储大小为4096字节。而且对于一个站点存储的cookie个数也有限制。

1.cookie原理
类似生活中去理发店办卡,第一次去办好卡以后自己带着卡离开,下一次去的时候带着卡去就可以了,店家看到卡就知道是自己的会员。
在这里插入图片描述

2.创建cookie相关方法

//方法1)创建cookie
Cookie cookie = new Cookie("key", "value");

//方法2)设置cookie过期时间,单位:秒
//正数:在指定时间后过期
//0  :立即删除该cookie
//负数:会话级别的cookie,关闭浏览器时失效
cookie.setMaxAge(60*60*24*7); //7天有效

//方法3)设置cookie的存储路径, 如果设置为 /cookie/xx ,那么/cookie开头的才能获取
cookie.setPath("/"); //建议设置为 / 方便获取

//方法4)将cookie回传给客户端保存
response.addCookie(cookie);

设置了cookie并回传客户端保存,就可以在响应报文中看到cookie的信息
在这里插入图片描述

3.获取cookie相关方法
一旦浏览器中保存了cookie,当浏览器再次发送请求时,cookie会自动发送给服务器。
在这里插入图片描述

//获取cookie
Cookie[] cookies = request.getCookies();
//遍历cookie获取key和value
for (Cookie c:cookies){
    String name = c.getName(); //获取cookie的key
    String value = c.getValue();//获取cookie的value
}

9.2 session 会话对象

session存储在服务器端,允许key-value的键值对,value是Object类型。
session对于存储个数和大小无限制。

1.session相关方法

//获取session
HttpSession session = request.getSession();
//向session中设置值
session.setAttribute("username","tom");
//从session中获取值
String username = (String)session.getAttribute("username");
//设置session过期时间,单位:秒, 默认过期时间为30分钟
session.setMaxInactiveInterval(60*30);
//销毁session
session.invalidate();

过期时间也可以在tomcat的配置文件中进行修改:tomcat/conf/web.xml

<session-config>
	<session-timeout>30</session-timeout>
</session-config>

2.session的原理
在这里插入图片描述
由此可以看出,session的运行需要cookie的协助才能完成。

利用session我们可以实现用户登录信息的保存。大致实现思路是:用户登录后将信息保存在session中,当下次请求过来时,尝试从session中获取用户信息,能获取到表示已经登录,没有获取到表示用户没有登录过。

十、Filter过滤器

10.1 介绍

  • Filter被称为过滤器,是Servlet2.3新增的一个特性,Filter在Servlet之前执行,因此开发人员可以通过Filter技术,能够实现对所有Web资源的管理,如实现权限访问控制、过滤敏感词汇等操作。在这里插入图片描述

  • Filter 过滤器它是 JavaEE 的规范,也就是一个接口。

10.2 编写Filter

编写Filter:

/**
 * 1.实现Filter接口,重写相关方法
 * 2.在web.xml中配置Filter
 */
public class MyFilter implements Filter {
    //构造器: tomcat启动就执行,只走一次
    public MyFilter(){
        System.out.println();
    }
    //初始化方法:tomcat启动就执行,只走一次
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        System.out.println("MyFilter初始化了");
    }
    //doFilter方法:请求被调用时执行
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("MyFilter执行了");
        //执行doFilter方法,请求才会继续向后执行,否则走到filter这儿就不会向后执行了
        filterChain.doFilter(request,response);
    }
    //销毁方法:tomcat关闭时执行
    @Override
    public void destroy() {
        System.out.println("MyFilter销毁了");
    }
}

在web.xml 配置过滤器:

<filter>
    <!--别名-->
    <filter-name>myFiler</filter-name>
    <!--过滤器的全限定名-->
    <filter-class>cn.msk.filer.MyFilter</filter-class>
</filter>
<filter-mapping>
    <!--别名-->
    <filter-name>myFiler</filter-name>
    <!--匹配所有路径-->
    <url-pattern>/*</url-pattern>
</filter-mapping>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

02-JavaWeb之Servlet及相关知识点 的相关文章

  • Eclipse 在源代码管理中保存操作

    我们希望找到一种在签入之前执行代码标准的 轻量级 方法 我们真的很喜欢使用 Eclipse 内置的想法保存操作 go to Preferences gt gt Java gt gt Editor gt gt Save Actions 其中有
  • org.apache.sling.api.resource,version=[2.3,3) -- 无法解析

    您好 我无法访问我的项目内容 我已经上传了从 CQ 访问内容所需的所有包 我唯一能看到的是 org apache sling api resource version 2 3 3 无法解析 这是否是异常的原因 如果是 请告诉我如何解决 中Q
  • Android在排序列表时忽略大小写

    我有一个名为路径的列表 我目前正在使用以下代码对字符串进行排序 java util Collections sort path 这工作正常 它对我的 列表进行排序 但是它以不同的方式处理第一个字母的情况 即它用大写字母对列表进行排序 然后用
  • 运行具有外部依赖项的 Scala 脚本

    我在 Users joe scala lib 下有以下 jar commons codec 1 4 jar httpclient 4 1 1 jar httpcore 4 1 jar commons logging 1 1 1 jar ht
  • wait() 在游戏中如何工作?

    在 playframework 的文档中here http www playframework org documentation 1 2 1 asynchronous已写 public static void loopWithoutBlo
  • 如何在不超过最大值的情况下增加变量?

    我正在为学校开发一个简单的视频游戏程序 我创建了一个方法 如果调用该方法 玩家将获得 15 点生命值 我必须将生命值保持在最大值 100 并且由于我目前的编程能力有限 我正在做这样的事情 public void getHealed if h
  • 如何安全地解决这个 Java 上下文类加载器问题?

    我的数百名用户中只有一位在启动我的 Java 桌面应用程序时遇到问题 他只有大约三分之一的时间开始 另外三分之二的时间在启动时抛出 NullPointerException Exception in thread AWT EventQueu
  • 我需要什么库才能在 Java 中访问这个 com.sun.image.codec.jpeg?

    我正在用java创建一个图像水印程序 并导入了以下内容 import com sun image codec jpeg JPEGCodec import com sun image codec jpeg JPEGEncodeParam im
  • 使用 AES SecretKey 的 Java KeyStore setEntry()

    我目前正在 Java 中开发一个密钥处理类 特别是使用 KeyStore 我正在尝试使用 AES 实例生成 SecretKey 然后使用 setEntry 方法将其放入 KeyStore 中 我已经包含了代码的相关部分 The KS Obj
  • hibernate锁等待超时超时;

    我正在使用 Hibernate 尝试模拟对数据库中同一行的 2 个并发更新 编辑 我将 em1 getTransaction commit 移至 em1 flush 之后我没有收到任何 StaleObjectException 两个事务已成
  • Java 中的“Lambdifying”scala 函数

    使用Java和Apache Spark 已用Scala重写 面对旧的API方法 org apache spark rdd JdbcRDD构造函数 其参数为 AbstractFunction1 abstract class AbstractF
  • Java整数双除法混淆[重复]

    这个问题在这里已经有答案了 方案1 int sum 30 double avg sum 4 result is 7 0 not 7 5 VS 方案2 int sum 30 double avg sum 4 0 Prints lns 7 5
  • Struts 2 + Sitemesh 3 集成 - FreemarkerDecoratorServlet 中的 NPE

    我将 Struts 2 版本 2 3 14 3 与 Sitemesh 3 版本 3 0 alpha 2 一起使用 并且在某些情况下遇到 NullPointerException 首先 这是我的 web xml 中的 struts2 site
  • Cucumber Java 与 Spring Boot 集成 - Spring @Autowired 抛出 NullPointer 异常

    我正在为 Spring boot 应用程序编写 cucumber java 单元测试来测试每个功能 当我与 Spring Boot 集成时 Autowired 类抛出 NullPointer 异常 Spring Boot应用程序类 Spri
  • 我可以创建自定义 java.* 包吗?

    我可以创建一个与预定义包同名的自己的包吗在Java中 比如java lang 如果是这样 结果会怎样 这难道不能让我访问该包的受保护的成员 如果不是 是什么阻止我这样做 No java lang被禁止 安全管理器不允许 自定义 类java
  • 游戏内的java.awt.Robot?

    我正在尝试使用下面的代码来模拟击键 当我打开记事本时 它工作正常 但当我打开我想使用它的游戏时 它没有执行任何操作 所以按键似乎不起作用 我尝试模拟鼠标移动和点击 这些动作确实有效 有谁知道如何解决这个问题 我发现这个问题 如何在游戏中使用
  • Trie 数据结构 - Java [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 是否有任何库或文档 链接提供了在 java 中实现 Trie 数据结构的更多信息 任何帮助都会很棒 Thanks 你可以阅读Java特里树
  • 如何从 Maven 存储库引用本机 DLL?

    如果 JAR 附带 Maven 存储库中的本机 DLL 我需要在 pom xml 中放入什么才能将该 DLL 放入打包中 更具体地举个例子Jacob http search maven org artifactdetails 7Cnet s
  • 在 RESTful Web 服务中实现注销

    我正在开发一个需要注销服务的移动应用程序 登录服务是通过数据库验证来完成的 现在我陷入了注销状态 退一步 您没有提供有关如何在应用程序中执行身份验证的详细信息 并且很难猜测您在做什么 但是 需要注意的是 在 REST 应用程序中 不能有会话
  • 如何修复:“无法解析类型 java.lang.CharSequence。它是从所需的 .class 文件间接引用的”消息? [复制]

    这个问题在这里已经有答案了 我正在尝试使用这个字符串 amountStr amountStr replace replace replace 但我收到一条错误消息 我知道我收到的错误消息是因为我刚刚发布的字符串已过时 所以我想知道该字符串的

随机推荐

  • C/C++的头文件 / 源文件 / 条件编译 / 多文件编译

    C C 的头文件 源文件 条件编译 多文件编译 头文件 头文件的定义与作用 include编译指令 头文件实例 源文件 条件编译 什么是条件编译 为什么要用条件编译 条件编译的使用 多文件编译 总结 头文件 头文件的定义与作用 之前我的博客
  • 【BLE】蓝牙外围设备升级(OTA)

    目录 需求分析 升级协议交互 协议具体定义 协议交互进一步解读 一个校验单位 4K 的具体传输方式 方案实现 总结 需求分析 本案例中 智能手表作为中央设备对心率带通过BLE进行升级 这里手表首先要通过某种方式获得心率带的固件 然后通过BL
  • 好的技术设计文档应该包括什么

    好的技术设计文档应该包括 项目背景和目标 总体架构和系统模块划分 数据流程和数据存储 系统安全性和数据安全性 性能和可伸缩性 接口和协议规范 部署和运维方案 项目风险和解决方案 测试和验收计划 版本控制 迭代计划和文档管理策略
  • 【脚本工具】python修改xml文件中类别的名称和删除指定的类别

    功能 能够删除xml中不需要的类别标签 和替换制定的类别名称 使用方法 1 修改origin ann dir 原始xml文件夹路径 2 修改new ann dir 保存新xml的文件夹路径 3 需要修改和删除的类别名称 usr bin en
  • 按钮提交在url后添加字段_在输入字段上定向单击“清除”按钮(X)

    按钮提交在url后添加字段 jQuery makes it easy to get your project up and running Though it s fallen out of favor in recent years it
  • :nth-of-child和:nth-of-type

    nth of child 用法 nth of child n n可以为数字或者表达式 例如2n 1 指的是奇数项 介绍 第n个孩子 例如 div nth of child 1 等同于 div first of child div的第一个孩子
  • Hadoop的伪分布式运行模式

    Hadoop运行模式包括 本地模式 伪分布式模式 以及完全分布式模式 1 本地模式 安装简单 在一台机器上运行服务 几乎不用做任何配置 但仅限于调试用途 没有分布式文件系统 直接读写本地操作系统的文件系统 2 伪分布式模式 在单节点上同时启
  • typescript—第七天,命名空间

    没有命名空间时的问题 先写一下这样代码 用类的形式在index html中实现header content和Footer部分 类似我们常说的模板 在page ts文件里 写出下面的代码 class Header constructor co
  • 简述 RSA 加密算法实现过程

    银行密码系统安全吗 质数 素数 到底有啥用 李永乐老师11分钟讲RSA加密算法 2018最新 哔哩哔哩 bilibili 质数 和 欧拉函数 公钥 范围 且
  • Python 爬虫学习笔记(十(4))scrapy链接提取器CrawlSpider

    CrawlSpider也可以这样用 对每一个提取出的链接都调用某些操作 创建项目 scrapy startproject 项目的名字 跳转到scrapy文件夹的目录下 创建爬虫文件 语句和之前不同 scrapy genspider t cr
  • Java读取resource目录下图片插入excel导出

    1 将图片放在resoure目录下 2 读取图片并插入excel private void monthContractRow1 Sheet sheet CellStyle style1 String language Workbook wo
  • ElementUI常用组件之布局组件

    安装elementui npm i element ui S 配置ElementUI 1 main js中 引入elementUI 共分三步走 a import element ui b import css文件 c use Element
  • jQuery中$ $()与$(document) this与$(this)三个的区别

    是jquery专用的特殊符号 bai可以说所有dujquery函数的调用都是从 开始的 在jquery里面表示一zhi个选择器 括号dao里面填写一定的表达式就可以选中你想要的元素 jquery的选择器除了能很好地遵循css的表达式外 还额
  • Ubuntu 无法进行SSH连接,开启22端口

    我们在VM中安装好Ubuntu 虚拟机后 经常需要使用Xshell等工具进行远程连接 但是会出现无法连接的问题 原因是Ubuntu中默认关闭了SSH 服务 1 查看Ubuntu虚拟机IP地址 命令 ifconfig 2 利用XShell等工
  • 点击按钮改变颜色 模型动画暂停继续功能

    using System Collections using System Collections Generic using UnityEngine using UnityEngine UI using DG Tweening publi
  • C语言关键字必备练习题

    1 作业标题 642 关于C语言关键字说法正确的是 作业内容 A 关键字可以自己创建 B 关键字不能自己创建 C 关键字可以做变量名 D typedef不是关键字 答案解析 C语言关键字 C语言定义的 具有特定含义 专门用于特殊用途的C语言
  • 【c++】内存四区(代码区、全局区、栈区、堆区)

    文章目录 内存分区模型 代码区 全局区 栈区 堆区 内存分区模型 c 程序在执行时 将内存大方向划分为4个区域 代码区 存放函数体的二进制代码 有操作系统进行管理 全局区 存放全局变量和静态变量以及常量 栈区 由编译器自动分配释放 存放函数
  • C++ 产生随机数

    推荐一个博客 以下转载该博客部分内容 主要代码 include
  • JSP、JSTL标签

  • 02-JavaWeb之Servlet及相关知识点

    一 Servlet 简介 Java Servlet 是运行在 Web 服务器 tomcat 或应用服务器上的程序 它可以接收来自 Web 浏览器或其他 HTTP 客户端的请求 并进行结果的响应 使用 Servlet 可以收集来自网页表单的用