ServletResponse
To send binary data in a MIME body response, use the ServletOutputStream
returned by getOutputStream()
). To send character data, use the PrintWriter
object returned by getWriter()
).
设置响应报文
响应行
响应头
响应体
传输字符数据中文乱码
锟斤拷烫烫烫 —— utf-8 gbk
?????? 表示压根不支持中文
服务器处理响应体使用的编码格式压根不支持中文,ISO-8859-1
浣犲ソ锛侊紒锛侊紒
package com.cskaoyan.response;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/response2")
public class ResponseServlet2 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//设置响应报文
//设置了该API之后,说明服务器设置的编码格式已经生效,这个时候如果还是乱码,只能说明一个问题
//浏览器使用的不是utf-8进行解码
//浏览器使用的是gbk(1.和你的平台编码--操作系统的编码 2.和你的语言有关)
//将这个改成gbk不是正确的处理流程,假设一台浏览器使用的默认编码格式不是gbk,不是又乱码了吗
//浏览器其实是支持很多种编码格式的,不管服务器采用那种编码格式,那么你设置了之后,告诉浏览器不就行了吗
//response.setCharacterEncoding("utf-8");
//如何告诉浏览器呢?1.响应头 2.响应体
//这个头其实有两层含义:1.设置服务器编码格式utf-8 2发送响应头,告诉浏览器使用的是utf-8
response.setHeader("Content-Type","text/html;charset=utf-8");
response.getWriter().println("你好!!!!");
}
}
方式二
package com.cskaoyan.response;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/response4")
public class ResponseServlet4 extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//中文乱码问题,解决方案二
//response.setContentType("text/html;charset=utf-8");
//设置响应体的编码格式utf-8,还需要将编码格式告诉给浏览器
//可以通过响应头,也可以通过响应体
//可以在代码里面写入html标签以及css、js代码,普通的文本
//只是这些文本对于浏览器来说,她们具有特殊的含义
response.setCharacterEncoding("utf-8");
response.getWriter().println("<!DOCTYPE html>\n" +
"<html lang=\"en\">\n" +
"<head>\n" +
" <meta charset=\"UTF-8\">\n" +
" <title>Title</title>\n" +
"</head>\n" +
"<body>");
response.getWriter().println("你好!!!!");
response.getWriter().println("</body>\n" +
"</html>");
}
}
输出字节数据到客户端
字节数据,二进制数据,文本、图片、音视频等
就是把二进制数据写入到响应体中,传输给客户端,客户端拿到之后进行解析,渲染出来
写入到响应体的API:
response.getWriter().prinltn()这个是写字符的,写字节的话需要使用另外一个API
response.getOutputStream()
第一个是将流写入到文件中
第二个是将流写入到response的缓冲区中,目的地不同,写入方式完全相同
package com.cskaoyan.response;
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.File;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet("/stream")
public class StreamServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String realPath = getServletContext().getRealPath("1.jpg");
//String realPath = getServletContext().getRealPath("WEB-INF/1.html");
FileInputStream inputStream = new FileInputStream(new File(realPath));
ServletOutputStream outputStream = response.getOutputStream();
int length = 0;
byte[] bytes = new byte[1024];
while ((length = inputStream.read(bytes)) != -1){
outputStream.write(bytes, 0, length);
}
//应该关闭流
inputStream.close();
//输出流可以关闭也可以不关闭,如果不关闭的话,tomcat会帮我们关闭
outputStream.close();
}
}
作业:
要求你在当前应用下实现一个缺省Servlet。
url-pattern必须是/。
静态资源文件就不能正常显示了,你需要做的事情,是静态资源文件还可以正常的显示出来。
package com.cskaoyan.response;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/")
public class MyDefaultServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("/");
//关于路径相关的API
String requestURI = request.getRequestURI();
String requestURL = request.getRequestURL().toString();
//该API返回当前应用的应用名
String contextPath = request.getContextPath();
//返回的路径: servletPath相对部署根目录的一个相对路径
// servletPath = requestURI - contextPath
String servletPath = request.getServletPath();
System.out.println(requestURI);
System.out.println(requestURL);
System.out.println(contextPath);
System.out.println(servletPath);
}
}
其他两种页面跳转技术
refresh响应头
package com.cskaoyan.response;
import javax.servlet.ServletException;
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.text.SimpleDateFormat;
import java.util.Date;
@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//refresh是一个响应头,
//页面会一直刷新,动态显示时间 Mon Nov 30 10:14:17 CST 2020
// 希望将时间改成这种格式 2020-11-30 10:13:00
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formateDate = format.format(new Date());
response.getWriter().println(formateDate);
//表示每隔指定秒数刷新当前页面
//response.setHeader("refresh", "1");
//表示经过指定描述之后跳转至url,然后结束
// response.setHeader("refresh","3;url=http://www.baidu.com");
response.setHeader("refresh","3;url=" + request.getContextPath() + "/load.html");
}
}
重定向
302、307 www.bing.com
需要状态码以及一个Location响应头
package com.cskaoyan.response;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//先根据重定向的定义以及之前学习的API自己先实现一下重定向
//response.setStatus(302);
//response.setHeader("Location", "http://www.baidu.com");
//JavaEE规范给我们提供了一个API来实现重定向
response.sendRedirect(request.getContextPath() + "/load.html");
}
}
package com.cskaoyan.response;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
if("admin".equals(username) && "admin".equals(password)){
//表示登录成功
//跳转的方式可以有如下三种:1.转发 2.定时刷新 3 重定向
//request.getRequestDispatcher("/success.html").forward(request, response);
// response.getWriter().println("登录成功,即将跳转至登录成功页面,如果没有跳转," +
// "可以点击<a href='" + request.getContextPath() + "/success.html" +"'>当前链接</a>手动跳转");
// response.setHeader("refresh", "10;url=" + request.getContextPath() + "/success.html");
response.sendRedirect(request.getContextPath() + "/success.html");
}
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
几种页面跳转技术的区别
转发、重定向、定时刷新
转发是一次请求,可以共享request域;其他两个是两次请求,不可以共享request域
转发只能转发到当前应用下;其他两种技术不受限制
转发是request介导的;其他两种是response介导的
转发是服务器介导的;其他两种是浏览器介导的
下载
先说浏览器的行为。
浏览器对于可以打开的文件执行打开操作,对于无法打开的文件默认执行下载操作。但是如果对于这部分浏览器可以打开的,如果希望浏览器执行下载,可以使用响应头,告诉浏览器执行下载操作,而不是打开。
package com.cskaoyan.response;
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.File;
import java.io.FileInputStream;
import java.io.IOException;
@WebServlet("/download")
public class DownloadServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//把1.jpg下载到本地
response.setHeader("Content-Disposition", "attachment;filename=1.jpg");
String realPath = getServletContext().getRealPath("1.jpg");
//String realPath = getServletContext().getRealPath("WEB-INF/1.html");
FileInputStream inputStream = new FileInputStream(new File(realPath));
ServletOutputStream outputStream = response.getOutputStream();
int length = 0;
byte[] bytes = new byte[1024];
while ((length = inputStream.read(bytes)) != -1){
outputStream.write(bytes, 0, length);
}
//应该关闭流
inputStream.close();
//输出流可以关闭也可以不关闭,如果不关闭的话,tomcat会帮我们关闭
outputStream.close();
}
}