HttpServletRequest与HttpServletResponse

web服务器接收到客户端的http请求后,针对这个请求,分别创建一个代表请求的HttpServletRequest对象和一个代表响应的HttpServletResponse对象。

  • 获取客户端请求过来的参数:HttpServletRequest
  • 给客户端响应一些数据:HttpServletResponse

1、HttpServletRequest

HttpServletRequest代表客户端的请求,用户通过HTTP协议访问服务器,HTTP请求中的所有信息会被封装到HttpServletRequest对象中,通过HttpServletRequest的方法,可以获得客户端的所有信息。

1.1、获取前端传递的参数与请求转发

1.1.1、获取前端的参数
  • getParameter():获取前端的数据,根据name获取到value,返回一个String类型的数据。
  • getParameterValues():获取前端的数据,根据name获取到value,返回的是一个String[]数组,即获取的值有多个。
1.1.2、请求转发
  • getRequestDispatcher():括号内参数传入转发的路径,“/”:解析为当前项目,即:http://localhost:8080/servletStudy。
  • forward(request,response):调用此方法,达到转发的目的。
    示例:获取前端登录页面传来的数据,进行简单的验证,根据结果进行转发

servlet:

public class LoginServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置请求与响应的编码
        request.setCharacterEncoding("UTF-8");
        response.setCharacterEncoding("UTF-8");
        // 获取前端传递来的参数
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String[] skills = request.getParameterValues("skills");
        // 验证输入的username和password
        if (username.equals("admin") && password.equals("123456")){
            System.out.println("登陆成功!");
            request.getRequestDispatcher("/success.jsp").forward(request,response);
        }else {
            System.out.println("登录失败!");
            request.getRequestDispatcher("/failure.jsp").forward(request,response);
        }
        System.out.println(username);
        System.out.println(password);
        for (String str : skills) {
            System.out.print(str + "\t");
        }
        System.out.println("admin" == username);
        System.out.println("123456" == password);
    }
}

登录页面:

  • ${pageContext.request.contextPath}是JSP取得绝对路径的方法,即取出当前项目的名称
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>首页</title>
    </head>
    <body>
        <div>
            <form method="get" action="${pageContext.request.contextPath}/login">
                账号:<input type="text" name="username"><br/>
                密码:<input type="password" name="password"><br/>
                技能:<input type="checkbox" name="skills" value="java" checked>Java
                <input type="checkbox" name="skills" value="python">Python
                <input type="checkbox" name="skills" value="c++">C++
                <input type="checkbox" name="skills" value="php">PHP<br/>
                <input type="submit" value="好兄弟,填好点我">
            </form>
        </div>
    </body>
</html>

根据输入的账户密码是否正确跳转到success.jsp与failure.jsp

2、HttpServletResponse

HttpServletResponse获取两个输出流:getPOutputStream()和getWiter()。获取的两个输出流不能同时使用,会报错。

HttpServletResponse应用:

2.1、浏览器下载文件

  • 步骤
  1. 获取文件的路径(相对路径与绝对路径都可)
  2. 获取文件名(把整个文件路径当作String的一个实例,调用substring方法,截取文件名,多多细品,我是刚学的这个方法,越品越有味儿)
  3. 告诉浏览器,我们要下载东西,即让浏览器支持我们下载文件(这一步向切要!!)
  4. 创建文件输入流读取下载的文件
  5. 创建响应输出流,在浏览器中响应并写出(下载)文件
  6. 关闭流资源
/**
 * 使用HttpServletResponse实现下载文件
 *
 * @Author:xiezr
 * @Creat:2021-07-29 15:12
 */
public class HttpServletResponseTest extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, UnsupportedEncodingException {
        // 1.
        String filePath = "G:\\SummerWeb\\servletStudy\\src\\main\\webapp\\images\\beautifulGirl.jpg";
        // 2.使用substring截取文件名
        String fileName = filePath.substring(filePath.lastIndexOf("\\") + 1);
        // 3.设置浏览器支持下载文件,设置文件名编码格式为UTF-8,防止下载的时候文件名显示错误乱码
        resp.setHeader("Content-disposition","attachment;filename"+ URLEncoder.encode(fileName,  "UTF-8"));
        // 4.使用缓冲流,提高效率
        BufferedInputStream fis = null;
        BufferedOutputStream bos = null;
        try {
            fis = new BufferedInputStream(new FileInputStream(filePath));
            // 5.创建响应输出流,ServletOutputStream继承与OutputStream,属于节点流
            ServletOutputStream sos = resp.getOutputStream();
            bos = new BufferedOutputStream(sos);
            // 读取文件,写出文件到浏览器,即下载
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1){
                bos.write(buffer,0,len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            // 6.关闭资源就不显示了
        }
    }
}

运行结果:

response 输出信息到前端 前端如何获取response参数_servlet


2.2、图片验证码

  • 步骤:要有验证码和图片,把验证码写进图片里面
  1. 定义一个方法,生成随机数
  2. 让浏览器刷新(也可不用,自己手动刷新更改验证码)
  3. 在内存中创建图片,使用BufferedImage类(此时的图片只有宽,高)
  4. 获得图片并对图片进行修改
  5. 给图片写入验证码
  6. 告诉浏览器请求打开的方式,即setContextType()
  7. 把图片写给浏览器
public class CheckCodeServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 1.
        response.setHeader("refresh","3");
        // 2.
        BufferedImage image = new BufferedImage(100, 30, BufferedImage.TYPE_INT_RGB);
        // 3.获取“画笔”工具
        Graphics2D graphics = (Graphics2D) image.getGraphics();
        // 修改背景颜色,填充颜色
        graphics.setColor(Color.white);
        graphics.fillRect(0,0,100,30);
        // 4.给图片写数据
        graphics.setColor(Color.MAGENTA);
        // 设置字体类型与字体大小
        graphics.setFont(new Font(null,Font.BOLD,30));
        // 将随机数写入图片
        graphics.drawString(productCode(),0,30);
        // 5.
        response.setContentType("image/jpg");
        // 设置浏览器不要缓存
        response.setDateHeader("expires",-1);
        response.setHeader("Cache-Control","no-cache");
        response.setHeader("Pragma","no-cache");
        // 6.图片IO流写出到浏览器上
        ImageIO.write(image,"jpg",response.getOutputStream());

    }
    // 生成随机数
    public String productCode(){
        Random random = new Random();
        // 把生成的随机数转换为String类型
        String str = String.valueOf(random.nextInt(666666));
        // 如果随机数生成的位数少于6为,使用0补齐
        StringBuffer sbuffer = new StringBuffer();
        for (int i = 0; i < 6 - str.length(); i++) {
            sbuffer.append("0");
        }
        return sbuffer + str;
    }
}

运行结果:

response 输出信息到前端 前端如何获取response参数_请求转发_02

2.3、HttpServletResponse实现重定向

  • sendRedirect():设置重定向到哪里。(常用)
    或者设置响应头:
  • setStatus(302):设置响应状态码
  • setHeader(“Location”,"/项目名/资源路径"):设置新的访问地址

一个web资源收到客户端的请求后,他会通知客户端去访问另一个web资源,这个过程叫做重定向(地址栏的url地址会改变)。

response 输出信息到前端 前端如何获取response参数_重定向_03

public class RedirectTest extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.sendRedirect("/servletStudy/hello");
    }
}

看一下浏览器:

response 输出信息到前端 前端如何获取response参数_servlet_04

3、请求转发与请求重定向的区别

  1. 相同点:都会实现页面的跳转
  2. 不同点
  • 请求转发的时候,url地址栏不会发生变化,响应状态码为307。请求重定向的时候,url地址栏会发生变化,响应状态码为302
  • 请求转发是一次请求,请求重定向是两次请求
  • 请求转发可以共享Request域中的数据,请求重定向不共享Request域中的数据,因为是两次请求,Tomcat每次请求都把数据封装到一个HttpServletRequest对象中。
  • 请求转发可以访问WEB-INF目录下的资源,请求重定向无法访问WEB-INF目录下的资源。(/WEB-INF在浏览器地址栏中是受保护,访问不到的)
  • 请求转发无法访问工程以外的资源,请求重定向可以访问工程外的资源

浏览器地址栏

请求次数

是否共享Request域的数据

能否访问WEB-INF目录下的资源

能否访问工程外的资源

请求转发

没有改变

一次




请求重定向

发生改变

两次