Request&Response

本文深入讲解Servlet中的请求与响应对象,包括请求对象的方法、请求参数处理、请求转发与包含、响应对象的使用方法等核心内容,并探讨了如何解决常见的中文乱码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请求对象-request

请求对象

  • 请求:获取资源。在BS架构中,就是客户端浏览器向服务端发出询问

  • 请求对象:就是在项目中用于发送请求的对象

在这里插入图片描述

Servlet关系视图

在这里插入图片描述

  • 请求对象常用方法-获取各种路径

    返回值方法名说明
    StringgetContextPath()获取虚拟路径名称
    StringgetServletPath()获取Servlet映射路径
    StringgetRemoteAddr()获取访问者ip地址
    StringgetQueryString()获取请求消息数据
    StringgetRequestURI()获取统一资源标识符
    StringBUffergetRequestURL()获取统一资源定位符
    package com.example.student_test;
    
    import javax.servlet.ServletException;
    import javax.servlet.http.HttpServlet;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.PrintWriter;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    
    public class StudentServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    
            String contextPath = req.getContextPath();
            String servletPath = req.getServletPath();
            String remoteAddr = req.getRemoteAddr();
            String queryString = req.getQueryString();
            String requestURI = req.getRequestURI();
            StringBuffer requestURL = req.getRequestURL();
            System.out.println(contextPath);
            System.out.println(servletPath);
            System.out.println(remoteAddr);
            System.out.println(queryString);
            System.out.println(requestURI);
            System.out.println(requestURL);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            super.doPost(req, resp);
        }
    }
    

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9hcWfTiQ-1643289877713)(/Users/heroma/Library/Application Support/typora-user-images/image-20220118211114174.png)]

  • 请求对象常用方法-获取请求头信息

    返回值方法名说明
    StringgetHeader(String name)根据请求头获取一个值
    EnumerationgetHeaders(String name)根据请求头名称获取多个值
    EnumerationgetHeaderNames()获取所有请求头名称
  • 请求对象常用方法-获取请求参数信息

    返回值方法名说明
    StringgetParameter(String name)根据名称获取数据
    String[]getParameterValues(String name)根据名称获取所有数据
    EnumerationgetParameterNames()获取所有名称
    Map<String, String>getParameterMap()获取所有参数的键值对
  • 获取请求参数并封装对象

    • 手动封装

       String username = req.getParameter("username");
              String age = req.getParameter("age");
              String score = req.getParameter("score");
              String[] hobbies = req.getParameterValues("hobbies");
              Student student = new Student(username, age, score, hobbies);
              System.out.println(student);
      
    • 反射封装

       Map<String, String[]> map = req.getParameterMap();
              Student student = new Student();
              for (String key: map.keySet()) {
                  String[] values = map.get(key);
                  //获取Student的属性描述器
                  try {
                      PropertyDescriptor descriptor = new PropertyDescriptor(key, student.getClass());
                      Method method = descriptor.getWriteMethod();
                      if (values.length > 1){
                          method.invoke(student, (Object) values);
                      }else {
                          method.invoke(student, values);
                      }
      
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
      
              }
              System.out.println(student);
      
    • 工具类封装

      Map<String, String[]> map = req.getParameterMap();
      Student student = new Student();
      try {
          BeanUtils.populate(student, map);
      } catch (IllegalAccessException e) {
          e.printStackTrace();
      } catch (InvocationTargetException e) {
          e.printStackTrace();
      }
      

流对象获取请求信息

返回值方法名说明
BufferedReadergetReader()获取字符输入流
ServletInputStreamgetInputStream()获取字节输入流
//字符流post
System.out.println(req);
BufferedReader reader = req.getReader();
String line;
while ((line = reader.readLine()) != null){
    System.out.println(line);
}
//字节流
ServletInputStream inputStream = req.getInputStream();
byte[] arr = new byte[1024];
int len;
while ((len = inputStream.read(arr)) != -1){
    System.out.println(new String(arr,0,len));
}

中文乱码问题

  • get方式

    • 没有乱码问题,在tomcat8版本后已经解决
  • post方式

    • 有乱码问题,可以通过setCharacterEncoding解决

      req.setCharacterEncoding("utf-8");
      

请求域

  • 请求域:可以在一次请求范围内进行数据共享

  • 一般用于请求转发多个资源中共享数据

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7beKyP7h-1643289877713)(/Users/heroma/Library/Application Support/typora-user-images/image-20220120110922458.png)]

  • 请求对象共享数据方法

    返回值方法名说明
    setAttribute(String name, Object value)向请求对象中存储数据
    ObjectgetAttribute(String name)通过名称获取请求域对象中的数据
    voidremoveAttribute(String name)通过名称移除请求对象中的数据

请求转发

  • 请求转发:客户端的一次请求到达后,需要借助其他Servlet来实现功能
  • 特点:
    • 浏览器地址栏不变
    • 域对象中的数据不会丢失
    • 负责转发的servlet转发前后相应的正文会丢失
    • 由转发的目的地来相应客户端
返回值方法名说明
RequestDispatchergetRequestDispatcher(String name)获取请求调度对象
voidforward(ServletRequest req, ServletResponse resp)实现转发
req.setAttribute("encoding","gdk");
RequestDispatcher dispatcher = req.getRequestDispatcher("/hello");
dispatcher.forward(req,resp);

请求包含

  • 请求包含:可以合并其他servlet中的功能一起相应给客户端
  • 特点:
    • 浏览器地址栏不变
    • 域对象中的数据不丢失
    • 被包含的servlet响应头会丢失
返回值方法名说明
RequestDispatchergetRequestDispatcher(String name)获取请求调度对象
voidinclude(ServletRequest req, ServletResponse resp)实现包含
System.out.println("studentServlet执行了");
RequestDispatcher dispatcher = req.getRequestDispatcher("/hello");
dispatcher.include(req,resp);

响应对象介绍

  • 响应:回馈结果。在BS架构中,就是服务器给客户端浏览器反馈信息
  • 响应对象:就是在项目中发送相应的对象
  • 响应对象也是是Servlet规范中定义的,它包括了协议无关的和协议相关的。
    • 协议无关的对象标准是:ServletResponse接口
    • 协议相关的对象标准是:HttpServletResponse接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7mhac1gz-1643289877714)(/Users/heroma/Library/Application Support/typora-user-images/image-20220127101033924.png)]

  • 常见状态码:

    状态码说明
    200执行成功
    302它和307一样,都是用于重定向的状态码。只是307目前已不再使用
    304请求资源未改变,使用缓存。
    400请求错误。最常见的就是请求参数有问题
    404请求资源未找到
    405请求方式不被支持
    500服务器运行内部错误
  • 状态码首位含义:

    状态码说明
    1xx消息
    2xx成功
    3xx重定向
    4xx客户端错误
    5xx服务器错误

字节流响应消息

返回值方法名说明
ServletOutputStreamgetOutputStream()获取响应字节输出流对象
voidsetContentType(“text/html;charset=UTF-8”)设置响应内容类型,解决中文乱码问题

字符流响应消息

返回值方法名说明
PrintWritergetWriter()获取响应字符流输出对象
setContentType(“text/html;charset=UTF-8”)设置响应内容类型,解决中文乱码问题
resp.setContentType("text/html;charset=UTF-8");
//获取字符输出流对象
PrintWriter writer = resp.getWriter();
//定义一个消息
String str = "祝你好运";
//通过字符流输出
writer.write(str);
writer.println(str);

响应图片

  1. 创建字节输入流对象,关联读取的图片路径
  2. 通过响应对象获取字节输出流对象
  3. 循环读取和写出图片
String realPath = getServletContext().getRealPath("/img/hi.jpeg");
System.out.println(realPath);
//1. 创建字节输入流对象,关联读取的图片路径
BufferedInputStream stream = new BufferedInputStream(new FileInputStream(realPath));
//2. 通过响应对象获取字节输出流对象
ServletOutputStream outputStream = resp.getOutputStream();
//3. 循环读取和写出图片
byte[] arr = new byte[1024];
int len;
while ((len = stream.read(arr)) != -1){
    outputStream.write(arr,0,len);
}
//4. 关闭资源
stream.close();

设置缓存

  • 缓存:对于不经常变化的数据,我们可以设置缓存时间,以避免浏览器频繁请求服务器。以此来提高效率

    返回值方法名说明
    voidsetDateHeader(String name, long time)设置消息头加缓存
    String str = "这是一条很火爆的新闻";
    //设置缓存
    resp.setDateHeader("Expires", System.currentTimeMillis() + 1*60*60*1000);
    //设置编码格式
    resp.setContentType("text/html;charset=UTF-8");
    //写出数据
    resp.getWriter().write(str);
    System.out.println("aaaaa");
    

定时刷新

  • 定时刷新:过了指定时间后,页面自动进行跳转

    返回值方法名说明
    voidsetHeader(String name, String value)设置消息头定时刷新
String message = "你的用户名或者密码有误,三秒后将自动跳转登录页面。";
//设置页面编码格式
resp.setContentType("text/html;charset=UTF-8");
resp.getWriter().write(message);
//定时刷新
resp.setHeader("Refresh","3;URL=/stu/addStudent.html");

请求重定向

  • 请求重定向:客户端的一次请求到达后没发现需要借助其他servlet来伤心啊功能

  • 特点:浏览器地址栏会发生变化,两次请求,请求域对象中不能共享数据,可以重定向到其他服务器

  • 重定向的原理

    • 设置响应状态码为302
      • resp.setStatus(302)
    • 设置相应的资源路径(响应到哪里去,通过响应头location来指定)
      • resp.setHeader(“location”,"/stu/addStudent.html");
  • 响应对象重定向方法

    返回值方法名说明
    sendRedirect(String name)设置重定向
    req.setAttribute("username","zhangsan");
    resp.sendRedirect("/stu/add");
    

文件下载

  1. 创建字节输入流,关联读取的文件
  2. 设置响应消息头支持的类型
  3. 设置响应消息头以下载的方式打开资源
  4. 通过响应对象获取字节输出流对象
  5. 循环读写
  6. 释放资源
//1. 创建字节输入流,关联读取的文件
String realPath = getServletContext().getRealPath("/img/hi.jpeg");
BufferedInputStream stream = new BufferedInputStream(new FileInputStream(realPath));
//2. 设置响应消息头支持的类型  Content-type:消息头名称  Application/octet-stream:消息头参数,应用的类型为字节流
resp.setHeader("Content-type","Application/octet-stream");
//3. 设置响应消息头以下载的方式打开资源   Content-Disposition:消息头名称   处理的形式  attachment;filename=1.jpeg 消息头参数,附件方式进行处理 指定下载文件的名称
resp.setHeader("Content-Disposition","attachment;filename=1.jpeg");
//4. 通过响应对象获取字节输出流对象
ServletOutputStream os = resp.getOutputStream();
//5. 循环读写
byte[] arr = new byte[1024];
int len;
while ((len = stream.read(arr)) != -1){
    os.write(arr, 0,len);
}
//6. 释放资源
stream.close();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heromps

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值