板块一 Servlet编程:第四节 HttpServletResponse对象全解与重定向 来自【汤米尼克的JAVAEE全套教程专栏】

本文主要是介绍板块一 Servlet编程:第四节 HttpServletResponse对象全解与重定向 来自【汤米尼克的JAVAEE全套教程专栏】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

板块一 Servlet编程:第四节 HttpServletResponse对象全解与重定向

  • 一、什么是HttpServletResponse
  • 二、响应数据的常用方法
  • 三、响应乱码问题
      • 字符流乱码
      • 字节流乱码
  • 四、重定向:sendRedirect
      • 请求转发和重定向的区别

在上一节中,我们系统的学习了请求响应在Servlet中service()方法的第一个形参HttpServletRequest(请求)对象,这一节中我们将学习它的兄弟,service()方法的第二个形参HttpServletResponse(响应)对象

一、什么是HttpServletResponse

在我们已然熟悉的浏览器访问Servlet的过程中。Request和Response 对象分别代表请求和响应:通过Request对象获取客户端数据;通过 Response 对象向客户端输出数据:
在这里插入图片描述
service()方法中形参接收的是HttpServletResponse接口的实例化对象,它继承自ServletResponse接口,专门用来封装HTTP响应消息,由于HTTP响应消息分为状态行响应消息头消息体三部分(详见HTTP协议理论与服务器请求响应原理小节),因此在HttpServletResponse中定义了状态行、响应消息头、消息体三部分。

  • 状态行部分
    响应消息头包含了关于响应的附加信息,例如内容类型、内容长度、缓存控制等。由setStatus(int status)方法实现,该方法用于设置HTTP响应消息的状态码,并生成相应代码;默认会生成一个状态码为200的状态行;
  • 响应消息头部分
    响应消息头包含了关于响应的附加信息,例如内容类型、内容长度、缓存控制等。可以使用setHeader(String name, String value)方法设置响应消息头的字段和值,例如setHeader("Content-Type", "text/html")设置内容类型为HTML。如果要设置相同字段的多个值,可以使用addHeader(String name, String value)方法,例如addHeader("Set-Cookie", "cookie1=value1")。此外还可以使用一些特定的方法来设置常见的响应消息头,例如setContentType(String type)setContentLength(int len)
  • 消息体部分
    消息体包含了实际的响应数据。可以通过获取ServletOutputStream或PrintWriter对象来写入响应消息体。getOutputStream()方法返回一个可以写入二进制数据的ServletOutputStream对象。
    getWriter()方法返回一个可以写入字符数据的PrintWriter对象。
    可以使用这些对象的方法将数据写入响应消息体,例如print(String s)、write(byte[] b)等。

二、响应数据的常用方法

接收到客户端请求后,可以通过HttpServletResponse对象直接进行响应,响应时需要获取输出流。
有两种形式:

  • getWriter() 获取字符流(只能响应字符串)
  • getOutputStream() 获取字节流(能响应一切数据)

响应回的数据到客户端被浏览器解析
注意:两者不能同时使用

实例
在start.java导入PrintWriter类,并在service()中写入测试代码

// 获取字符输出流
PrintWriter writer = resp.getWriter();
//输出数据
writer.write("Hello");

启动服务器,在浏览器中访问得
在这里插入图片描述
在start.java中导入ServletOutputStream类,并在service()中写入测试代码

//得到字节输出流
ServletOutputStream out = resp.getOutputStream();
// 输出数据
out.write("Hi".getBytes());

启动服务器,在浏览器中访问得
在这里插入图片描述
但当两者同时使用时
start.java

package www.caijiyuan;import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;@WebServlet("/start")
public class start extends HttpServlet {@Overrideprotected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取字符输出流PrintWriter writer = resp.getWriter();//输出数据writer.write("Hello");//得到字节输出流ServletOutputStream out = resp.getOutputStream();// 输出数据out.write("Hi".getBytes());}
}

启动服务器,在浏览器中访问,只得到了第一个的打印内容
在这里插入图片描述
这是为什么呢?查看报错信息
在这里插入图片描述原来是getWriter()已经调用过response对象了,如果再响应一次response对象就已经不存在了

三、响应乱码问题

在上一节中我们使用request.setCharacterEncoding("UTF-8");解决了请求时中文乱码的问题,同样,在响应时也存在中文乱码问题。这是因为服务器响应的数据也会经过网络传输,服务器端有一种编码方式,在客户端也存在一种编码方式,当两端使用的编码方式不同时则出现乱码。

字符流乱码

对于getWriter()获取到的字符流,响应中文必定出乱码,由于服务器端在进行编码时默认会使用ISO-8859-1格式的编码,该编码方式并不支持中文。要解决该种乱码只能在服务器端告知服务器使用一种能够支持中文的编码格式,这也是我们在解决请求时中文乱码的方法

response.setCharacterEncoding("UTF-8");

此时还只完成了一半的工作
要保证数据正确显示,还需要指定客户端的解码方式

response.setHeader("content-type", "text/html; charset=UTF-8");

两端指定编码后,乱码就解决了。一句话:保证发送端接收端编码一致

实例
我们在start.java的service()中写入测试测试代码,试图打印中文

// 获取字符输出流
PrintWriter writer = resp.getWriter();
//输出数据
writer.write("汤米尼克");

启动服务器,在浏览器中访问,发现输出中文乱码
在这里插入图片描述
设置服务器和客户端的编码格式统一

// 设置服务端的编码
resp.setCharacterEncoding("UTF-8");
// 设置客户端的响应类型及编码
resp. setHeader("content-type", "text/html; charset=UTF-8");
// 获取字符输出流
PrintWriter writer = resp.getWriter();
// 输出数据
writer.write("汤米尼克");

重启浏览器,再在浏览器中访问就解决问题了
在这里插入图片描述
理解了原理,其实我们还可以同时设置客户端和服务端的编码方式

response.setContentType( "text/html; charset=UTF-8");

这一句就可以替换上面的两句

字节流乱码

对于getOutputStream()方式获取到的字节流,响应中文时,由于本身就是传输的字节,所以此时可能出现乱码,也可能正确显示。当服务器端给的字节恰好和客户端使用的编码方式一致时则文本正确显示,否则出现乱码。无论如何我们都应该准确掌握服务器和客户端使用的是那种编码格式,以确保数据正确显示。
因此,字节流乱码的解决方式与上面字符流乱码的解决方式一样,在响应发出之前同时设置服务器和客户端的编码格式统一即可

response.setContentType( "text/html; charset=UTF-8");

四、重定向:sendRedirect

重定向是一种服务器为指导的客户端行为
怎么理解这句话呢?客户端发出一个请求,被服务器接收处理后进行响应,在响应的同时,服务器会给客户端一个新的地址(下次请求的地址),当客户端接收到响应后,会立刻、马上自动根据服务器给的新地址发起第二个请求,服务器接收请求并作出响应,重定向完成。可以看出这个过程中有两个请求存在,其中两个Servlet的Request对象并不共享、不能传值,属于客户端行为。

在Servlet中重定向的语句为

response.sendRedirect("url");

实例:从start.java重定向到after.java的过程
在start.java的service()中写入重定向前的测试代码

System.out.println("这里是start");
resp.sendRedirect("after");

在after.java的service()中写入重定向到底测试代码

System.out.println("这里是after");

启动服务器,在浏览器中输入start的地址
在这里插入图片描述
回车访问后地址立即跳转到after,说明重定向的地址栏会发生改变
在这里插入图片描述
同时控制台输出了
在这里插入图片描述
那么重定向在服务器中的响应头是如何实现的?
如下图,在开发者工具中打开响应头的内容
在这里插入图片描述
会发现start文件响应行的状态码是302,这就是重定向的状态码
并且响应头键值对中Location键的值就是要重定向到的地址:after文件
这与我们在第一节 HTTP协议理论与服务器请求响应原理中学习的响应头的知识首尾呼应起来了

请求转发和重定向的区别

上一节中我们学习了Request对象的请求转发,这一节又学习了Response对象的重定向,两兄弟让人傻傻分不清,必须好好区分区分

请求转发重定向
request.getRequestDispatcher("url").forward(request, response);response.sendRedirect("url");
服务器端行为客户端行为
一次请求,Request域中数据共享两次请求,Request域中数据不共享
地址栏不发生变化地址栏发生变化
跳转只能在当前站点内跳转任意地址

在这一节中我们学习了HttpServletResponse对象,学习了字符流字节流响应方法、重定向方法。不禁思考,Servlet作为“后端”,在Web交互中最重要的作用就是传递各种数据,但目前我们学到的传值的方法还知之甚少,在下一节中我们将学习Cookie对象、HttpSession对象、ServletContext对象,它们作为不同特点的容器在Servlet上可以实现不同范围的传值

这篇关于板块一 Servlet编程:第四节 HttpServletResponse对象全解与重定向 来自【汤米尼克的JAVAEE全套教程专栏】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/727622

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟 开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚 第一站:海量资源,应有尽有 走进“智听