首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

JavaWeb三大组件之Servlet学习

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中,添加配置

实现自定义Servlet

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

3. Servlet接口说明

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

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

首先是创建: 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()方法获取

5. ServletRequest

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

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

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

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

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的配置,下面两个是必须的

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

必须 / 开头

/servlet 表示精确匹配

http://localhost:8088/servlet匹配

http://localhost:8088/servlets不匹配

http://localhost:8088/servlet/123不匹配

/servlet/* 表示目录匹配,所有servlet路径开头的都可以匹配

http://localhost:8088/servlet匹配

http://localhost:8088/servlet/123匹配

http://localhost:8088/servlet/123/123匹配

http://localhost:8088/servlets不匹配

/*.do 表示扩展名匹配,所有以 .do 结尾的匹配

既然这个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了

最长路径匹配

servletA的url-pattern为/test/,而servletB的url-pattern为/test/a/,此时访问http://localhost/test/a时,容器会选择路径最长的servlet来匹配,也就是这里的servletB

扩展匹配,如果url最后一段包含扩展,容器将会根据扩展选择合适的servlet

如果前面三条规则都没有找到一个servlet,容器会根据url选择对应的请求资源,即匹配defaultServlet

2. 参数获取

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

a. 通过 getQueryString

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

b. 通过 getParameter

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

c. 通过 getInputStream

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

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

注意

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

d. 获取上传的文件

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

3. 数据返回

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

a. getWriter

b. getOutputStream

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

说明

上面两种方式互斥,只能使用其中一种case

Servlet程序向ServletOutputStream或PrintWriter对象中写入的数据将被Servlet引擎获取,Servlet引擎将这些数据当作响应消息的正文,然后再与响应状态行和各响应头组合后输出到客户端

Serlvet的service方法结束后,Servlet引擎将检查getWriter或getOutputStream方法返回的输出流对象是否已经调用过close方法,如果没有,Servlet引擎将调用close方法关闭该输出流对象

4. 返回头设置

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

是否缓存,缓存时间

设置cookie

设置 corss-origin 相关,以支持跨域

设置 content-type ...

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

III. 实例测试

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

对应的xml配置如下

实测演示:

IV. 其他

声明

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

扫描关注,java分享

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20180126A152VF00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券