JavaWeb--Servlet(下)
目录
- 前言
- 五丶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(下)相关推荐
- Javaweb servlet体系结构与原理剖析
Javaweb servlet体系结构与原理剖析 1.Servlet的工作过程 2.Servlet体系结构 3.Servlet工作原理 4.Servlet生命周期 1.Servlet的工作过程 当用户 ...
- javaweb(servlet)+jsp+Mysql实现的简单相册管理系统(功能包含登录、管理首页、添加图片、分类管理、修改密码、图片详情等)
博客目录 javaweb(servlet)+jsp+Mysql实现的简单相册管理系统 实现功能截图 系统功能 使用技术 代码 完整源码 javaweb(servlet)+jsp+Mysql实现的简单相 ...
- JavaWeb——Servlet(全网最详细教程包括Servlet源码分析)
JavaWeb--Servlet Tomcat工作机制动画演示(点击动图可全屏观看) 什么是Servlet Servlet(Server Applet),全称Java Servlet,未有中文译文.是 ...
- JavaWeb Servlet 登录功能 注销功能
JavaWeb Servlet 登录功能 注销功能 有三个逻辑: 处理登陆的逻辑,用户主页的逻辑,退出登录逻辑 登陆的逻辑LoginServlet.java import java.io.IOExce ...
- Javaweb Servlet 下载文件
JavaWeb Servlet 实现下载文件 Servlet类 import javax.servlet.ServletException; import javax.servlet.ServletO ...
- javaweb(servlet)+jsp+Mysql实现的酒店客房管理系统(功能包含登录、用户管理、住客信息管理、房型管理、房间管理、会员星级管理、订单管理等)
博客目录 javaweb(servlet)+jsp+Mysql实现的酒店客房管理系统 实现功能截图 系统功能 使用技术 代码 完整源码 javaweb(servlet)+jsp+Mysql实现的酒店客 ...
- javaWeb——Servlet
Servlet 系统架构 B/S结构的系统通信原理(没有涉及到Java小程序) 关于WEB服务器软件 实现一个最基本的web应用(这个web应用中没有java小程序) 对于一个动态的web应用来说,一 ...
- Java-Web Servlet开发
一.Servlet概述 1.什么是Servlet Servlet是JavaWeb的三大组件之一,它属于动态资源.Servlet的作用是处理请求,服务器会把接收到的请求交给Servlet来处理,在Ser ...
- 重学JavaWeb —— Servlet,简单全面一发入魂
文章目录 Servlet 概述 基本使用 两个重要对象 请求转发 会话技术 Cookie Session 对比小结 其它相关对象 ServletContext ServletConfig 过滤器 概述 ...
- javaweb+servlet+mysql登录+注册+增删改查源码
一.项目功能简介 功能流程图 源码: 百度网盘链接:https://pan.baidu.com/s/1QpbX1Sz0nZJwlvzEvx7zEw 提取码:ynzu 数据库: 链接:https:// ...
最新文章
- jQuery中get()和eq()的区别
- 吸引纠缠的双白矮星和迭代收敛的神经网络
- 浙江树人学院计算机专业好吗,浙江树人学院有哪些专业及什么专业好
- 从vivo 大规模特征存储实践中学点经验
- EFCore Lazy Loading + Inheritance = 干净的数据表 (二)
- linux增加调整虚拟内存
- ewebeditor未授权:功能被禁用请先配置授权_SteamPY新功能——外区账号礼物自动领取...
- python爬虫什么网站都能爬吗_python如何爬取动态网站
- 我的世界1.8.9无需正版的服务器,我的世界1period;8period;9服务器纯洁服地址 | 手游网游页游攻略大全...
- 年薪30W的软件测试“老司机”工作经验
- java ajax 进度条_java使用ajax实现进度条
- [Luogu 2090]数字对
- 剑指offer-刷题总结
- 【算法】什么是OJ系统?
- Vue项目打包部署到七牛CDN
- OpenJ_Bailian - 3164 奇偶排序
- Linux常用命令 实用命令万字总结(转载学习)
- W25qxxx 实现文件系统 ---- 基于RT-thread嵌入式操作系统
- 室内导航--机器视觉、ROS、Goseek(二)Ubuntu 20.04 LTS 准备
- winform 使用SplashScreen窗口
热门文章
- iOS --- 识别相册中图片上的二维码
- 频分多址、时分多址、码分多址、空分多址之间的区别
- Word中分隔符的用法
- 房产小程序APP功能
- 使用FFmpeg读取视频流并保存
- Error response from daemon: Container is restarting,wait until the container is running
- android 表情键盘切换,Android仿微信键盘切换效果
- 博客转移到:http://www.cnblogs.com/yaos/
- Matlab之函数探查器
- 背景固定和滚动 background-attachment: fixed/scroll;