Servlet 的 API

HttpServlet

        init:当 tomcat 收到了 /hello 这样的路径是请求后就会调用 HelloServlet,于是就需要对 HelloServlet 进行实例化(只实例一次,后续再有请求也不实例了)。

        destory:如果是通过 smart tomcat 的停止按钮,这个操作本质上是通过 tomcat 的 8005 端口主动停止,能够触发 destory。但如果是直接杀进程,此时很可能来不及执行 destory(这种情况比较常见)。

        service:每次收到请求都会先执行 service,然后再根据请求的类型调用对应的 doxxx。

因此:Servlet 的生命周期就可以理解为:1. 一开始的时候,执行 init;2. 每次收到请求,执行 service;3. 销毁之前,执行 destory。

处理请求

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("/method")
public class MethodServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doGet");
        resp.getWriter().write("doGet");
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPost");
        resp.getWriter().write("doPost");
    }

    @Override
    protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doPut");
        resp.getWriter().write("doPut");
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("doDelete");
        resp.getWriter().write("doDelete");
    }
}

        这里默认是 get 请求,为了构造别的方法请求可以使用 postman 来构造,也可以通过 Ajax 写代码来进行构造

postman

Ajax

首先得在 webapp 目录下创建一个 .html 的文件

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!-- 使用这个页面来构造 Ajax 请求 -->
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script>
        $.ajax({
            type: 'post',
            //这是相对路径的写法
            //url: 'method',
            //这是绝对路径的写法
            url: '/hello_servlet/method',
            success: function (body, status) {
                console.log(body);
            }
        });
    </script>
</body>
</html>

HttpServletRequest

        当 Tomcat 通过 Socket API 读取 HTTP 请求(字符串), 并且按照 HTTP 协议的格式把字符串解析成 HttpServletRequest 对象.

:因为 query string 是键值对形式(form 表单构造的 body 也是),所以就可以通过 getParameter 放法来根据 key 获取到 value。

获取 GET 请求中的参数

        GET 请求中的参数一般都是通过 query string 传递给服务器的. 形如:/getParameter?studentId=10&classId=20

        此时浏览器通过 query string 给服务器传递了两个参数, studentId 和 classId, 值分别是 10 和 11,此时在服务器端就可以通过 getParameter 来获取到参数的值.

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("/getParameter")
public class GetParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 预期浏览器会发一个形如 /getParameter?studentId=10&classId=20 请求.
        // 借助 req 里的 getParameter 方法就能拿到 query string 中的键值对内容了.
        // getParameter 得到的是 String 类型的结果.
        String studentId = req.getParameter("studentId");
        String classId = req.getParameter("classId");
        resp.setContentType("text/html");
        resp.getWriter().write("studentId = " + studentId + " classId = " + classId);
    }
}

        getParameter 的返回值类型为 String. 必要的时候需要手动把 String 转成 int 。当没有 query string的时候, getParameter 获取的值为 null.

获取 POST 请求中的参数

        POST 请求的参数一般通过 body 传递给服务器. body 中的数据格式有很多种. 如果是采用 form 表单的形式, 仍然可以通过 getParameter 获取参数的值(直接可以根据 key 获取 value)。

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("/postParameter")
public class PostParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String studentId = req.getParameter("studentId");
        String classId = req.getParameter("classId");
        resp.setContentType("text/html");
        resp.getWriter().write("studentId = " + studentId + " classId = " + classId);
    }
}

创建 testPost.html, 放到 webapp 目录中:

<form action="postParameter" method="POST">
    <input type="text" name="userId">
    <input type="text" name="classId">
    <input type="submit" value="提交">
</form>

form 表单点击 提交 一定会发生页面跳转的

获取 POST 请求中的参数(2)

        如果 POST 请求中的 body 是按照 JSON 的格式来传递, 那么获取参数的代码就要发生调整。因为通过 json 传递数据,服务器这边默认是把整个 body 都读过来,即没有按照键值对的方式来处理,也就不能根据 key 获取 value。

        因此,要使用第三方库 “Jackson” 来解析 json 格式。在 maven 仓库里搜 Jackson,然后选一个版本点进去把 xml 片段粘贴到 pom.xml 的 <dependencies> 中即可。

import com.fasterxml.jackson.databind.ObjectMapper;

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;

class Student {
    // 把属性设为 public 的原因是能让 外面的Jackson 获取到这里有什么属性
    public int studentId;
    public int classId;
}

@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 这段注释的代码是没有时候第三方库 Jackson 的,得到的是没有被处理过的 json
        // 通过这个方法来处理 body 为 json 格式的数据.
        // 直接把 req 对象里 body 完整的读取出来.
        // getInputStream
        // 在流对象中读多少个字节? 取决于 Content-Length
//        int length = req.getContentLength();
//        byte[] buffer = new byte[length];
//
//        InputStream inputStream = req.getInputStream();
//        inputStream.read(buffer);
//
//        // 把这个字节数组构造成 String, 打印出来.
//        String body = new String(buffer, 0, length, "utf8");
//        System.out.println("body = " + body);
//        resp.getWriter().write(body);


        // 使用 jackson 涉及到的核心对象.
        ObjectMapper objectMapper = new ObjectMapper();
        // readValue 就是把一个 json 格式的字符串转成 Java 对象.
        // writeValue 把一个 java 对象转成 json 格式字符串
        Student student = objectMapper.readValue(req.getInputStream(), Student.class);
        System.out.println(student.studentId + ", " + student.classId);
        
    }
}

HttpServletResponse

        Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到

HttpServletResponse 对象中. 然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过 Socket 写回给浏览器.

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.sendRedirect("https://www.bilibili.com");  // 这是直接构造了重定向响应

        // 上面的一行代码也可以分成下面两行:先设置状态码,然后再设置需要跳转到哪里
        resp.setStatus(302);
        resp.setHeader("Location", "https://www.bilibili.com");
    }
}

  • 18
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值