目录

  • 前言
  • 五丶Servlet API详解(下)
    • <1>HttpServletResponse
    • <2>设置状态码/设置响应头
    • <3>响应正文为html/设置响应体
      • 1>如果是简单格式
      • 2>如果是复杂格式
    • <4>重定向 + 转发
      • 1>转发
      • 2>重定向
      • 3>关于重定向和转发的区别
    • <5>获取一个文件--渲染展示 + 下载
      • 1>渲染
      • 2>下载
    • <6>动态生成网页内容
  • 六丶Cookie和Session
    • <1> 回顾Cookie
    • <2>回顾Session

前言

加油!坚持呀!

五丶Servlet API详解(下)

<1>HttpServletResponse

这个部分我们学习了在服务端去处理http响应的对象,在这个过程当中,我们会调用该对象的方法,去设置对象属性的内容。当然,最后tomcat会组织为http响应报文。

这一部分的主要方法如下:

1.void setStatus(int sc) 为该响应设置状态码。
2.void setHeader(String name,String value)设置一个带有给定的名称和
值的 header. 如果 name 已经存在,则覆盖旧的值.
3.void addHeader(Stringname, String value)添加一个带有给定的名称和
值的 header. 如果 name 已经存在,不覆盖旧的值, 并列添加新的键值对
4.void setContentType(Stringtype)设置被发送到客户端的响应的内容类型
。
5.void setCharacterEncoding(Stringcharset)设置被发送到客户端的响
应的字符编码(MIME 字符集)例如,UTF-8。
6.void sendRedirect(Stringlocation) 使用指定的重定向位置 URL 发送
临时重定向响应到客户端。
7.PrintWriter getWriter() 用于往 body 中写入文本格式数据.
8.OutputStream getOutputStream()用于往 body 中写入二进制格式数据

<2>设置状态码/设置响应头

我们在这里实现的程序内容是,用户在浏览器通过参数指定要返回的状态码。首先,我们在这里创建一个类ResponseStudyServlet。当然,老套路,我们代码的模板还是和Ruquest时候一样。


@WebServlet("/response")
public class ResponseStudyServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {}
}

然后我们就在里面书写我们的后端代码,首先就是要获取queryString的响应状态码

String status = req.getParameter("status");

然后我们要把这个状态码转换成为Integer类型,为了更明确地显示响应成功,我们可以进行显示设置。

if(status != null) {resp.setStatus(Integer.parseInt(status));resp.getWriter().write("设置响应状态码成功");}

然后我们抓包看看具体情况

可以看到这里响应状态码是200,响应成功。因为我们没有进行状态码的设置,所以就是响应成功默认返回200。
那么我们就要开始着手书写前端代码,进行状态码的设置,进行前后端的交接。这里还是老规矩,前端代码在VSCode书写。在webapp下,创建文件response.html,来设置我们的响应头

<h3>设置响应头</h3>
<input type="text" name="" id="status">
<br>
<button onclick="setStatus()">提交</button>
<script>function setStatus(){//js中发请求:(1)ajax (2)直接修改urllet status = document.querySelector("#status");//后端会设置这个文本框输入的值为响应状态码:严格来做需要验证(省略)window.location.href = "response?status="+status.value;}
</script>

这里我对window.location.href这行代码进行说明

浏览器内置的window对象里面有一个location,表示地址栏对象,地址栏对象有一个href属性

这里我们在文本框中输入的内容,就是我们设置的状态码。


这里是乱码,看不出来很正常,我们打开抓包工具看就好。

可以看到我设置的状态码此时生效了。
我们设置响应头的键值对,键可以是标准的http响应头的键。也可以是自定义的,但是只有当响应状态码是301,302,307的时候,响应头有location字段,我们才可以实现重定向。

resp.setHeader("Location","http://www.baidu.com");//这里我们没有设置响应状态码所以不会生效
resp.setHeader("uesrname","张三");

当我们在文本栏当中输入3xx对应的状态码的时候,会发生什么呢?


这个时候就会发生重定向,location重定向到百度页面。

<3>响应正文为html/设置响应体

我们响应头设置暂时完毕啦,这个时候我们设置一下Content-tyoe,也就是响应体的内容。
在IDEA中新建一个类,HTMLTypeServlet,然后老规矩,模板先搞起来。

@WebServlet("/html")
public class HTMLTypeServlet extends HttpServlet {//html?type=...@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {/}
}

然后设置我们的响应体内容也很简单,看如下代码:

resp.setContentType("text/html;charset=utf-8");

但是在这里我们就要分情况讨论啦。我们根据url当中的type关键字来获取获得提交给我们服务端的html响应正文是简单格式还是复杂格式的。

1>如果是简单格式

如果说是简单格式的,这里我们在VScode中表明type=1,说明是简单格式。

<h3>响应正文为简单的html</h3><a href="html?type=1">查看</a>

这里如果是简单格式我们就没有什么特别需要说明的,就输出一个响应成功,代表我们的服务端获取成功就好。IDEA书写

//在这里,我们先拿到request请求queryString中type关键字
String type = req.getParameter("type");
if ("1".equals(type)){//返回简单的htmlpw.println("<h3>获取网页成功</h3>");}

在浏览器显示如下:

然后我们点击查看,就是给服务端提交type= 1的url,表明这就是一个简单的html响应body,对应变化如下:

2>如果是复杂格式

那为什么这里要说是复杂格式呢?简单和复杂的html区别在哪里?
没错,复杂的html是会动态变化的。
那么我们在前端代码中书写

 <h3>响应正文为复杂的html(动态变化的)</h3><input type="text" id="username" placeholder="输入姓名"><br><button onclick="toWelcome()">跳转</button>

这里我们用一个文本框来获取输入的内容,然后按键toWelcome()方法进行绑定

function toWelcome(){let username = document.querySelector("#username");window.location.href = "html?type=2&username=" + username.value;}

一但按下按键,那么我们给服务端的queryString里的type关键字就会设置为2,username的值设置为我们文本框中输入的内容


对应显示内容如下:

<4>重定向 + 转发

实现一个程序, 返回一个重定向 HTTP 响应, 自动跳转到另外一个页面。实际上这段代码在上文中的跳转到百度的那行代码已经实现。而且也说了,响应头有location字段时,才是重定向。这里我们继续延展这个知识点。
继续我们的前端代码书写

 <h3>重定向</h3><a href="goto?type=1">跳转</a><h3>转发到hello.html</h3><a href="goto?type=2">跳转</a>

点下不同的按键,往后端发送的内容里就会有不同的queryString。
这里我们两个后端代码分开写,但是都要先获取type字段的值。

String type = req.getParameter("type");

1>转发

resp.setStatus(301);
resp.setHeader("Location","http://www.sogou.com");

首先设置状态码为301,然后设置响应头重定向到百度页面。我们可以把如上代码简化为如下形式。

resp.sendRedirect("http://www.sogou.com");

2>重定向

req.getRequestDispatcher("http://www.baidu.com").forward(req,resp);

这里我们对应情况说完后,整合一下代码。

if("1".equals(type)){//重定向resp.sendRedirect("http://www.sogou.com");
}else if("2".equals(type)){//转发req.getRequestDispatcher("http://www.baidu.com").forward(req,resp);
}

对应页面

如果是转发

可以发现,这里没有跳转到百度页面,也是跳转到了本地文件。

3>关于重定向和转发的区别

转发如下:

1、属于转发,也是服务器跳转,相当于方法调用,在执行当前文件的过程中转向执行目标文件,两个文件(当前文件和目标文件)属于同一次请求,前后页共用一个request,可以通过此来传递一些数据或者session信息,request.setAttribute()和request.getAttribute()。
2、在前后两次执行后,地址栏不变,仍是当前文件的地址。
3、不能转向到本web应用之外的页面和网站,所以转向的速度要快。
4、URL中所包含的“/”表示应用程序(项目)的路径。

重定向如下:

1、属于重定向,也是客户端跳转,相当于客户端向服务端发送请求之后,服务器返回一个响应,客户端接收到响应之后又向服务端发送一次请求,一共是2次请求,前后页不共用一个request,不能读取转向前通过request.setAttribute()设置的属性值。
2、在前后两次执行后,地址栏发生改变,是目标文件的地址。
3、可以转向到本web应用之外的页面和网站,所以转向的速度相对要慢。
4、URL种所包含的"/"表示根目录的路径。

<5>获取一个文件–渲染展示 + 下载

1>渲染

这里是服务端接收文件,比如说像图片音乐什么的,然后用他们来渲染页面。
首先先书写我们的前端,也就是客户端代码

<h3>获取一个图片(渲染展示)</h3>
<img src="file?type=photo&show=1" alt="">
<h3>获取一个音乐(渲染展示)</h3>
<audio src="file?type=music&show=1" controls></audio>

这里根据queryString来获取文件的类型,也就是确定客户端是要是图片还是什么类型。
然后开始我们后端的代码书写:

OutputStream os = resp.getOutputStream();

先获取对应对象的输出流,然后获得返回的文件类型,和返回时候的操作。

//返回的文件类型:1.图片 2.
String type = req.getParameter("type");
//返回时的操作:1.渲染 2.下载
String show = req.getParameter("show");

这里我们返回时候会返回一个文件,所以就要先创建一个File对象file。
然后进行判断就好了

if("photo".equals(type)){//返回图片resp.setContentType("application/octet-stream");file = new File("D:\\JavaWeb\\img\\dog.jpg");}else if("music".equals(type)){//返回音乐           resp.setContentType("audio/mp3");//MP3格式file = new File("D:\\CloudMusic\\王巨星 - 拾忆(抖音版).mp3");}

然后因为我们的前端代码里面发起了两个请求,所以图片和音乐都全了,所以这里页面上也会出现照片和音乐。这里我们的对象里的内容指定完毕,然后就可以把他转化为字节流,同时指定长度发回去了。

byte[] data =  Files.readAllBytes(file.toPath());
resp.setContentLength(data.length);//=setHeader("Content-Length",xxx)
os.write(data);

最后页面显示如下:

2>下载

其实这里和上面情况差不多是一样的,但是我们要更换一下show的值。

<h3>获取一个图片(渲染展示)</h3>
<img src="file?type=photo&show=1" alt="">
<h3>获取一个音乐(渲染展示)</h3>
<audio src="file?type=music&show=1" controls></audio>

然后给上面的后端代码进行修改,加一个判断就好

if("photo".equals(type)){//返回图片if("1".equals(show)){resp.setContentType("image/jpeg");//jpg格式}else{resp.setContentType("application/octet-stream");}file = new File("D:\\JavaWeb\\img\\dog.jpg");
}else if("music".equals(type)){//返回音乐            if("1".equals(show)){resp.setContentType("audio/mp3");//MP3格式}else{//这样只是没有设置下载的文件名,有兴趣可以自行扩展完成resp.setContentType("application/octet-stream");}file = new File("D:\\CloudMusic\\王巨星 - 拾忆(抖音版).mp3");
}

判断类型,然后判断是要单纯获得一个图片还是说要下载。
我这里想特别说一下application/octet-stream

当浏览器在请求资源时,会通过http返回头中的content-type决定如何显示/处理将要加载的数据,如果这个类型浏览器能够支持阅览,浏览器就会直接展示该资源,比如png、jpeg、video等格式。在某些下载文件的场景中,服务端可能会返回文件流,并在返回头中带上Content-Type: application/octet-stream,告知浏览器这是一个字节流,浏览器处理字节流的默认方式就是下载。

所以我们浏览器显示页面如下:

这里要注意了,下载的是个字节流,我没有指名文件的名称以及格式,所以下载之后要自己修改,笔者在这里不做过多解释。

<6>动态生成网页内容

这部分内容常用于ajax请求,返回一些数据,用于动态的填充网页。
首先在客户端发起ajax请求,书写前端代码。

<h3>获取ajax响应数据动态生成网页内容</h3>
<button onclick="gen()">试试</button>
<div id="content"></div>

我们在这里绑定按键,如果按下这个按键,就会向服务端发送请求并且获取响应。
对应gen()方法如下:

function gen(){let content = document.querySelector("#content");ajax({url:"ajax-response",method:"get",callback:function(status,resp){console.log(resp);//resp是一个字符串//[{"from":"旺财","to":"咪咪","info":"来吃小鱼干"},{"from":"旺财","to":"咪咪","info":"来吃小骨头"}]//转换为json对象let array = JSON.parse(resp);for(json of array){//开始遍历//每一个json对象创建一个dom来保存信息let p = document.createElement("p");p.innerText = json.form + " 对 " + json.to + " 说: " + json.info;content.appendChild(p);}}})}

当然,这里是要设置一下回调函数的。


function ajax(args){//var ajax = function(){}let xhr = new XMLHttpRequest();// 设置回调函数xhr.onreadystatechange = function(){// 4: 客户端接收到响应后回调if(xhr.readyState == 4){// 回调函数可能需要使用响应的内容,作为传入参数args.callback(xhr.status, xhr.responseText);}}xhr.open(args.method, args.url);//如果args中,contentType属性有内容,就设置Content-Type请求头if(args.contentType){//js中,if判断,除了判断boolean值,还可以判断字符串,对象等,有值就为truexhr.setRequestHeader("Content-Type", args.contentType);}//如果args中,设置了body请求正文,调用send(body)if(args.body){xhr.send(args.body);}else{//如果没有设置,调用send()xhr.send();}}

然后就可以对我们的后端代码下手了。首先构造一个Message类,用对应的message对象来存储我们要动态添加的内容。

static class Message{private String from;//谁private String to;//对谁private String info;//说了什么public Message(String from, String to, String info) {this.from = from;this.to = to;this.info = info;}public String getForm() {return from;}public void setForm(String from) {this.from = from;}public String getTo() {return to;}public void setTo(String to) {this.to = to;}public String getInfo() {return info;}public void setInfo(String info) {this.info = info;}

接着就可以进行对象的创建啦。

List<Message> messageList = new ArrayList<>();
Message m1 = new Message("咪咪","旺财","来吃小鱼干");
Message m2 = new Message("旺财","咪咪","来吃小骨头");
messageList.add(m1);
messageList.add(m2);

用一个List对象,储存Message对象,然后接下来就把这个Message对象转化为json字符串。

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(messageList);

接着就设置ajax,进行ajax响应,返回这个json字符串。

resp.setContentType("application/json;charset=utf-8");
resp.getWriter().println(json);

之后我们就可以在我们的页面上动态生成内容。

六丶Cookie和Session

<1> 回顾Cookie

HTTP协议自身是属于”无状态“协议。也就是说:默认情况下客户端和服务端的此次通信,和下次通信之间没有直接的联系。
但是实际上我们很多时候是知道请求之间的关联关系。比如,第二次访问网站的时候是能够知道这个网站是否之前已经访问过的。

这个令牌就保存在Cookie字段当中,此时在服务器这边就需要记录信息,以及令牌对应的用户信息。

<2>回顾Session

对于服务器来说,同一时刻收到的请求很多,为了认清那个请求是属于那个用户的。就需要记录好用户的令牌以及和用户之间的关系。

会话本质是一个hash表,存储了些键值对结构,key就是令牌的ID,也就是SessionID,而用户的信息就是Session,当然这里的Session也是一个Map对象。

1.用户登录时,服务器在Session中新增一个新纪录,并把sessionid/token返回给客户端。
(例如通过HTTP响应中的Set-cookie)字段。
2.客户端后续再次访问的时候,请求中带上sessionid/token(比如通过HTTP请求中的Cookie
字段带上)
3.服务器收到请求之后,根据请求中的sessionid/token在session信息当中收到对应的用户
信息,然后进行后续操作

JavaWeb--Servlet(下)相关推荐

  1. Javaweb servlet体系结构与原理剖析

    Javaweb servlet体系结构与原理剖析 1.Servlet的工作过程 2.Servlet体系结构 3.Servlet工作原理 4.Servlet生命周期 1.Servlet的工作过程 当用户 ...

  2. javaweb(servlet)+jsp+Mysql实现的简单相册管理系统(功能包含登录、管理首页、添加图片、分类管理、修改密码、图片详情等)

    博客目录 javaweb(servlet)+jsp+Mysql实现的简单相册管理系统 实现功能截图 系统功能 使用技术 代码 完整源码 javaweb(servlet)+jsp+Mysql实现的简单相 ...

  3. JavaWeb——Servlet(全网最详细教程包括Servlet源码分析)

    JavaWeb--Servlet Tomcat工作机制动画演示(点击动图可全屏观看) 什么是Servlet Servlet(Server Applet),全称Java Servlet,未有中文译文.是 ...

  4. JavaWeb Servlet 登录功能 注销功能

    JavaWeb Servlet 登录功能 注销功能 有三个逻辑: 处理登陆的逻辑,用户主页的逻辑,退出登录逻辑 登陆的逻辑LoginServlet.java import java.io.IOExce ...

  5. Javaweb Servlet 下载文件

    JavaWeb Servlet 实现下载文件 Servlet类 import javax.servlet.ServletException; import javax.servlet.ServletO ...

  6. javaweb(servlet)+jsp+Mysql实现的酒店客房管理系统(功能包含登录、用户管理、住客信息管理、房型管理、房间管理、会员星级管理、订单管理等)

    博客目录 javaweb(servlet)+jsp+Mysql实现的酒店客房管理系统 实现功能截图 系统功能 使用技术 代码 完整源码 javaweb(servlet)+jsp+Mysql实现的酒店客 ...

  7. javaWeb——Servlet

    Servlet 系统架构 B/S结构的系统通信原理(没有涉及到Java小程序) 关于WEB服务器软件 实现一个最基本的web应用(这个web应用中没有java小程序) 对于一个动态的web应用来说,一 ...

  8. Java-Web Servlet开发

    一.Servlet概述 1.什么是Servlet Servlet是JavaWeb的三大组件之一,它属于动态资源.Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Ser ...

  9. 重学JavaWeb —— Servlet,简单全面一发入魂

    文章目录 Servlet 概述 基本使用 两个重要对象 请求转发 会话技术 Cookie Session 对比小结 其它相关对象 ServletContext ServletConfig 过滤器 概述 ...

  10. javaweb+servlet+mysql登录+注册+增删改查源码

    一.项目功能简介 功能流程图 源码: 百度网盘链接:https://pan.baidu.com/s/1QpbX1Sz0nZJwlvzEvx7zEw  提取码:ynzu 数据库: 链接:https:// ...

最新文章

  1. jQuery中get()和eq()的区别
  2. 吸引纠缠的双白矮星和迭代收敛的神经网络
  3. 浙江树人学院计算机专业好吗,浙江树人学院有哪些专业及什么专业好
  4. 从vivo 大规模特征存储实践中学点经验
  5. EFCore Lazy Loading + Inheritance = 干净的数据表 (二)
  6. linux增加调整虚拟内存
  7. ewebeditor未授权:功能被禁用请先配置授权_SteamPY新功能——外区账号礼物自动领取...
  8. python爬虫什么网站都能爬吗_python如何爬取动态网站
  9. 我的世界1.8.9无需正版的服务器,我的世界1period;8period;9服务器纯洁服地址 | 手游网游页游攻略大全...
  10. 年薪30W的软件测试“老司机”工作经验
  11. java ajax 进度条_java使用ajax实现进度条
  12. [Luogu 2090]数字对
  13. 剑指offer-刷题总结
  14. 【算法】什么是OJ系统?
  15. Vue项目打包部署到七牛CDN
  16. OpenJ_Bailian - 3164 奇偶排序
  17. Linux常用命令 实用命令万字总结(转载学习)
  18. W25qxxx 实现文件系统 ---- 基于RT-thread嵌入式操作系统
  19. 室内导航--机器视觉、ROS、Goseek(二)Ubuntu 20.04 LTS 准备
  20. winform 使用SplashScreen窗口

热门文章

  1. iOS --- 识别相册中图片上的二维码
  2. 频分多址、时分多址、码分多址、空分多址之间的区别
  3. Word中分隔符的用法
  4. 房产小程序APP功能
  5. 使用FFmpeg读取视频流并保存
  6. Error response from daemon: Container is restarting,wait until the container is running
  7. android 表情键盘切换,Android仿微信键盘切换效果
  8. 博客转移到:http://www.cnblogs.com/yaos/
  9. Matlab之函数探查器
  10. 背景固定和滚动 background-attachment: fixed/scroll;