Servlet 常见的API

文章目录

    • 写在前面
    • Smart Tomcat 插件
    • Servlet 中常见的API
      • 1. HttpServlet
        • init 方法
        • destroy 方法
        • service 方法
        • Servlet 的生命周期
      • 使用 postman 构造请求
      • 使用 ajax 构造请求
      • 2. HttpServletRequest
      • 3. 前端给后端传参
        • 1). GET, query string
        • 2). POST, form
        • 3). json
      • 4. HttpServletResponse

写在前面

上一篇我们写了第一个 Servlet 程序, 是使用 Servlet 最朴素的方式. 我们也可以通过一些操作来简化这些步骤.

这就不得不提到插件了
IDEA 功能非常强大吗, 但也不是面面俱到的, IEDA 提供了一些 API , 可以让程序员开发插件对 IDEA 现有的功能进行扩展.


Smart Tomcat 插件

Servlet 常见的API_第1张图片
Servlet 常见的API_第2张图片
安装好重启 IDEA 即可

首次使用这个插件的时候, 我们需要配置一下.

  1. 新增一个运行配置
    Servlet 常见的API_第3张图片
  2. 新增配置

Servlet 常见的API_第4张图片

  1. 设置一下 Tomcat 的位置, 其他的保持默认即可

Servlet 常见的API_第5张图片

  1. 运行

Servlet 常见的API_第6张图片
Servlet 常见的API_第7张图片
运行之后, idea 就会自己调用 Tomcat 执行了.

在这里插入图片描述
Servlet 常见的API_第8张图片
Servlet 常见的API_第9张图片

这样的话我们是不是就方便了许多呢, 就算我们修改数据之后也只需在 idea 中重启一下服务器即可, 就不需要手动打包部署了.

smart tomcat 的工作原理
它不是把 war 包拷贝了(webapp 里没变), idea是通过另一种方式来启动 tomcat 的
tomcat 支持启动的时候显示指定一个特定的 webapp 目录, 相当于是让 tomcat 加载单个 webapp 运行.
Servlet 常见的API_第10张图片
idea 直接调用 tomcat , 让 tomcat 加载当前项目中的目录.
这个过程其实没有打 war 包的过程, 也没有拷贝, 也没有解压缩的过程.

Servlet 常见的API_第11张图片

Servlet 中常见的API

1. HttpServlet

我们写 Servlet 代码的时候, 首先第一步就是先创建类, 继承自 HttpServlet, 并重写其中的某些方法

方法名称 调用时机
init 在 HttpServlet 实例化之后被调用一次
destory 在 HttpServlet 实例不再使用的时候调用一次
service 收到 HTTP 请求的时候调用
doGet 收到 GET 请求的时候调用(由 service 方法调用)
doPost 收到 POST 请求的时候调用(由 service 方法调用)
doPut/doDelete/doOptions/… 收到其他请求的时候调用(由 service 方法调用)
init 方法

Servlet 常见的API_第12张图片
然后我们重启服务器, 重新访问

Servlet 常见的API_第13张图片
我们多刷新几次

Servlet 常见的API_第14张图片

tomcat 收到了 /hello 这样路径的请求就会调用 hello_servlet_1 进行实例化(实例化只进行一次)
后续在收到 /hello 此时不必再进行实例化, 直接复用之前的 hello_servlet_1 即可

destroy 方法

Servlet 常见的API_第15张图片

然后关闭服务器

Servlet 常见的API_第16张图片
Servlet 常见的API_第17张图片

但是这里的 destroy 不一定被执行到

  1. 如果是通过 smart tomcat 的停止按钮, 这个操作本质上是通过 tomcat 的 8005 端口, 主动停止, 能够触发 destroy.
  2. 如果是直接杀进程, 此时可能来不及执行 destroy 就关闭了.

因此不太推荐使用 destroy, 不靠谱

service 方法
Servlet 的生命周期
  1. 开始的时候, 执行 init
  2. 每次收到请求, 执行 service
  3. 销毁之前, 执行 destroy

Servlet 常见的API_第18张图片


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");
    }
}

根据不同的请求, 返回不同的响应

使用 postman 构造请求

Servlet 常见的API_第19张图片

Servlet 常见的API_第20张图片
Servlet 常见的API_第21张图片


使用 ajax 构造请求

首先创建一个 html 文件, 一定注意文件位置在 webapp 目录下
Servlet 常见的API_第22张图片

引入 jQuery cdn 链接, 编写代码

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js">script>
    <script>
        $.ajax({
            type:'get',
            // 相对路径
            // url:'method',
            // 绝对路径
            url:'/test2/mothod',
            success: function(body, status) {
                console.log(body);
            }
        })
    script>
body>
html>

这里的 url 是个相对路径, 相对路径的基准目录就是该 html 所在的路径

然后重新启动服务器, 重新访问
在这里插入图片描述

改这里的 type 类型就能构造出不同的请求
Servlet 常见的API_第23张图片

2. HttpServletRequest

核心方法

方法 描述
String getProtocol() 返回请求协议的名称和版本
String getMethod() 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT
String getRequestURI() 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。
String getContextPath() 返回指示请求上下文的请求 URI 部分。
String getQueryString() 返回包含在路径后的请求 URL 中的查询字符串。Enumeration
getParameterNames() 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。
String getParameter(Stringname) 以字符串形式返回请求参数的值,或者如果参数不存在则返回null。
String[] getParameterValues(Stringname) 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null。
Enumeration getHeaderNames() 返回一个枚举,包含在该请求中包含的所有的头名。
String getHeader(Stringname) 以字符串形式返回指定的请求头的值。
String getCharacterEncoding() 返回请求主体中使用的字符编码的名称。
String getContentType() 返回请求主体的 MIME 类型,如果不知道类型则返回 null。
int getContentLength() 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。
InputStream getInputStream() 用于读取请求的 body 内容. 返回一个 InputStream 对象.

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 ShowRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 这里设置 content-type
        resp.setContentType("text/html");

        // 搞个StringBuild , 把这些的 api 的结果拼起来, 统一写回到响应中
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(req.getProtocol());
        stringBuilder.append("
"
); stringBuilder.append(req.getMethod()); stringBuilder.append("
"
); stringBuilder.append(req.getRequestURI()); stringBuilder.append("
"
); stringBuilder.append(req.getContextPath()); stringBuilder.append("
"
); stringBuilder.append(req.getQueryString()); stringBuilder.append("
"
); stringBuilder.append("
"
); stringBuilder.append("
"
); stringBuilder.append("
"
); stringBuilder.append("
"
); // 获取 header 中的键值对 Enumeration<String> headerNames = req.getHeaderNames(); while (headerNames.hasMoreElements()) { String headerName = headerNames.nextElement(); stringBuilder.append(headerName + ":" + req.getHeader(headerName)); stringBuilder.append("
"
); } resp.getWriter().write(stringBuilder.toString()); } }

Servlet 常见的API_第24张图片


3. 前端给后端传参

1). GET, query string

在前端给后端传练个数字, 一个是同学的 studentiId, 一个是 classId

?studentIt=10&classId=20

下面编写代码来处理这个请求

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 + " class = " + classId);
    }
}

在这里插入图片描述
Servlet 常见的API_第25张图片

2). POST, form

对于前端是 form 表单这样格式的数据, 后端还是使用 getParameter 来获取.

form 表单 这种格式也是键值对, 和 query string 的格式一样
只是这部分内容存在 body 中

下面我们编写代码

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
head>
<body>
    <form action="postParameter" method="post">
        <input type="text" name="studentId">
        <input type="text" name="classId">
        <input type="submit" value="提交">
    form>
    
body>
html>

在这里插入图片描述
输入内容提交就能构造出一个 POST 请求, body 就是form 表单格式.
Servlet 常见的API_第26张图片

我们也可以抓包看看

Servlet 常见的API_第27张图片
Servlet 常见的API_第28张图片

下面我们编写后端的代码

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 + " class " + classId);

    }
}

在这里插入图片描述
Servlet 常见的API_第29张图片

使用 getParameter 方法, 既可以获取到 query string 中的键值对, 也可以获取到 form 表单构造的 body 中的键值对.

3). json

json 也是一种非常主流的数据格式, 也是键值对结构.
我们可以把 body 部分 按照这个格式来组织
前端可以使用 ajax 的方式来构造出这个内容. 还可以用 postman 直接构造

Servlet 常见的API_第30张图片

编写代码

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.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;

/**
 * @author chenhongfei
 * @version 1.0
 * @describe
 * @date 2023/11/14
 */
@WebServlet("/postParameter2")
public class PostParameter2Servlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        // 通过这个方法来处理 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);
    }
}

Servlet 常见的API_第31张图片
服务器这边我们也能看到

Servlet 常见的API_第32张图片

图解:
Servlet 常见的API_第33张图片

这个代码的执行流程, 和上个通过 form 表单传参, 流程是类似的. 只不过是传输的数据类型不同罢了.

form 表单是形如 classId=20&studentId=10

json 的格式形如:
{
classId:20,
studentId:10
}


本质上来说, 这三种方式都是等价的.

当前通过 json 传递数据, 但是服务器这边只是把整个 body 读出来, 还没有按照键值对的方式来处理(不能根据 key 获取 value)
form 表单是可以根据 key 获取 value (getParameter 就支持了).

这里我们推荐使用第三方库, Jackson

通过 Meven 引入第三方库
meven 库

Servlet 常见的API_第34张图片
Servlet 常见的API_第35张图片

把代码复制到 pom.xml

Servlet 常见的API_第36张图片

编写代码

          Student student = objectMapper.readValue(req.getInputStream(),Student.class);

  1. 这个代码会从 body 中取出 json 格式的字符串
    {
    classId: 20,
    studentId 10
    }
  2. 根据第二个参数类对象, 创建 Student 对象
  3. 解析上述 json 的字符串, 处理成 map 键值对结构
  4. 遍历所有键值对, 看键的名字和 Student 实例的哪个属性名字匹配, 就把对应的属>性 value 设置到该属性中
  5. 返回该 Student 实例

4. HttpServletResponse

Servlet 中的 doXXX 方法的目的就是根据请求计算得到相应, 然后把响应的数据设置到HttpServletResponse 对象中.
然后 Tomcat 就会把这个 HttpServletResponse 对象按照 HTTP 协议的格式, 转成一个字符串, 并通过Socket 写回给浏览器

核心方法

方法 描述
void setStatus(int sc) 为该响应设置状态码。
void setHeader(String name,String value) 设置一个带有给定的名称和值的 header. 如果 name 已经存在,则覆盖旧的值.
void addHeader(Stringname, String value) 添加一个带有给定的名称和值的 header. 如果 name 已经存在,不覆盖旧的值, 并列添加新的键值对
void setContentType(Stringtype) 设置被发送到客户端的响应的内容类型。
void setCharacterEncoding(String charset) 设置被发送到客户端的响应的字符编码(MIME 字符集)例如,UTF-8。
void sendRedirect(String location) 使用指定的重定向位置 URL 发送临时重定向响应到客户端。
PrintWriter getWriter() 用于往 body 中写入文本格式数据.
OutputStream getOutputStream() 用于往 body 中写入二进制格式数据.

设置字符编码

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;charset=utf8");
        // resp.setCharacterEncoding("utf-8");
        resp.getWriter().write("学生 = " + studentId + " 班级 = " + classId);
    }
}

在这里插入图片描述

Servlet 常见的API_第37张图片

重定向

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.sogou.com");
    }
}

在这里插入图片描述
点击就跳转到了搜狗了

Servlet 常见的API_第38张图片

单独设置也可以

 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //resp.sendRedirect("https://www.sogou.com");
        resp.setStatus(302);
        resp.setHeader("Location","https://www.sogou.com");
    }

你可能感兴趣的:(JavaEE,servlet)