JavaWeb学习之Request&Response

Request&Response

  • Request:获取请求数据
  • Response:设置响应数据

Request

Request 继承体系

继承体系

  1. Tomcat需要解析请求数据,封装为request对象,并且创建request对象传递到service方法中
  2. 使用request对象,查阅JavaEE API文档的HttpServletRequest接口

Request获取请求数据

  • 请求数据分为3部分:
    1. 请求行:GET /request-demo/req1?username=zhangsan HTTP/1.1
      • String getMethod():获取请求方式:GET
      • String getContextPath():获取虚拟目录(项目访问路径): /request-demo
      • StringBuffer getRequestURL():获取URL(统一资源定位符): http://localhost:8080/request-demo/req1
      • String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
      • String getQueryString():获取请求参数(GET方式): username=zhangsan&password=123
    2. 请求头:User-Agent: Mozilla/5.0 Chrome/91.0.4472.106
      • String getHeader(String name):根据请求头名称,获取值
    3. 请求体:username=superbaby&password=123
      • ServletlnputStream getInputStream():获取字节输入流
      • BufferedReader getReader():获取字符输入流

Request通用方式获取请求参数

  • 请求参数获取方式:

    GET方式:

    • String getQueryString()

    POST方式

    • BufferedReader getReader()

思考:
GET请求方式和POST请求方式区别主要在于获取请求参数的方式不一样,是否可以提供一种统一获取请求参数的方式,从而统一doGet和doPost方法内的代码?

  • Map<String, String[ ]> getParameterMap():获取所有参数Map集合
  • String[ ] getParameterValues(String name)︰根据名称获取参数值(数组)
  • String getParameter(String name):根据名称获取参数值(单个值)

示例:

//前端文件
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="GBK">
    <title>requestDemo</title>
</head>
<body>
<form action="/webdemo/request" method="post">
    <input type="text" name="username"> <br>
    <input type="password" name="password"> <br>
    <input type="checkbox" name="hobby" value="1"> 游泳 
    <input type="checkbox" name="hobby" value="2"> 跳绳 <br>
    <input type="submit">
</form>
</body>
</html>
//RequestDemo后端文件
package com.jihua.webdemo;

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.util.Map;


@WebServlet("/request")
public class RequestDemo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //1. 获取所有参数的Map集合
        Map<String, String[]> parameterMap = req.getParameterMap();
        for (String key : parameterMap.keySet()) {
            System.out.print(key + ":");
            //获取值
            String[] values = parameterMap.get(key);
            for (String value : values) {
                System.out.print(value + " ");
            }
            System.out.println();
        }
        System.out.println("------");
        //2. 根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        System.out.println("hobby: ");
        for (String hobby : hobbies) {
            System.out.print(hobby + " ");
        }
        System.out.println();
        System.out.println("------");
        //3.根据key获取单个参数值
        String username = req.getParameter("username");
        String password = req.getParameter("password");
        System.out.println(username);
        System.out.println(password);
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
}
//控制台输出
username:zhangsan 
password:123123 
hobby:1 2 
------
hobby: 
1 2 
------
zhangsan
123123
  • 使用通用方式获取请求参数后,屏蔽了GET和POST的请求方式代码的不同,则代码可以定义为如下格式:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        ······
    }
    
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        this.doGet(req, resp);
    }
    
  • 可以使用Servlet模板创建Servlet更高效

右键新建文件时选择Servlet,如果没有就打开项目结构选择Facet下方根源勾选相应目录

可在设置-编辑器-文件和代码模板-其他-Web-Java代码模板-Servlet Annotated Class.java修改每次创建的模板

请求参数中文乱码处理

  • 请求参数如果存在中文数据,则会乱码

  • 解决乱码:

  • POST:getReader()

    request.setcharacterEncoding("UTF-8");//设置字符输入流的编码
    
  • GET:获取参数的方式: getQueryString

    乱码原因:浏览器在传输中文请求时,将中文使用相应的字符编码方式进行URL转换,将中文转为十六进制数并用%隔开,数据传到Tomcat后再进行URL解码,Tomcat使用lSO-8859-1解码,不可更改,而浏览器一般选择UTF-8编码,编解码使用的字符集不一致,所以造成了乱码

    Java自带一个处理URL编解码的类

    package com.jihua.webdemo;
    
    import java.io.UnsupportedEncodingException;
    import java.net.URLDecoder;
    import java.net.URLEncoder;
    
    public class URLDemo {
        public static void main(String[] args) throws UnsupportedEncodingException {
            String username = "张三";
            //1. URL编码
            String encode = URLEncoder.encode(username, "utf-8");
            System.out.println(encode);
            //2. URL解码
            String decode = URLDecoder.decode(encode, "utf-8");
            System.out.println(decode);
        }
    }
    
    //输出
    %E5%BC%A0%E4%B8%89
    张三
    
    进程已结束,退出代码0
    

    解决方法:

    //3.1先对乱码数据进行编码:转为字节数组
    byte[] bytes = username.getBytes(StandardCharsets.ISO_8859_1);
    
    //3.2字节数组解码
    username = new String(bytes,StandardCharsets.UTF_8);
    System.out.println(username);
    
  • 通用解决方式:

    username = new String(username.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
    

Tomcat 8.0之后,已将GET请求乱码问题解决,设置默认的解码方式为UTF-8

Request请求转发

请求转发

  • 请求转发(forward):一种在服务器内部的资源跳转方式

  • 实现方式:

    req.getRequestDispatcher("资源B路径").forward(req,resp);
    
  • 请求转发资源间共享数据:使用Request对象

    • void setAttribute(String name, Object o):存储数据到request域中Object
    • getAttribute(String name):根据key,获取值
    • void removeAttribute(String name):根据key,删除该键值对

    例如:

    //在demo1中:
    req.setAttribute("msg","hello");
    req.getRequestDispatcher("/demo2").forward(req,resp);
    //在demo2中:
    Object msg = req.getAttribute("msg");
    System.out.println(msg);
    
  • 请求转发特点:

    • 浏览器地址栏路径不发生变化
    • 只能转发到当前服务器的内部资源
    • 一次请求,可以在转发的资源间使用request共享数据

Response

Response设置响应数据功能介绍

  • 响应数据分为3部分:
    1. 响应行:HTTP/1.1 200 OK
      • void setStatus(int sc)︰设置响应状态码
    2. 响应头:Content-Type: text/html
      • void setHeader(String name, String value)︰设置响应头键值对
    3. 响应体:<html><head>head><body></body></html>
      • PrintWriter getWriter():获取字符输出流
      • ServletOutputStream getOutputStream():获取字节输出流

Response完成重定向

  • 重定向(Redirect):一种资源跳转方式

  • 实现方式:

    //1. 设置响应状态码
    resp.setStatus(302);
    //2. 设置重定向路径
    resp.setHeader("location","“资源B的路径");
    
    //简化方式完成重定向
    response. sendRedirect( location: "/request-demo/resp2");
    
  • 重定向特点:

    • 浏览器地址栏路径发生变化
    • 可以重定向到任意位置的资源(服务器内部、外部均可)
    • 两次请求,不能在多个资源使用request共享数据
路径问题
  • 明确路径谁使用?

    • 浏览器使用:需要加虚拟目录(项目访问路径)
    • 服务端使用:不需要加虚拟目录
  • 举例

    • <a href='路径'> 加虚拟目录
    • <form action='路径'> 加虚拟目录
    • req.getRequestDispatcher("路径") 不加虚拟目录(转发)
    • resp.sendRedirect("路径") 加虚拟目录(重定向)
  • 动态获取虚拟目录

    String contextPath = request.getcontextPath();
    

Response响应字符数据

  • 使用:

    1. 通过Response对象获取字符输出流

      PrintWriter writer = resp.getWriter();
      
    2. 写数据

      writer.write("aaa");
      
  • 示例:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取字符输出流
        PrintWriter writer = resp.getWriter();
        // content-type
        resp.setHeader("content-type" ,"text/html");
        writer.write("aa");
        writer.write("<h1>aaa</h1>");
    }
    
  • 简化content-type书写以及解决中文乱码问题

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // content-type
        resp.setContentType("text/html;charset=utf-8");
        // 获取字符输出流
        PrintWriter writer = resp.getWriter();
    
        writer.write("你好");
        writer.write("<h1>aaa</h1>");
    }
    
  • 注意:

    • 该流不需要关闭,随着响应结束,response对象销毁,由服务器关闭

    • 中文数据乱码:原因通过Response获取的字符输出流默认编码:ISO-8859-1

      resp.setContentType("text/html;charset=utf-8");
      

Response响应字节数据

  • 使用:

    1. 通过Response对象获取字符输出流

      ServletOutputStream outputStream = resp.getOutputStream();
      
    2. 写数据

      outputStream.write(字节数据);
      
  • 示例:

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取字节输出流
        ServletOutputStream os = resp.getOutputStream();
        // 读取文件
        FileInputStream fis = new FileInputStream("D:/图片/work.png");
        //拷贝
        byte[] ch = new byte[1024];
        int len = 0;
        while ((len=fis.read(ch))!=-1) {
            os.write(ch,0,len);
        }
    }
    
  • 可以使用lOUtils工具类简化流的复制

    首先用maven导入

    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
    

    然后导包使用

    import org.apache.commons.io.IOUtils;
    
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 获取字节输出流
        ServletOutputStream os = resp.getOutputStream();
        // 读取文件
        FileInputStream fis = new FileInputStream("D:/图片/work.png");
        //拷贝
        IOUtils.copy(fis,os);
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值