1.7 Java全栈开发前端+后端(全栈工程师进阶之路)-前置课程JavaWeb,使用Servlet组件处理请求和响应

web开发最重要的之一不就是处理请求与响应吗,那么这节就来总结Servlet是如何处理的,在请求与响应这块基本都差不多,浅浅的过一下!

Request

request:获取请求数据

浏览器会发送HTTP请求到后台服务器[Tomcat]

HTTP的请求中会包含很多请求数据[请求行+请求头+请求体]

后台服务器[Tomcat]会对HTTP请求中的数据进行解析并把解析结果存入到一个对象中

所存入的对象即为request对象,所以我们可以从request对象中获取请求的相关参数

获取到数据后就可以继续后续的业务,比如获取用户名和密码就可以实现登录操作的相关业务!

Request 继承体系

所以ServletRequest和HttpServletRequest是继承关系,并且两个都是接口,接口是无法创建。 对象,这个时候就引发了下面这个问题:

这个时候,我们就需要用到Request继承体系中的RequestFacade :

该类实现了HttpServletRequest接口,也间接实现了ServletRequest接口。

Servlet类中的service方法、doGet方法或者是doPost方法最终都是由Web服务器[Tomcat]来调用的,所以Tomcat提供了方法参数接口的具体实现类,并完成了对象的创建。

要想了解RequestFacade中都提供了哪些方法,我们可以直接查看JavaEE的API文档中关于ServletRequest和HttpServletRequest的接口文档,因为RequestFacade实现了其接口就需要重写接口中的方法。

所以,你可以打印这个参数resquest,可以看到这个对象是由RequestFacade创建的!

Request 获取请求参数

1.请求行包含三块内容,分别是请求方式、请求资源路径、HTTP协议及版本

对于这三部分内容,request对象都提供了对应的API方法来获取!

2.对于请求头的数据,格式为key: value如下:

3.获取请求体数据 浏览器在发送GET请求的时候是没有请求体的,所以需要把请求方式变更为POST! 对于请求体中的数据,Request对象提供了如下两种方式来获取其中的数据,分别是: 获取字节输入流,如果前端发送的是字节数据,比如传递的是文件数据,则使用该方法:

ServletInputStream getInputStream()

获取字符输入流,如果前端发送的是纯文本数据,则使用该方法:

BufferedReader getReader()

以上java代码如下:

@WebServlet("/req1")
public class RequestDemo1 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // String getMethod():获取请求方式: GET
        String method = req.getMethod();
        System.out.println(method);//GET
        // String getContextPath():获取虚拟目录(项目访问路径):/request-demo
        String contextPath = req.getContextPath();
        System.out.println(contextPath);
        // StringBuffer getRequestURL(): 获取URL(统一资源定位符):http://localhost:8080/request-demo/req1
        StringBuffer url = req.getRequestURL();
        System.out.println(url.toString());
        // String getRequestURI():获取URI(统一资源标识符): /request-demo/req1
        String uri = req.getRequestURI();
        System.out.println(uri);
        // String getQueryString():获取请求参数(GET方式): username=zhangsan
        String queryString = req.getQueryString();
        System.out.println(queryString);


        //------------
        // 获取请求头:user-agent: 浏览器的版本信息
        String agent = req.getHeader("user-agent");
        System.out.println(agent);


    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //获取post 请求体:请求参数

        //1. 获取字符输入流
        BufferedReader br = req.getReader();
        //2. 读取数据
        String line = br.readLine();
        System.out.println(line);
    }
}

对于post请求,可以写一个html表单测试!

获取请求参数的通用方式

对于请求参数的获取,常用的有以下两种:

GET:

String getQueryString()

POST:

BufferedReader getReader();

但通常情况写,有可能我们get或post处理的业务逻辑是相同的,但请求方式有不同,怎么办呢?

当然,也可以在doGet中调用doPost,在doPost中完成参数的获取和打印,另外需要注意的是,doGet和doPost方法都必须存在,不能删除任意一个。

GET请求和POST请求获取请求参数的方式不一样,在获取请求参数这块该如何实现呢?要想实现,我们就需要思考:

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

解决方法一:

这样不就好了,但是以后每个Servlet我们都要这样这样写,还是麻烦!

解决方案二: request对象已经将上述获取请求参数的方法进行了封装,并且request提供的方法实现的功能更强大,以后只需要调用request提供的方法即可,在request的方法中都实现了哪些操作呢?

如图,request将获取到的内容进行分割,然后将分割后的数据存到Map集合中!

基于此,request提供了以下api,直接上案例代码了哦:

package com.aniu;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.util.Map;

/**
 * request 通用方式获取请求参数
 */
@WebServlet("/demo3")
public class ServletDemo3 extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //GET请求逻辑
        System.out.println("get....");

        //1. 获取所有参数的Map集合
        Map<String, String[]> map = req.getParameterMap();
        for (String key : map.keySet()) {
            // 例如username:zhangsan lisi
            System.out.print(key+":");

            //获取值,遍历数组
            String[] values = map.get(key);
            for (String value : values) {
                System.out.print(value + " ");
            }

            System.out.println();  //换行
        }

        System.out.println("------------");

        //2. 根据key获取参数值,数组
        String[] hobbies = req.getParameterValues("hobby");
        for (String hobby : hobbies) {

            System.out.println(hobby);
        }

        //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 {
        //POST请求逻辑
        System.out.println("post...");

        this.doGet(req,resp);
    }
}

b.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/tomcat-demo/demo3" 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>

可以看到出现汉字乱码问题! 解决请看: 已解决Servlet中Request请求参数中文乱码的问题_为什么输出控制台servlet的request出行看不懂的乱码-优快云博客

Request 请求转发

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

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求

(2)资源A处理完请求后将请求发给资源B

(3)资源B处理完后将结果响应给浏览器

(4)请求从资源A到资源B的过程就叫请求转发

@WebServlet("/req5")
public class RequestDemo5 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                System.out.println("demo5...");
                //存储数据
                request.setAttribute("msg","hello");
                // 请求转发
                request.getRequestDispatcher("/req6").forward(request,response);
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                this.doGet(request, response);
        }
}
@WebServlet("/req6")
public class RequestDemo6 extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                System.out.println("demo6...");
                //获取数据
                Object msg = request.getAttribute("msg");
                System.out.println(msg);
        }
        @Override
        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                this.doGet(request, response);
        }
}

Response

response:设置响应数据

  • 业务处理完后,后台就需要给前端返回业务处理的结果即响应数据

  • 把响应数据封装到response对象中

  • 后台服务器[Tomcat]会解析response对象,按照[响应行+响应头+响应体]格式拼接结果

  • 浏览器最终解析结果,把内容展示在浏览器给用户浏览

Response继承体系

Response 设置响应数据功能

HTTP响应数据总共分为三部分内容,分别是响应行、响应头、响应体,对于这三部分内容的数据, respone对象都提供了方法来进行设置。

1.响应行

对于响应头,比较常用的就是设置响应状态码:

void setStatus(int sc);

2.响应头

设置响应头键值对

void setHeader(String name,String value);

3.响应体

对于响应体,是通过字符、字节输出流的方式往浏览器写, 获取字符输出流:

PrintWriter getWriter();

获取字节输出流

ServletOutputStream getOutputStream();

Respones 请求重定向

Response重定向(redirect):一种资源跳转方式。

(1)浏览器发送请求给服务器,服务器中对应的资源A接收到请求

(2)资源A现在无法处理该请求,就会给浏览器响应一个302的状态码+location的一个访问资源B的

路径

(3)浏览器接收到响应状态码为302就会重新发送请求到location对应的访问地址去访问资源B

(4)资源B接收到请求后进行处理并最终给浏览器响应结果,这整个过程就叫重定向

重定向方法一:

resp.setStatus(302);
resp.setHeader("location","资源访问路径");

重定向方法二:

//重定向
resposne.sendRedirect("资源访问路径");

请求转发和重定向的区别

Response 响应数据

响应字符数据:

//设置响应的数据格式及数据的编码
response.setContentType("text/html;charset=utf-8");
writer.write("你好");

响应字节数据:

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

ServletOutputStream outputStream = resp.getOutputStream();

2.通过字节输出流写数据:

outputStream.write(字节数据);
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        //1. 读取文件
        FileInputStream fis = new FileInputStream("d://a.jpg");
        //2. 获取response字节输出流
        ServletOutputStream os = response.getOutputStream();
        //3. 完成流的copy
        byte[] buff = new byte[1024];
        int len = 0;
        while ((len = fis.read(buff))!= -1){
        os.write(buff,0,len);
        }
        fis.close();
}

以上内容均来自博主:馆主阿牛

原文:

http://t.csdnimg.cn/6boY2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

明裕学长

打赏私我进交流群

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

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

打赏作者

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

抵扣说明:

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

余额充值