Javaweb学习笔记day07---Web体系Servlet

37 篇文章 0 订阅
9 篇文章 0 订阅

请求转发

  • 概述
    • 跳转资源,内部资源跳转
  • 特点
    • 请求转发只有一个请求;
    • 请求转发是内部资源跳转;
    • 请求转发的网址不会发生改变
  • 代码实现
/**
 * 请求转发
 */
@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适用。
  • 作用

    • 操作响应行、响应头、响应正文
  • 关系视图

    • image-20211206092716895

响应对象之输出内容

  • 概述
    • 通过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);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值