【JavaEE】【Servlet API详解】重点!!!

努力经营当下,直至未来明朗!


坚持一定很酷!

【Servlet API概述】

  1. API其实就是一组类/方法
  2. Servlet提供的类和方法很多,但是最主要就使用三个:
    ① HttpServlet: (继承)1

② HttpServletRequest:(方法参数)
③ HttpServletResponse:(方法参数)
2
(HttpServletRequest、HttpServletResponse中的方法都是和http报文格式有关的)


【HttpServlet】

  1. 核心方法
    3
    1)init:创建出HttpServlet实例会调用一次,其作用其实就是用来初始化。一般就是首次访问的时候会被实例化。
    2)destroy:不一定能够调用到。因为HttpServlet不再调用其实就是在tomcat关闭时,关闭tomcat有两种方法:
    ① 直接杀进程:如点击idea中的红色方框、cmd直接点击x、通过任务管理器结束进程等,此时destroy无法被调用。
    8005端口是用来控制tomcat的,通过该端口给tomcat发送一个关闭操作,此时tomcat就可以正常关闭,也就能够调用destroy了。

(工作中最常用的其实就是直接杀进程方式关闭,所以不太会调用到destroy方法)

3) service:tomcat收到请求之后实际上是先调用service方法,在service中根据方法来调用不同的doXXX方法。(实际开发中其实很少会重写service,重写doXXX方法就够了)

  1. 面试题】谈谈Servlet的生命周期?
    生命周期:其实就是正确的时间干正确的事儿。
    也就是回答:Servlet中有三个主要的方法:init、destroy、service,以及何时被调用:init在servlet被实例化的时候调用一次,destroy是在servlet销毁之前调用一次,service是每次收到请求调用(两次)。
    (调用两次service原因:两次service

【HttpServletRequest】

  1. 核心方法:
    30

  2. 写一个测试代码:
    10
    11
    (枚举类型是不可以通过下标访问和修改的)

  3. 如果不写content type,此时浏览器就不知道body是啥格式,就会去猜;但是一般不要让浏览器去猜,而是直接setContentType

body格式如:
tect/plain(纯文本)、text/html、 text/css、 application/js、 application/json、 image/png 等

  1. 还有一个重要场景就是:使用api获取到请求中的重要参数(query string中的值 以及 body中的值)
    对于query string来说,核心方法就是 getqueryString

1)实例:
31

(在服务器中打印)
32

(在浏览器中打印)
33

此时:浏览器没有正确识别出中文,当前不是没有urlencode的缘故(因为服务器这里的打印结果是正确的);但是返回的响应页面浏览器没能正确识别,为了让浏览器能够识别,需要显式在响应上加上content type。
35

注意:即使在地址栏输入的是encode的内容,但是servlet getParameter会自动的针对urlencode的结果进行decode,不需要我们手动处理

  • getParameter获取键值对的时候,如果是键key不存在,得到的就是null;如果是键存在、值不存在,得到的就是” ”;如果key、value都不存在,得到的也是null。

2)POST实例:
如果请求是post,如何获取到body中的参数?

A. 请求的body是x-www-form-urlencode 的 form表单形式:
这里也是使用getParameter来获取的。
但是post请求不是直接在地址栏输入就可以的,需要构造请求:
① 这里可以使用第三方工具postman来构造请求:构造完成后直接点send就可以看到结果
(postman也是http客户端,其地位和浏览器是对等的)
36

② 还可以搞个html页面,通过form表单发送请求。
(注:html创建是在webapp下,不是WEB-INF下!! new file)
(如果在idea中不好写代码,就切到vscode中写代码)

37
(一定要注意这里的路径:不是webapp,而是servl,之前在idea tomcat上设定的context path!!)

在提交之后可以在fiddler中看到body信息,也就是post请求构造成功。

(body中被form表单自动urlencode了)
38
(post请求路径)
39

(form表单类型)
40

虽然已经显式地告诉了浏览器响应的编码方式,但是响应页面依旧是乱码:
41

查看发现服务器中也是乱码:
42

说明:服务器在针对请求进行解析的时候就已经乱码了。所以:需要显式地告诉servlet应该按照哪种编码来理解请求的body。
所以:给请求也设置编码方式:
43

  • 【请求处设置的utf8是告诉servlet(tomcat)如何解析;响应处设置的utf8是告诉浏览器如何解析】

响应这里设置字符集有两种写法:setContentType 以及 setCharacterEncoding,但是还是建议使用setContentType完整写法;
设置的字符集只是其中一部分,还需要设置格式。

【补充】

“爬虫”:其实就是一个HTTP客户端,是自己写的。能在浏览器中做的一切操作,理论上都是可以用爬虫来实现的。
(90%的爬虫都是违法的。服务器承受的请求压力是有限的,爬虫其实属于无效访问,还白白增大了服务器的压力,容易把别人的服务器搞挂了;另外,可能会涉及别人的隐私信息。(很多网站都是有反爬策略))

【注意】
43
顺序不能颠倒。务必要保证先设置所有的header,最后再设置body(servlet的坑)。
即:先格式 后写入!!

B. 请求的body是json:(使用 {键值对,} 构成的)

① 需要先读取body中的内容,使用getInputStream来读取流对象,然后再进一步来读取流对象。

② 如何解析json格式?
Servlet没有内置json解析,所以我们就使用第三方库。市面上很多第三方库如fastjson、jackson、gson等,但是我们主要使用的是jackson,因为jackson是Spring御用的json库。

③ 使用中央仓库maven(中央仓库)下载安装jackson:选择databind -> 随便选择一个版本(此时我选2.13.4.1)-> 复制如下图maven中内容 -> 拷贝到pom.xml中(依旧是dependecies中)-> 如果标红,就进行刷新操作
45
46

④ 其实使用jackson非常方便,掌握一个类两个方法就行:

ObjectMapper类:
① readValue方法:把JSON格式的数据转为java的对象
②writeValueAsString方法:把java对象转成jjson格式的字符串

【readValue方法:第一个参数可以是字符串,也可以是输入流; 第二个参数是获取类对象(类似于反射),也就是要解析出来的结果的对象的类】
47

【重点理解】

① 读取输入流,获取到要解析的字符串
② 把字符串按照json格式进行解析,得到一组键值对(Map)
③ 根据类对象创建一个实例
④ 遍历类对象中属性的名字,拿着名字去与上述Map中查询匹配,将匹配到的value赋值到对应对象的属性中去
⑤ 返回这个构造完成的对象。
(要求:json键值对中 键 的名字/类型要和类的 属性 一一对应

【注】

① 要实现java对象就要有java类,而类中的属性务必是public或者是带有public的getter/setter ,否则json无法访问该对象的属性。
② 另外,该类必须有无参版本的构造方法,如果不写任何构造方法,编译器能够自动生成无参的构造方法。(但是一旦写了有参的构造方法,就一定要自己手动写无参的构造方法)

在postman中构造post请求时,json格式设置方法如下:

49
50
在postman中写json格式的时候,务必要保证这里的key是带引号的!正常的json中key都是要带引号的! (但是js里的对象是不带的

具体参考代码JsonServlet


【HttpServletResponse】

  1. 核心方法:
    50

注:HttpServletRequest方法一般是get系列,而HttpServletResponse方法一般是set系列:因为doGet/doPost等这样的方法中的HttpServletResponse对象就是空对象,需要往里面写入数据

  1. 举个例子:
    1) 设置不同的状态码:
    (代码:StatusServlet
    这些状态码具体怎么处理(前端页面显示啥)都是由程序员自定义的。

2) 设置响应的header:
通过这个实现页面的自动刷新:header设置refresh属性,值是一个秒数。
在进行刷新时,刷新时间总是会比设定的时间稍多一些,理由:

① 进程调度消耗时间
② 网络传输消耗时间
③ 服务器响应消耗时间

(代码:AutoRefreshServlet

3)构造重定向响应(3开头系列):
(代码:RedirectServlet 没有referer的)


写例子:表白墙

  1. 之前写的表白墙,其内容只是在内存中存在(List保存),一旦刷新之后内容就丢失。
  2. 此时需要让用户留言的数据能够在服务器这儿保存,保证页面即使关闭之后数据也不会丢失!此时就可以保证页面加载数据时是从服务器这儿加载数据的,之前留言的内容不会丢失。

1)准备工作:创建maven项目MessageWall,引入依赖,创建目录结构

2)设计前后端如何交互:前端啥时候给后端发请求,发的请求是啥样的,返回的响应是啥样的。

① 在表白墙中,希望点击提交之后数据能够在服务器中保存(存档);
② 当关闭页面再重新启动/刷新之后,需要从服务器获取到之前保存过的数据并在页面上进行显示(读档)

【客户端和服务器的交互是根据业务需求的】

3)理清请求和响应的细节。
① 发送数据给服务器:
51

接口约定的方式是无穷的,必须要确定一个唯一方案,这样前后端才可以配合开发。

②从服务器获取到已经保存的数据:
52

4)开发后端和前端代码

① 前端代码是在webapp目录底下! 然后使用vscode打开并操作
② 注意:将资源都放到webapp下,包括写Servlet,其实编译之后的.class文件也是在webapp底下的;webapp就描述了当前网站的Context Path。

53

55
(发送请求:前端代码,前面还加了一个script 引入jquery)

③ 页面进行加载的时候就需要进行“读档”操作:直接写在script标签中的代码都是在页面加载的时候执行的

④ 注:smart tomcat 会把一部分内存中的数据保存下来,后续重启服务器的时候数据就会恢复回来。

【注意:请求、响应过程!】

web程序一旦出现问题,起手式就是“抓包”,通过抓包确定是前端问题还是后端问题。


5)需要让数据在数据库中持久化保存:jdbc编程
① 在中央仓库搜索mysql:
58

② 选择5.1.49版本,复制代码并粘贴到pom.xml的dependencies中

③ 设计数据库表结构:几张,表里有哪些

本表白墙中只需要一张表message,列:from、to、message(id可以没有)

在cmd中操作:首先 目录要cd到mysql.exe所在的目录,然后输入mysql -u root -p进入数据库(也可以直接使用mysql client)

59此时建表成功(注意关键字要加上``)

④ 此时重新修改后端代码,直接保存在数据库中。
记忆数据库操作代码


6)DataSource存在多份,这不太合理,所以使用单例模式对DataSource进行封装。
① 单例模式:只创建一个实例!
② 一般由两种模式:懒汉模式和饿汉模式,一般更倾向于使用懒汉模式。
懒汉模式涉及到一个线程安全问题。

③ 所以考虑:Servlet代码中是否涉及到多线程/线程安全问题?

① Servlet写的是一个服务器,同一时刻可能要处理多个客户端的请求。
② 一旦同时有多个客户端都发来请求,服务器就势必要同时处理多个请求。Tomcat内部正是使用了多线程的方式来处理的。
③ 则:Servlet代码中涉及到多线程/线程安全问题。


表白墙参考代码

参考代码表白墙


小结

  1. HttpServlet
    ① doXXX:处理哪种http请求会调用的对应的方法
    ② init/destroy/service:Servlet的生命周期

  2. HttpServletRequest:HTTP请求,get系列方法
    可以获取到以下信息:
    协议名(版本号)、URL、query string、header、query string/body的键值对等

  3. HttpServletResponse:HTTP响应,set系列方法
    可以设置以下信息:
    状态码、各种header、body等

  4. 表白墙代码:主要注意 mysql +单例模式(线程安全)

yyy

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
不用担心英文j2eeapi看不懂了 提供一种方式 跨多个页面请求或对 Web 站点的多次访问标识用户并存储有关该用户的信息 servlet 容器使用此接口创建 HTTP 客户端和 HTTP 服务器之间的会话 会话将保留指定的时间段 跨多个连接或来自用户的页面请求 一个会话通常对应于一个用户 该用户可能多次访问一个站点 服务器能够以多种方式维护会话 比如使用 cookie 或重写 URL 此接口允许 servlet 查看和操作有关某个会话的信息 比如会话标识符 创建时间和最后一次访问时间 将对象绑定到会话 允许跨多个用户连接保留用户信息 当应用程序将对象存储到会话中或从会话中移除对象时 该会话将检查对象是否实现了 HttpSessionBindingListener 如果实现了 则 servlet 将通知该对象它已经被绑定到会话 或者已从会话中取消对它的绑定 通知是在绑定方法完成后发送的 对于无效或过期的会话 通知是在会话已经无效或过期之后发送的 当容器使用分布式容器设置在 VM 之间迁移会话时 所有实现 HttpSessionActivationListener 接口的会话属性都会得到通知 servlet 应该能够处理客户端选择不加入会话的情况 比如故意关闭 cookie 时 在客户端加入会话前 isNew 一直返回 true 如果客户端选择不加入会话 则 getSession 将对每个请求返回一个不同的会话 并且 isNew 将总是返回 true 会话信息的范围仅限于当前 Web 应用程序 ServletContext 因此存储在一个上下文中的信息在另一个上下文中不是直接可见的 ">不用担心英文j2eeapi看不懂了 提供一种方式 跨多个页面请求或对 Web 站点的多次访问标识用户并存储有关该用户的信息 servlet 容器使用此接口创建 HTTP 客户端和 HTTP 服务器之间的会话 会话将保留指定的时间段 跨多个连接 [更多]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Dream是普通小孩耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值