请求转发
- 概述
- 跳转资源,内部资源跳转
- 特点
- 请求转发只有一个请求;
- 请求转发是内部资源跳转;
- 请求转发的网址不会发生改变
- 代码实现
/**
* 请求转发
*/
@WebServlet("/demo01")
public class Demo01Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo01Servlet");
//1,获取请求调度器
RequestDispatcher requestDispatcher = request.getRequestDispatcher("demo02");
//2,请求转发
requestDispatcher.forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
/**
* 请求转发
*/
@WebServlet("/demo02")
public class Demo02Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo02Servlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
适用场景
/**
* 请求转发到WEB-INF目录中资源
*/
@WebServlet("/demo03")
public class Demo03Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// "/web07/demo03" 访问 "/web07/WEB-INF/boy1.jpg"
request.getRequestDispatcher("WEB-INF/boy1.jpg").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
resquest作为域对象
- 概述
- request作为域对象,数据的共享范围为一次请求
- 代码实现
@WebServlet("/demo04")
public class Demo04Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
int num = 250;
request.setAttribute("num", num);
//请求转发
request.getRequestDispatcher("demo05").forward(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
@WebServlet("/demo05")
public class Demo05Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer num = (Integer) request.getAttribute("num");
System.out.println("num = " + num);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
响应对象概述
-
概述
Defines an object to assist a servlet in sending a response to the client. The servlet container creates a ServletResponse object and passes it as an argument to the servlet's service method.
- 是一个用于向浏览器发送响应的对象,该对象由服务器创建,并通过Servlet的service方法传递给Servlet适用。
-
作用
- 操作响应行、响应头、响应正文
-
关系视图
响应对象之输出内容
- 概述
- 通过response对象向浏览器输出内容
- 代码实现
/**
* 响应对象之输出内容
*/
@WebServlet("/demo06")
public class Demo06Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.1,告诉服务器,以utf-8编码响应正文
//response.setCharacterEncoding("utf-8");
//1.2,告诉浏览器,以utf-8解码响应正文
//response.setHeader("Content-Type","text/html;charset=utf-8");
//1,告诉服务器,以utf-8编码响应正文;告诉浏览器,以utf-8解码响应正文。
response.setContentType("text/html;charset=utf-8");
//向页面输出"helloworld" : 操作响应正文
response.getWriter().write("你好世界");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
响应对象值定时跳转
- 概述
- response对象通过操作refresh响应头达到定时跳转资源的目的。
- 代码实现
@WebServlet("/demo07")
public class Demo07Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo07Servlet date : " + new Date());
//定时跳转
response.setHeader("Refresh", "3;url=demo08");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
@WebServlet("/demo08")
public class Demo08Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Date date = new Date();
System.out.println("Demo08Servlet date = " + date);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
重定向
- 概述
- 跳转资源,外部资源跳转;
- response对象操作状态码=302,操作响应头location
- 特点
- 重定向是有两次请求;
- 重定向的网址栏会发生变化
- 代码实现
@WebServlet("/demo09")
public class Demo09Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo09Servlet");
//重定向Demo10Servlet
//response.setStatus(302);
//response.setHeader("location", "demo10");
response.sendRedirect("demo10");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
@WebServlet("/demo10")
public class Demo10Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo10Servlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
资源跳转的路径问题
- 资源跳转
- 相对路径
- 请求转发 : ok
- 重定向 : ok
- 绝对路径
- 请求转发:/资源访问路径
- 重定向:/项目访问路径/资源访问路径
- 相对路径
- 代码实现
/**
* 资源跳转的路径问题
*/
@WebServlet("/demo11")
public class Demo11Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("Demo11Servlet");
//相对路径
//请求转发 : ok
//request.getRequestDispatcher("demo12").forward(request, response);
//重定向 : ok
//response.sendRedirect("demo12");
//绝对路径
//请求转发 : 内部资源跳转,/资源访问路径
//request.getRequestDispatcher("/demo12").forward(request, response);
//request.getRequestDispatcher("www.baidu.com").forward(request, response);
//重定向 : 外部资源跳转,ok , /项目访问路径/资源访问路径
response.sendRedirect("http://www.baidu.com");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
响应对象之文件下载问题解决
- 概述
- 将服务器中的文件拷贝到本地电脑(浏览器)中;
- 浏览器支持最简易的下载功能(能够解析那么就直接解析展示,如果不能解析就下载)
- 开发步骤
- ①获取下载文件的名称
- ②服务器告诉浏览器下载文件的mimeType
- ③服务器告诉浏览器必须弹出下载窗口(Content-Disposition)
- ④通过IO流将服务器中文件拷贝到浏览器中
- 代码实现
/**
* 文件下载
*/
@WebServlet("/download")
public class Demo13Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("download");
//①获取下载文件的名称
String fileName = "girl1.jpg";
//②服务器告诉浏览器下载文件的mimeType
//2.1,获取下载文件的mimeType
String mimeType = getServletContext().getMimeType(fileName);
response.setContentType(mimeType);
//③服务器告诉浏览器必须弹出下载窗口(Content-Disposition)
response.setHeader("Content-Disposition", "attachement;filename=" + fileName);
//④通过IO流将服务器中文件拷贝到浏览器中
//4.1,获取下载文件的路径(真实磁盘路径) :
// E:\workspace\211018\web07\web\download\girl1.jpg
// E:\workspace\211018\web07\out\artifacts\web07_war_exploded\download\girl1.jpg
String filePath = getServletContext().getRealPath("/download/" + fileName);
//4.2,获取下载文件的输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
//4.3,获取高效字节输出流(向浏览器写出下载文件的字节数据)
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
//4.4,边读边写
int len = -1;
byte[] bys = new byte[8192];
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
//4.5,释放资源
bis.close();
bos.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
存在问题
- ①用户手动输入下载文件名称
- ②下载文件中文文件名称乱码
package com.atguigu.servler;
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.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
/**
* 文件下载
*/
@WebServlet("/download")
public class Demo13Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("download");
//①获取下载文件的名称
String fileName = request.getParameter("filename");
//②服务器告诉浏览器下载文件的mimeType
//2.1,获取下载文件的mimeType
String mimeType = getServletContext().getMimeType(fileName);
response.setContentType(mimeType);
//③服务器告诉浏览器必须弹出下载窗口(Content-Disposition)
String newFileName = URLEncoder.encode(fileName,"utf-8");
response.setHeader("Content-Disposition", "attachement;filename=" + newFileName);
//④通过IO流将服务器中文件拷贝到浏览器中
//4.1,获取下载文件的路径(真实磁盘路径) :
String filePath = getServletContext().getRealPath("/download/" + fileName);
//4.2,获取下载文件的输入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filePath));
//4.3,获取高效字节输出流(向浏览器写出下载文件的字节数据)
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
//4.4,边读边写
int len = -1;
byte[] bys = new byte[8192];
while ((len = bis.read(bys)) != -1) {
bos.write(bys, 0, len);
}
//4.5,释放资源
bis.close();
bos.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
Servlet的线程安全
- 概述
- 通过Servlet生命周期,知道Servlet是多线程单实例的,会存在线程安全问题。
- 解决方案
- ①使用锁机制
- 效率低
- ②尽量避免使用成员变量,而是使用局部变量
- ①使用锁机制
- 线程安全演示
@WebServlet("/demo14")
public class Demo14Servlet extends HttpServlet {
private Integer num = 0;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
num = Integer.parseInt(request.getParameter("num"));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("num = " + num);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
①使用锁机制
@WebServlet("/demo14")
public class Demo14Servlet extends HttpServlet {
private Integer num = 0;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
synchronized (this) {
num = Integer.parseInt(request.getParameter("num"));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("num = " + num);
}
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}
②尽量避免使用成员变量,而是使用局部变量
@WebServlet("/demo14")
public class Demo14Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
Integer num = Integer.parseInt(request.getParameter("num"));
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("num = " + num);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doGet(request, response);
}
}