Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >JavaWeb三大组件之Servlet学习

JavaWeb三大组件之Servlet学习

作者头像
一灰灰blog
发布于 2018-02-06 08:43:44
发布于 2018-02-06 08:43:44
1K00
代码可运行
举报
文章被收录于专栏:小灰灰小灰灰
运行总次数:0
代码可运行

JavaWeb三大组件之Servlet学习

平时直接用springmvc较多,都没怎么接触底层的Servlet,导致对一些基本的知识点了解都不够,所以今天专门的抽出时间来学习一下

带着问题出发,看下可以怎么玩

  • 如何自定义一个Servlet
  • 自定义的Serlvet如何工作
  • servlet的优先顺序怎么判定
  • servlet匹配是怎样的 (url-mapping...)
  • 如何获取参数(get请求参数,post请求参数,上传文件)
  • 如何返回数据(返回页面,返回文件,返回二进制)
  • 请求头和返回头的设置

I. 基本知识点

1. 什么是Servlet

Servlet是JavaWeb的三大组件之一,它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:

  • 接受请求
  • 处理请求
  • 完成响应

2. 怎么玩Servlet

一般来讲,创建一个自定义的Servlet有两个步骤,在web.xml中配置serverlt的声明;实现Servlet接口,实现自定义的Servlet逻辑

一个简单的case如下

web.xml中,添加配置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<servlet>
    <servlet-name>doc-servlet</servlet-name>
    <servlet-class>com.yihui.study.DocServlet</servlet-class>
    <load-on-startup>0</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>doc-servlet</servlet-name>
    <url-pattern>/study/*</url-pattern>
</servlet-mapping>

实现自定义Servlet

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DocServlet extends HttpServlet {

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        PrintWriter writer = resp.getWriter();
        writer.append("这是一个自定义servlet")
                .append("emoj?==").flush();
        System.out.println("hereher!!!!");
    }
}

上面这个Servlet,实现了拦截 /study 下的所有请求, 然后返回一段文本,上面作为演示,具体的展开下面说明

3. Servlet接口说明

上面是直接继承了HttpServlet,可能没法完全的暴露一个Servlet的具体接口有哪些,以及它的生命周期是怎样的,接下来则直接针对源头进行说明

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public interface Servlet {
    // 初始化
    public void init(ServletConfig config) throws ServletException;
    
    // 获取配置信息
    public ServletConfig getServletConfig();
    
    // 处理请求
    public void service(ServletRequest req, ServletResponse res)
	throws ServletException, IOException;
	
	  // Returns information about the servlet, such as author, version, and copyright
    public String getServletInfo();
    
    // 销毁
    public void destroy();
}

五个方法,从命名也可以看出对应的生命周期

  • 首先是创建: init() 方法被创建
  • 创建完毕之后,请求来了,分给 service方法,执行对应的业务逻辑
  • 最后不想玩了,就销毁掉,此时触发 destroy方法

说明

在Servlet被创建后,服务器会马上调用Servlet的void init(ServletConfig)方法。请记住, Servlet出生后马上就会调用init()方法,我们可以把一些对Servlet的初始化工作放到init方法中,今后所有分配到这个Servlet的请求,都是公用这个Servlet的

4. ServletConfig

init()方法的参数

ServletConfig对象对应web.xml文件中的元素。例如你想获取当前Servlet在web.xml文件中的配置名,那么可以使用servletConfig.getServletName()方法获取

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String getServletName():获取Servlet在web.xml文件中的配置名称,即指定的名称; 
ServletContext getServletContext():用来获取ServletContext对象,ServletContext会在后面讲解; 
String getInitParameter(String name):用来获取在web.xml中配置的初始化参数,通过参数名来获取参数值; 
Enumeration getInitParameterNames():用来获取在web.xml中配置的所有初始化参数名称;

5. ServletRequest

请求对象,可以从其中获取请求数据,请求头等

内部提供的方法挺多,通常我们最关心的有:

  • 获取参数: javax.servlet.ServletRequest#getParameter
  • 获取头 : javax.servlet.http.HttpServletRequest#getHeader
  • 获取cookie: javax.servlet.http.HttpServletRequest#getCookies
  • 获取请求 : javax.servlet.http.HttpServletRequest#getRequestURI
  • ...

还有一个比较重要的就是指定字符编码,如我们通常要求提交的参数满足utf8编码,这时就可以如下设置

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// javax.servlet.ServletRequest#setCharacterEncoding
request.setCharacterEncoding("utf-8");

如我们最常用的一个spring的fitler,关键代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// org.springframework.web.filter.CharacterEncodingFilter#doFilterInternal
// 
@Override
protected void doFilterInternal(
		HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
		throws ServletException, IOException {

	if (this.encoding != null && (this.forceEncoding || request.getCharacterEncoding() == null)) {
		request.setCharacterEncoding(this.encoding);
		if (this.forceEncoding) {
			response.setCharacterEncoding(this.encoding);
		}
	}
	filterChain.doFilter(request, response);
}

6. ServletResponse

返回对象,返回响应给调用方的结构,设置返回头

返回数据给调用方,主要就是利用这个东西了,内部提供的方法也不少,我们主要关心的其实也并不太多

  • 设置返回头:javax.servlet.http.HttpServletResponse#setHeader
  • 添加cookie: javax.servlet.http.HttpServletResponse#addCookie
  • 重定向 : javax.servlet.http.HttpServletResponse#sendRedirect
  • 异常 : javax.servlet.http.HttpServletResponse#sendError
  • 设置ContentType: javax.servlet.ServletResponse#setContentType
  • 设置返回流: javax.servlet.ServletResponse#getOutputStream, javax.servlet.ServletResponse#getWriter
  • 设置编码: javax.servlet.ServletResponse#setCharacterEncoding

II. 进阶

1. web.xml中配置

这个配置,主要针对 Servlet 的顺序指定,URL匹配这两个问题,所以有必要研究下这个配置中的说明

通常web.xml的配置,下面两个是必须的

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- servlet的配置 -->
<servlet>
    <!-- servlet的内部名称,自定义。尽量有意义 -->
    <servlet-name>ServletDemo</servlet-name>
    <!-- servlet的类全名: 包名+简单类名 -->
    <servlet-class>com.xxx.ServletDemo</servlet-class>
</servlet>
<!-- servlet的映射配置 -->
<servlet-mapping>
    <!-- servlet的内部名称,一定要和上面的内部名称保持一致!! -->
    <servlet-name>ServletDemo</servlet-name>
    <!-- servlet的映射路径(访问servlet的名称) -->
    <url-pattern>/servlet</url-pattern>
</servlet-mapping>

其中 servlet-mapping 指定映射的路径,满足条件的会匹配对应的Servlet,匹配规则有以下几个定义

既然这个url匹配支持模糊匹配,那么问题来了,如果两个servlet都匹配了这个path路径,那么到底是哪个处理呢?

注意到前面有个配置参数:load-on-startup

  • 当值为0或者大于0时,表示容器在应用启动时就加载这个servlet;
  • 当是一个负数时或者没有指定时,则指示容器在该servlet被选择时才加载
  • 正数的值越小,启动该servlet的优先级越高

注意 这个参数是加载顺序,而不是最终的匹配顺序

那么匹配顺序的优先级是:

  • 精确路径匹配
    • 比如servletA 的url-pattern为 /test,servletB的url-pattern为 /* ,这个时候,如果我访问的url为http://localhost/test ,这个时候容器就会先 进行精确路径匹配,发现/test正好被servletA精确匹配,那么就去调用servletA,也不会去理会其他的servlet了
  • 最长路径匹配
  • 扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet
  • 如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源,即匹配defaultServlet

2. 参数获取

参数获取,则主要区分get请求参数,post提交表单,上传的文件了

a. 通过 getQueryString

这种获取参数的方式,只能获取url上面的参数,无法获取到post的表单内容

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
String str = req.getQueryString();
b. 通过 getParameter
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 返回所有的请求参数
javax.servlet.ServletRequest#getParameterMap

这种使用姿势,和我们在SpringMVC中常见的基本一致

c. 通过 getInputStream

获取请求流,一般的使用姿势如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
InputStream stream = req.getInputStream();
byte[] bytes = new byte[stream.available()];
stream.read(bytes);
String str = new String(bytes);

然后就需要自己对上面的请求参数进行处理了;两厢对比,常规的获取方法,直接使用 getParameter方式更加优雅

注意

通过getInputStream方式获取了请求数据之后,再通过 getParameter获取不到参数的,也好理解,请求的流,被你读取之后,其他的地方就无法获取流中的数据了

d. 获取上传的文件

从请求参数中获取上传的文件,网上随意搜索了一下,发现大部分都使用apache的fileupload包, 其实处理的依然是inputstream这个请求流,只是逻辑比较复杂,粗略的翻看了一下源码,发现这一块还挺有意思的,准备单独的深入看一下

3. 数据返回

返回数据,前面介绍HttpServletResponse的时候,就给出了两个方法

a. getWriter
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public PrintWriter getWriter() throws IOException;
b. getOutputStream
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public ServletOutputStream getOutputStream() throws IOException;

下面简单说一下上面的区别

PrintWriter

ServletOutputStream

字符流返回

字节流返回

需要字符编码

字节流直接返回(返回文件就很占优势了)

说明

  1. 上面两种方式互斥,只能使用其中一种case
  2. Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端
  3. Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象

4. 返回头设置

常见的请求头和返回头设置,对于servlet而言也是比较常见的,一般常见的几个设置

  • 是否缓存,缓存时间
  • 设置cookie
  • 设置 corss-origin 相关,以支持跨域
  • 设置 content-type ...

而实际的使用也比较简单了,如下即可

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# javax.servlet.http.HttpServletResponse#addHeader
response.addHeader("Content-Type", "text/html; charset=UTF-8");

III. 实例测试

创建一个自定义的嗯Servlet,然后拦截所有 /study 下面的请求

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class DocServlet extends HttpServlet {

    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setCharacterEncoding("utf-8");
        PrintWriter writer = resp.getWriter();
        writer.append("这是一个自定义servlet")
                .append("emoj?==").flush();
        System.out.println("hereher!!!!");
    }

    protected void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException {
        Map map = req.getParameterMap();
        System.out.println("arg: " + map);
        res.getWriter().append("success").flush();
    }
}

对应的xml配置如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
 <servlet>
    <servlet-name>doc-servlet</servlet-name>
    <servlet-class>com.yihui.study.DocServlet</servlet-class>
    <load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>doc-servlet</servlet-name>
    <url-pattern>/study/*</url-pattern>
</servlet-mapping>

实测演示:

IV. 其他

参考

  1. servlet详解(第一篇)

声明

尽信书则不如,已上内容,纯属一家之言,因本人能力一般,见解不全,如有问题,欢迎批评指正

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
servlet反射、生命周期、接口
Servlet是JavaWeb的三大组件之一,它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
eadela
2019/09/29
3970
servlet反射、生命周期、接口
JavaWeb 入门篇(2)Hello Servlet!!!
1、创建一个maven 项目 添加web框架(将web.xml 换成最新的4.0 后面有完整配置文件) 配置tomcat
宁在春
2022/10/31
2750
JavaWeb 入门篇(2)Hello Servlet!!!
JavaWeb后端入门6—Servlet
Servlet是一个运行在Web服务器上的Java程序,用于处理从Web客户端发送的请求并对请求做出响应。
用户6948990
2025/04/03
1470
JavaWeb后端入门6—Servlet
Java Servlet详解(体系结构+注解配置+生命周期)
顾名思义:服务端的小程序 Servlet只是一个接口,定义了Java被浏览器访问到(Tomcat)的识别规则,我们需要定义一个类来实现Servlet接口
一只胡说八道的猴子
2020/09/27
5510
Java Servlet详解(体系结构+注解配置+生命周期)
Servlet技术【第一篇】入门请不要放弃
Servlet概述、实现、细节、获取资源、ServletConfig、ServletContext
BWH_Steven
2019/08/29
1.2K0
Servlet技术【第一篇】入门请不要放弃
Java Web Servlet (Part A)- Servlet &amp; HttpServlet
Servlet是JavaEE规范的一种,主要是为了扩展Java作为Web服务的功能,统一接口。由其他内部厂商如tomcat,jetty内部实现web的功能。如一个http请求到来,容器将请求封装为servlet中的HttpServletRequest对象,调用init(),service()等方法输出response,由容器包装为httpresponse返回给客户端的过程。
RiemannHypothesis
2022/09/26
7090
Java Web Servlet (Part A)- Servlet &amp; HttpServlet
代码审计 | Java Web 核心技术 - Servlet
Servlet 是 Java Web 容器中运行的小程序,Servlet 原则上可以通过任何客户端-服务端协议进行通信,但它们常与 HTTP 一起使用,因此 Servlet 通常作为 “HTTP Servlet”的简写。
TeamsSix
2022/09/20
5220
代码审计 | Java Web 核心技术 - Servlet
Servlet详解
Servlet是server+Applet的缩写,表示一个服务器应用。Servlet就是一套规范,按照这套规范写的代码就可以直接在Java服务器上面运行。
秋白
2019/02/21
6320
Servlet详解
Java匹马行天下之JavaWeb核心技术——Servlet
Servlet是在服务器上运行的小程序,也就是一个Java类,但比较特殊,不需要new,自动就可以运行。也有创建、垃圾回收和销毁过程。Servlet是JavaWeb的三大组件之一(Servlet、Filter、Listener),它属于动态资源。Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Servlet中通常需要:
泰斗贤若如
2019/06/18
7840
E011Web学习笔记-Servlet
实际上Servlet是一个接口,定义了Java类被浏览器访问到(或者说被Tomcat识别的)规则;
訾博ZiBo
2025/01/06
1050
E011Web学习笔记-Servlet
Servlet
Servlet 程序运行在服务器端,处理浏览器带来的 HTTP 请求,并返回响应给浏览器,实现用户交互。
Qwe7
2022/08/12
8120
Servlet 详解
当服务器每次接收到请求时,都会调用 service 方法,该方法是会被多次调用的。
wsuo
2020/07/31
8460
Servlet 详解
servlet就是这么简单
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
好好学java
2018/09/21
9810
servlet就是这么简单
重温Java Web的技术细节
-web应用同样也需要一些初始化的参数,但 相对于每一个Servlet有一个ServletConfig来说,一个Web应用(确切的说是每个JVM)仅有一个ServletContext来存放这些参数,这个ServletContext对Web应用中的每个Servlet都可用。
智慧zhuhuix
2020/09/01
1.1K0
重温Java Web的技术细节
JavaWeb三大组件(Servlet程序、Filter过滤器、Listener监听器)
启动tomcat,浏览器访问http://localhost:8080/springmvc/servletlifecycle,控制台打印:
Java微观世界
2025/01/21
8480
JavaWeb三大组件(Servlet程序、Filter过滤器、Listener监听器)
6. Servlet入门 - Servlet概述
Servlet 运行在服务端(tomcat) 的Java小程序,是sun公司提供一套规范. 就是动态资源
Devops海洋的渔夫
2022/01/14
3.4K0
6. Servlet入门 - Servlet概述
JavaWeb复习
JavaWeb是指通过java语言编写可以通过浏览器访问的程序的总称叫javaweb
暴躁的程序猿
2022/03/23
8320
Javaweb03-servlet&filter
第一个servlet应用程序,实现servlet接口 定义:凡是实现了servlet api接口(或者继承servlet api接口的实现类)的类就是servlet应用程序;
化羽羽
2022/10/28
2150
Javaweb核心之servlet详解
Servlet是SUN公司提供的一套规范,名称就叫Servlet规范,它也是JavaEE规范之一。我们可以像学习Java基础一样,通过API来学习Servlet。这里需要注意的是,在我们之前JDK的API中是没有Servlet规范的相关内容,需要使用JavaEE的API。目前在Oracle官网中的最新版本是JavaEE8,该网址中介绍了JavaEE8的一些新特性。当然,我们可以通过访问官方API,学习和查阅里面的内容。
楠羽
2022/11/18
8210
Javaweb核心之servlet详解
基于Servlet实现的简单登陆练习
源码分享: 链接:https://pan.baidu.com/s/1LNtaEn7RgceO1Zez9DyLRA 提取码:w739
时间静止不是简史
2020/07/26
5380
相关推荐
servlet反射、生命周期、接口
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验