Servlet(二):Servlet的运行原理HttpServlet、HttpServletRequest、HttpServletResponse类详解

Servlet API详解

Servlet API中包含了很多的内容,但我们主要用到的是以下三个类,HttpServlet,HttpServletRequest,HttpServletResponse

HttpServlet类

在写Servlet代码的时候,第一步是创建一个类,继承HttpServlet,并重写其中的方法

【核心方法】
在这里插入图片描述
【补充】:

  • 我们实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service
  • destory这个方法不一定能执行到,如果Tomcat是通过8005管理端口来进行关闭,会执行destory,如果直接杀死Tomcat进程,则不会调用,且大部分情况是直接杀死Tomcat进程
  • Servlet的生命周期,上述方法的调用时机,就是Servlet的生命周期(描述了一个Servlet实例从生到死的过程) 最先执行init方法,且只执行一次,然后执行service方法(可能执行多次),最后执行destory方法
  • HttpServlet的实例只在程序启动时创建一次,而不是每次收到HTTP请求都重新创建实例

【处理GET请求】

  1. 在浏览器地址栏中填写url,默认就是通过GET方法发送请求
    在这里插入图片描述
  2. 处理GET请求的Servlet代码
    在这里插入图片描述
  3. 响应结果
    在这里插入图片描述

【处理POST请求】

通过ajax的方式构造一个POST请求,因此我们需要创建一个HTML,在HTML中创建出对应的webapp代码,HTML文件必须要放在webapp目录下
在这里插入图片描述

  1. 访问test.html,同时发送POST请求
    在这里插入图片描述

  2. 处理POST请求的代码
    在这里插入图片描述

  3. 响应结果,在success中是将返回的结果打印到控制台上的
    在这里插入图片描述

【注意】

  • 直接通过浏览器输入url得到的响应的内容就是直接被浏览器渲染到界面上的,但ajax不是,拿到的响应数据,是由回调的方法来处理的,可以显示到界面上,也可以不显示
  • ajax中url参数的写法,上面是相对路径的写法,test.html处在/servlet1/test.html中,要访问的路径是/servlet1/hello,因此url可直接写成hello,但绝对不能写成/hello,加了/就表示当前路径是绝对路径
  • 绝对路径的写法 : /servlet1/hello
  • 在WebServlet这个注解中的路径,一定要加/,如果不加/,Tomcat就会认为是无效的路径,从而不能正确启动/加载
    在这里插入图片描述

除了使用ajax构造请求,还可以使用第三方工具Postman构造请求,这种方式使用起来更方便简单

HttpServletRequest类

Http请求中包含了很多信息,例如请求方法,url,版本号,各种header,body,因此HttpServletRequest类中就提供了一组方法,让我们能够获取到Http请求中的这些信息

【核心方法】
在这里插入图片描述
上述的方法都是"读方法",而不是"写方法",因为对于服务器来说,请求对象是服务器收到的内容,不应该修改
【使用示例1】:打印请求的信息

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.Enumeration;


@WebServlet("/showRequest")
public class ShowRequest extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html; charset=utf-8");
        StringBuilder respBody = new StringBuilder();
        respBody.append(req.getProtocol());
        respBody.append("<br>");
        respBody.append(req.getMethod());
        respBody.append("<br>");
        respBody.append(req.getRequestURI());
        respBody.append("<br>");
        respBody.append(req.getContextPath());
        respBody.append("<br>");
        respBody.append(req.getQueryString());
        respBody.append("<br>");
        respBody.append("<h3>headers:</h3>");
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            respBody.append(headerName + " ");
            respBody.append(req.getHeader(headerName));
            respBody.append("<br>");
        }
        resp.getWriter().write(respBody.toString());
    }
}

在这里插入图片描述
【使用示例2】:获取GET请求中的参数
GET请求中的参数一般是通过query string传递给服务器的

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;

@WebServlet("/studentInfo")
public class StudentInfoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //假设客户端发来的请求格式形如/studentInfo?studentId=100&classId=8
        //可以通过getParameter方法拿到这两个id的值
        String queryString=req.getQueryString(); //拿到整个querystring
         String classId=req.getParameter("classId");
         String studentId=req.getParameter("studentId");
         resp.getWriter().write("classId:"+classId+" "+"studentId:"+studentId);
        //resp.getWriter().write(queryString);
    }
}

在这里插入图片描述

getParameter 的效果是拿到 query string中的键值对,根据key获取value
当没有 query string的时候, getParameter 获取的值为 null

【使用示例3】:获取POST请求中的参数
POST请求一般是通过body传递给服务器,body中的格式有很多种,如果采用form表单的形式,仍然可以通过getParameter获取参数的值

  • 通过Postman构造一个POST请求,并通过form表单的形式传参数
    在这里插入图片描述
@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf8");
        //获取body中的参数
        //约定body使用application/x-www-form-urlencoded的形式传参,也就是form表单的形式
        //形如classId=100&studentId=99,这个格式和query string相同,只是数据在body中
        String classId=req.getParameter("classId");
        String studentId=req.getParameter("studentId");
        resp.getWriter().write("classId:"+classId+" "+"studentId:"+studentId);
    }
  • 在body中通过json的形式传参
    在这里插入图片描述
    在这里插入图片描述

在服务器端不能通过getParameter的方式直接获取json形式的参数了,因为json格式解析起来,并不是特别容易,json支持一些更复杂的数据结构,也可以进行嵌套,例如某个key的value又是一个json
因此,可以使用处理json的第三方库,我们下面使用的是Jackson,在使用之前需要在项目中引入Jackson
在这里插入图片描述
【关于Jackson的使用】

  • 我们主要使用的是Jackson提供的一个类ObjectMapper
  • ObjectMapper中提供两个了两个主要的方法
  • readValue,将json字符串转换成Java对象,该方法的第一个参数是String或InputStream,第二个参数是转换的结果对应的类对象(因此需要先有一个类)
    在这里插入图片描述
  • writeValue方法,将Java对象转成json字符串
  • 通过Postman构造POST请求,并通过json格式传递参数
    在这里插入图片描述
  • 后端使用Jackson处理json格式的字符串
    在这里插入图片描述

HttpServletResponse类

【核心方法】
在这里插入图片描述

响应对象是服务器要返回给浏览器的内容, 这里的重要信息都是程序猿设置的. 因此上面的方法都是 “写” 方法.

【代码示例1】:设置状态码

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;

@WebServlet("/status")
public class StatusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置状态码
        resp.setStatus(200);
        
    }
}

在这里插入图片描述
在响应中设置状态码200,得到的抓包结果

在这里插入图片描述

在响应中设置状态码404,得到的浏览器页面和抓包结果

在这里插入图片描述
在这里插入图片描述

【代码示例2】:自动刷新,在响应的header中设置Refresh属性,每刷新一次都会给服务器发送一个新的请求

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;

@WebServlet("/refresh")
public class RefreshServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Refresh","1"); //value表示每隔几秒刷新一次
        resp.getWriter().write(System.currentTimeMillis()+"");//返回当前的时间戳
    }
}

页面显示效果和抓包结果

在这里插入图片描述

在这里插入图片描述

【代码示例3】:重定向,服务器返回一个重定向报文,让浏览器自动跳转到新的页面

具体做法:

  1. 设置状态码3xx(典型是302)
  2. 在响应的header中设置Location,表示要跳转的页面
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;

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(302);
        resp.setHeader("Location","https://www.sogou.com");
       //resp.sendRedirect("https://www.sogou.com");和上面两行代码的写法等价
    }
}

页面效果和抓包结果

在这里插入图片描述

敲下回车之后,跳转到搜狗主页

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值