Servlet详解(Servlet源码)

news2024/9/9 4:40:02

Servlet

Servlet是运行在Web服务器或应用服务器上的小程序,它作为来自Web浏览器或其他HTTP客户端的请求和HTTP服务器上的数据库或应用程序之间的中间层。Servlet能够接收来自客户端的基于HTTP协议的请求,并且对请求进行响应。
Servlet是用来处理客户端请求并产生动态网页内容的Java类。
通常Servlet特指HttpServlet,用来接受浏览器的访问请求,浏览器最常用的请求为GET和POST方式,还有其它五种,而HttpServlet分别有七个方法(PUT、DELETE、HEADER、TRACE、OPTION)处理这些类型的请求,另有一个是J2EE不支持的,是CONNECT。Servlet是J2EE规范中的重要成员,是构成WEB的重要组件
Servlet是JavaEE规范中的技术之一,是Java开发中最重要的动态资源之一。

Servlet生命周期

Servlet有良好的生存期的定义,包括加载和实例化、初始化、处理请求以及服务结束。这个生存期由javax.servlet.Servlet接口的init,service和destroy方法表达。 Servlet被服务器实例化后,容器运行其init方法,请求到达时运行其service方法,service方法自动派遣运行与请求对应的doGet,doPost等,当服务器决定将实例销毁的时候调用其destroy方法。

Servlet的执行流程

客户端发起请求:客户端(如浏览器)向服务端发起HTTP请求。
服务器解析请求:Tomcat服务器通过解析请求地址(URL),找到对应的web应用,并解析出客户端想访问的web资源。
加载Servlet:如果发现Servlet是第一次访问,服务器就会加载Servlet,创建Servlet对象。
初始化:调用Servlet的init()方法,进行初始化操作。默认情况下,Servlet对象会在第一次被访问的时候初始化,对应的init()方法得到执行,并且只会执行一次。
处理请求:调用Servlet的service()方法处理客户端的请求。每当有一次来自客户端的请求,Tomcat服务器会开启一个新的线程调用service()方法。
响应请求:service()方法执行完后,服务器会响应数据给客户端浏览器。
销毁:当服务器正常关闭时,Servlet对象会被销毁,对应的destroy()方法执行,并且只会执行一次。

Servlet的创建方式

Servlet的创建主要有三种方式:
实现Servlet接口:通过实现Servlet接口,实现所有抽象方法。这种方式支持最大程度的自定义,但通常不推荐,因为需要实现的方法较多。
继承GenericServlet抽象类:GenericServlet实现了Servlet接口,但必须与协议无关。继承此类后,需要重写service()方法,其他方法可以选择重写。这种方式让开发Servlet变得简单,但和HTTP协议无关。
继承HttpServlet抽象类:HttpServlet继承自GenericServlet,并基于HTTP协议进行了封装。继承此类后,需要重写doGet()和doPost()等方法。这种方式表示请求和响应都要和HTTP相关,是最常用的方式。

Servlet的配置方式

Servlet的配置主要有两种方式:
web.xml文件配置:在web应用的web.xml文件中配置Servlet的映射关系。
注解配置:使用@WebServlet注解直接在Servlet类上进行配置,这种方式简化了配置过程,是现代开发中的主流方式。

Servlet的生命周期

Servlet的生命周期从创建开始,直到销毁结束。主要包括以下几个阶段:
加载和实例化:当Servlet容器启动时,或者在请求到达时Servlet容器首次调用Servlet的service()方法时,Servlet容器会加载并实例化Servlet。
初始化:容器调用Servlet的init()方法进行初始化。
请求处理:对于到达的客户端请求,Servlet容器会创建代表请求的HttpServletRequest对象和代表响应的HttpServletResponse对象,然后调用Servlet的service()方法。service()方法会根据请求的方式(GET、POST等)调用相应的doXXX()方法(如doGet()、doPost())。
销毁:当Servlet容器关闭或Web应用被卸载时,Servlet容器会调用Servlet的destroy()方法进行销毁。

Servlet的用途

Servlet主要用于处理客户端的请求,生成动态网页内容,并与后端的数据库或其他应用进行交互。它可以读取客户端发送的显式数据(如HTML表单数据)和隐式数据(如cookies、媒体类型等),处理这些数据,并生成响应发送给客户端。Servlet还可以与Java类库的其他部分进行交互,如通过sockets和RMI机制与applets、数据库或其他软件进行通信。

Servlet的线程安全问题

由于Servlet采用的是单例模式(即Servlet对象从始至终都只会创建一次),而一个浏览器就代表一个线程,多个浏览器就是多线程。因此,当存在成员变量时,多个线程并发访问此变量就容易出现线程安全问题。解决线程安全问题的方案包括:
改变共享属性:将成员变量变成局部变量。
改变可变属性:用final修饰成员变量,使其成为常量。
使用同步锁:虽然可以解决线程安全问题,但会降低Servlet的性能,因此通常不推荐在Servlet中使用同步锁。
实现SingleThreadModel接口:虽然可以让Servlet引擎以单线程模式调用service()方法,但这种方式并不推荐,因为它会降低Servlet的并发处理能力。
综上所述,Servlet是Java Web开发中非常重要的技术之一,它通过处理HTTP请求和响应,实现了Web应用的前后端交互。在使用Servlet时,需要注意其生命周期、配置方式、线程安全问题等方面。

Servlet 源码

Servlet 是 Java EE 中处理服务器端请求和响应的核心组件。通过 Servlet 接口、GenericServlet 类和 HttpServlet 类,我们可以实现各种功能的Servlet应用。HttpServletRequest 和 HttpServletResponse 接口提供了丰富的方法来处理HTTP请求和生成响应。理解这些类和接口的源码和工作原理,有助于开发高效的Web应用程序。
1. Servlet 接口
Servlet 接口是所有 Servlet 的父接口,定义了 Servlet 的生命周期方法:
init(ServletConfig config): 初始化 Servlet 方法。在 Servlet 被实例化后调用一次,用于进行资源初始化。
service(ServletRequest req, ServletResponse res): 处理请求和生成响应的方法。每个请求都会调用该方法。
destroy(): 销毁 Servlet 方法。在服务器卸载 Servlet 时调用,用于进行资源清理。
getServletConfig(): 返回 Servlet 的配置信息。
getServletInfo(): 返回 Servlet 的基本信息,如作者、版本等。

public interface Servlet {
    void init(ServletConfig config) throws ServletException;
    ServletConfig getServletConfig();
    void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
    String getServletInfo();
    void destroy();
}

2. GenericServlet 类
GenericServlet 类实现了 Servlet 接口,并简化了实现过程。开发者只需要实现 service 方法。

public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
    private transient ServletConfig config;

    public void init(ServletConfig config) throws ServletException {
        this.config = config;
        this.init();
    }

    public void init() throws ServletException {
    }

    public ServletConfig getServletConfig() {
        return this.config;
    }

    public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

    public String getServletInfo() {
        return "";
    }

    public void destroy() {
    }
}

3. HttpServlet 类
HttpServlet 类继承了 GenericServlet 类,专门用于处理 HTTP 请求。它定义了多个方法来处理不同的 HTTP 方法(如 GET、POST、PUT、DELETE 等)。

public abstract class HttpServlet extends GenericServlet {
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method GET is not supported by this URL");
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method POST is not supported by this URL");
    }

    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method PUT is not supported by this URL");
    }

    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method DELETE is not supported by this URL");
    }

    protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Allow", "GET, HEAD, POST, PUT, DELETE, OPTIONS");
    }

    protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method TRACE is not supported by this URL");
    }

    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String method = req.getMethod();
        if (method.equals("GET")) {
            this.doGet(req, resp);
        } else if (method.equals("POST")) {
            this.doPost(req, resp);
        } else if (method.equals("PUT")) {
            this.doPut(req, resp);
        } else if (method.equals("DELETE")) {
            this.doDelete(req, resp);
        } else if (method.equals("OPTIONS")) {
            this.doOptions(req, resp);
        } else if (method.equals("TRACE")) {
            this.doTrace(req, resp);
        } else {
            resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Method " + method + " is not supported by this URL");
        }
    }

    protected long getLastModified(HttpServletRequest req) {
        return -1L;
    }
}

4. HttpServletRequest 和 HttpServletResponse 接口
HttpServletRequest 和 HttpServletResponse 是两个用于处理 HTTP 请求和响应的接口。
HttpServletRequest:
获取请求参数、头信息、路径信息、会话信息等。
常用方法:getParameter(), getHeader(), getSession(), getMethod(), getRequestURI() 等。

public interface HttpServletRequest extends ServletRequest {
    String getAuthType();
    Cookie[] getCookies();
    long getDateHeader(String name);
    String getHeader(String name);
    Enumeration<String> getHeaders(String name);
    Enumeration<String> getHeaderNames();
    int getIntHeader(String name);
    String getMethod();
    String getPathInfo();
    String getPathTranslated();
    String getContextPath();
    String getQueryString();
    String getRemoteUser();
    boolean isUserInRole(String role);
    Principal getUserPrincipal();
    String getRequestedSessionId();
    String getRequestURI();
    StringBuffer getRequestURL();
    String getServletPath();
    HttpSession getSession(boolean create);
    HttpSession getSession();
    String changeSessionId();
    boolean isRequestedSessionIdValid();
    boolean isRequestedSessionIdFromCookie();
    boolean isRequestedSessionIdFromURL();
    boolean isRequestedSessionIdFromUrl();
    boolean authenticate(HttpServletResponse response) throws IOException, ServletException;
    void login(String username, String password) throws ServletException;
    void logout() throws ServletException;
    Collection<Part> getParts() throws IOException, ServletException;
    Part getPart(String name) throws IOException, ServletException;
    <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException;
}

HttpServletResponse:
设置响应状态码、头信息、内容类型,写出响应内容等。
常用方法:setStatus(), setHeader(), setContentType(), getWriter(), getOutputStream() 等。

public interface HttpServletResponse extends ServletResponse {
    void addCookie(Cookie cookie);
    boolean containsHeader(String name);
    String encodeURL(String url);
    **加粗样式**String encodeRedirectURL(String url);
    String encodeUrl(String url);
    String encodeRedirectUrl(String url);
    void sendError(int sc, String msg) throws IOException;
    void sendError(int sc) throws IOException;
    void sendRedirect(String location) throws IOException;
    void setDateHeader(String name, long date);
    void addDateHeader(String name, long date);
    void setHeader(String name, String value);
    void addHeader(String name, String value);
    void setIntHeader(String name, int value);
    void addIntHeader(String name, int value);
    void setStatus(int sc);
    void setStatus(int sc, String sm);
    int getStatus();
    String getHeader(String name);
    Collection<String> getHeaders(String name);
    Collection<String> getHeaderNames();
    void setContentType(String type);
}

5. 示例:自定义Servlet
以下是一个简单的自定义Servlet示例:

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;
import java.io.PrintWriter;

@WebServlet("/hello")
public class HelloServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();
        out.println("<html><body>");
        out.println("<h1>Hello, Servlet!</h1>");
        out.println("</body></html>");
    }
}

在这个示例中,我们创建了一个简单的Servlet,处理GET请求并返回一个HTML页面。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1961240.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

阳光混合试验的三个指标

户外干燥气候循环系统&#xff08;仿真模拟空气干燥气侯&#xff09;户外湿冷气侯循环系统&#xff08;仿真模拟寒湿和冰冷晚间气侯&#xff09;室内干燥气候耐久度 阳光模拟温湿度试验箱 主要用于汽车及零部件的曝晒试验、如塑料样板、仪表盘、中控屏、方向盘、保险杠等&…

基于 GADF+Swin-CNN-GAM 的高创新电能扰动信号识别模型!

往期精彩内容&#xff1a; 电能质量扰动信号数据介绍与分类-Python实现-CSDN博客 Python电能质量扰动信号分类(一)基于LSTM模型的一维信号分类-CSDN博客 Python电能质量扰动信号分类(二)基于CNN模型的一维信号分类-CSDN博客 Python电能质量扰动信号分类(三)基于Transformer…

【计算机毕设论文】基于SpringBoot的诗词管理系统

&#x1f497;博主介绍&#xff1a;✌全平台粉丝5W,高级大厂开发程序员&#x1f603;&#xff0c;博客之星、掘金/知乎/华为云/阿里云等平台优质作者。 【源码获取】小伙伴可以关注我 感兴趣的可以先收藏起来&#xff0c;同学门有不懂的毕设选题&#xff0c;项目以及论文编写等…

轻松入门Linux—CentOS,直接拿捏 —/— <1>

一、什么是Linux Linux是一个开源的操作系统&#xff0c;目前是市面上占有率极高的服务器操作系统&#xff0c;目前其分支有很多。是一个基于 POSIX 和 UNIX 的多用户、多任务、支持多线程和多 CPU 的操作系统 Linux能运行主要的UNIX工具软件、应用程序和网络协议 Linux支持 32…

小程序开发_05协同工作和发布

一、开发流程 二、权限管理 三、不同成员的权限 四、小程序发布上线的步骤 上传代码--->提交审核-->发布1. 上传代码 提交审核 三、发布上线

文件IO相关作业

1> 使用文件IO完成&#xff0c;将源文件中的所有内容进行加密&#xff08;大写转小写、小写转大写&#xff09;后写入目标文件中 源文件内容不变 #include<myhead.h>int main(int argc, const char *argv[]) {//判断传入的是否是两个文件if(argc!3){write(2,"inp…

期末复习资料——计算机系统基础

第一章 1、下列关于机器字长、指令字长和存储字长的说法中&#xff0c;正确的时_②、③_ ①三者在数值上总是相等的。②三者在数值上可能不相等。③存储字长是存放在一个存储单元中的二进制代码位数。④数据字长就是MDR的位数。 机器字长、指令字长和存储字长&#xff0c;三…

【区块链+绿色低碳】碳低链 | FISCO BCOS应用案例

在碳中和、碳达峰国家战略的号召下&#xff0c;碳中和数字化、协同低碳的发展如火如荼。但是在金融业的实际场景应用中&#xff0c; 存在数据收集效率低、数据核查困难、服务单一等问题&#xff0c;痛点集中为两个&#xff1a;一是数据冗杂&#xff0c;可能会存在数据篡改&…

【python报错已解决】`AttributeError: ‘DataFrame‘ object has no attribute ‘ix‘`

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言&#xff1a; 在数据分析或者数据处理的过程中&#xff0c;我们经常会遇到各种各样的报错信息&#xff0c;这些报错信息往…

【漏洞复现】APP分发签名系统index-uplog.php存在任意文件上传漏洞

漏洞描述 APP分发签名系统index-uplog.php存在任意文件上传漏洞 免责声明 技术文章仅供参考,任何个人和组织使用网络应当遵守宪法法律,遵守公共秩序,尊重社会公德,不得利用网络从事危害国家安全、荣誉和利益,未经授权请勿利用文章中的技术资料对任何计算机系统进行入侵…

游戏类App出海广告变现,新手开发者如何选对聚合广告平台?

无论是轻量化小游戏还是中重度游戏&#xff0c;厂商的终极目标都是盈利。从商业化角度来说&#xff0c;单一的变现模式存在一些问题。纯内购驱动的游戏除了少数大竞技品类&#xff0c;大多是为垂直玩家设计&#xff0c;难以扩量。而纯广告变现驱动的游戏&#xff0c;在抗风险方…

所谓有趣的灵魂,实际上就是这个人的信息密度和知识层面,都远高于你!

1. 信息界的“百科全书” 信息密度&#xff1a;大脑里的“硬盘” 我们先来八一八什么是信息密度。想象一下&#xff0c;如果大脑是个硬盘&#xff0c;那么信息密度高的人&#xff0c;硬盘里存的可都是高清大片和无损音乐&#xff0c;随时准备给你来一场视听盛宴。 知识层面&am…

vue3数据结构的渲染01

处理数据&#xff1a; //现有原始数据showCertificateUrl “url01;url02” 使用以下代码将两条通过分号";"分割的url进行处理 const parseUrls () > {urls.value [];// 每次重新赋值前一定要清空之前的旧数据&#xff01;if (!showCertificateUrl.value) {retu…

[前端]解决Iframe即使设置高度100%,但还是显示滚动条scrollbar的问题

前言 好烦,你看看这两个重复的滚动条. 一个是来自iframe,另一个来自父级的div(overflow: auto;) 我已经在css中设置了iframe的height: 100%;border: none;,但无论如何还是显示出了父级的scrollbar 解决 将iframe的display: block;即可. 或者vertical-align: bottom;

安全测试与渗透测试的区别

在这个数字化时代&#xff0c;网络安全如同数字世界的守护神&#xff0c;其重要性不言而喻。而在这场没有硝烟的战争中&#xff0c;安全测试与渗透测试作为两大核心利器&#xff0c;常常被提及却又容易混淆。今天&#xff0c;就让我们揭开它们的神秘面纱&#xff0c;一探二者之…

2024.7.30 作业

1> 使用文件IO完成&#xff0c;将源文件中的所有内容进行加密&#xff08;大写转小写、小写转大写&#xff09;后写入目标文件中&#xff0c;源文件内容不变 #include <myhead.h> int main(int argc,const char *argv[]) {int fd1 -1,fd2 -1;if((fd1 open(".…

【和相同的二元子数组】python刷题记录

R2-前缀和专题 目录 前缀和哈希表 双指针 ps: 第一眼过去&#xff0c;这题应该能用双指针解出来&#xff0c;应该也能用前缀和解题。 前缀和哈希表 适用于 nums[i] 值不固定为 0 和 1 的其他情况 class Solution:def numSubarraysWithSum(self, nums: List[int], goal: i…

Vue入门记录(一)

效果 本文为实现如下前端效果的学习实践记录&#xff1a; 实践 入门的最佳实践我觉得是先去看官网&#xff0c;官网一般都会有快速入门指引。 根据官网的快速上手文档&#xff0c;构建一个新的Vue3TypeScript&#xff0c;查看新建的项目结构&#xff1a; 现在先重点关注comp…

前端科举八股文-手撕代码篇

前端科举八股文-手撕代码篇 手撕排序算法选择排序思路 冒泡排序思路 快速排序思路 手撕bind方法思路解析 手撕js的继承方案构造继承实现原理 原型继承实现原理 组合继承实现原理 寄生组合继承实现原理 手撕instanceOf实现原理 手撕new 操作符手撕防抖实现原理 手撕节流实现原理…

Java8 新特性,看这篇文章就够了

Java8 是 Java 编程语言的一个重要版本&#xff0c;于 2014 年 3 月发布。它引入了许多新的功能和改进&#xff0c;其中包括 Lambda 表达式、Stream API、新的日期/时间 API 和 Nashorn JavaScript 引擎等。 Java 8 的主要特点如下&#xff1a; Lambda 表达式&#xff1a;Lamb…