Servlet API详解

在这里插入图片描述

请添加图片描述

⭐️前言⭐️

本文我们主要介绍Servlet里的关键API,也就是HttpServlet、HttpServletRequest、HttpServletResponse这三个类中一些方法的使用。

🍉博客主页: 🍁【如风暖阳】🍁
🍉精品Java专栏【JavaSE】【备战蓝桥】、【JavaEE初阶】【MySQL】【数据结构】
🍉欢迎点赞 👍 收藏留言评论 📝私信必回哟😁

🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉

🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言

🍉博客中涉及源码及博主日常练习代码均已上传码云(gitee)GitHub


请添加图片描述

请添加图片描述

🍅1.HttpServlet

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

1.1 核心方法

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

在实际开发中主要重写doXXX方法,很少会重写init/destory/service.

这些方法的调用时机,就称为“Servlet生命周期”(也就是描述了一个Servlet实例从生到死的过程)
在这里插入图片描述

注意:HttpServlet的实例只是在程序启动时创建一次,而不是每次收到HTTP请求都重新创建实例。

1.2 代码示例:处理GET请求

创建MethodServlet.java,创建doGet方法

@WebServlet("/method")
public class MethodServlet extends HelloServlet{
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("GET RESPONSE");
    }
}

我们知道,在浏览器中直接输入URL就可以构造一个GET请求,现在我们来测试服务器的处理:
在这里插入图片描述

1.3 代码示例:处理POST请求

在MethodServlet.java中,新增doPost方法

@Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write("POST 响应");
    }

完成了服务器端的代码,我们需要构造一个POST请求来进行测试,并不能通过直接输入URL的方式来构造POST请求;构造POST请求的方法有两种,一种是基于form表单,另一种是通过ajax来构造,下边我们主要来看看通过ajax的方式来如何构造post请求。(该流程的详情也可见文章【构造HTTP请求与HTTPS加密1.2】

首先我们需要先在webapp目录下创建一个HTML文件,用来构造POST请求。
在这里插入图片描述
然后我们需要引入jQuery依赖(搜索jQuery mdn进行复制,也可本地导入)
在这里插入图片描述
最后使用jQueryajax函数.
在这里插入图片描述
注意:ajax请求中的URL不能加/,但是Servlet类的注解必须加上/.

我们访问http://localhost:8080/maven_1102/testMethod.html,出现如下图结果:
在这里插入图片描述
也就是出现了乱码的情况,这是因为我们在编译器上,字体的默认编码方式为utf-8,而浏览器字体的默认编码方式为GBK,因为编码方式的不同,导致同一文件在不同地方的展示出现了乱码的情况;我们可以通过响应,显式的告诉浏览器通过utf8的方式进行编码,就可以避免乱码的情况了。
在这里插入图片描述
上述红框中代码的含义为,响应的返回类型为html格式,编码方式为utf8.

重新打包部署并测试:
在这里插入图片描述

🍅2.HttpServletRequest

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

2.1 核心方法

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

通过这些方法可以获取到一个请求中的各个方面的信息。

注意:请求对象是服务器收到的内容,不应该修改。因此上面的方法也都只是“读”方法,而不是“写”方法。

2.2 代码示例:打印请求信息

创建ShowRequestServlet类,调用一下在2.1中涉及到的几个关键API,并把得到的结果组织到一个html中,并作为响应的body.

@WebServlet("/showRequest")
public class ShowRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //把API执行的结果,放到stringBuilder中
        StringBuilder stringBuilder=new StringBuilder();
        stringBuilder.append("<h3>首行部分</h3>");
        stringBuilder.append(req.getProtocol());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getMethod());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getRequestURI());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getContextPath());
        stringBuilder.append("<br>");
        stringBuilder.append(req.getQueryString());
        stringBuilder.append("<br>");
        stringBuilder.append("<h3>header部分</h3>");
        Enumeration<String> headerNames=req.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName= headerNames.nextElement();
            String headerValue=req.getHeader(headerName);
            stringBuilder.append(headerName+":"+headerValue+"<br>");
        }
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write(stringBuilder.toString());
    }
}

在这里插入图片描述

2.3 代码示例:获取GET请求中的参数

最常用的其实是getParameter这个方法,能够获取到query string中的详细内容。创建一个GetParameterServlet类来获取Get请求中的参数。

@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String userId=req.getParameter("userId");
        String classId=req.getParameter("classId");
        resp.getWriter().write("userId="+userId+",classId="+classId);
    }
}

浏览器构造如下请求。
在这里插入图片描述

2.4 代码示例:获取POST请求中的参数

POST请求的body格式主要有以下三种:

1.x-www-form-urlencoded
2.form-data
3.json

最为常见的是第一种和第三种,我们可以通过form表单或者ajax的方式来构造出这样的POST请求。

1)基于form表单构造x-www-form-urlencoded这种格式的请求。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <form action="postParameter" method="post" accept-charset="utf-8">
        <span>userId</span>
        <input type="text" name="userId">
        <span>classId</span>
        <input type="text" name="classId">
        <input type="submit" value="提交">
    </form>
</body>
</html>

服务器获取参数的方式和GET方法一样,也是getParameter。

@WebServlet("/postParameter")
public class PostGetParameterServlet extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //设置请求与响应中的编码格式
        req.setCharacterEncoding("utf-8");
        resp.setContentType("text/html; charset=utf8");
        //获取post请求中的参数
        String userId=req.getParameter("userId");
        String classId=req.getParameter("classId");
        resp.getWriter().write("userId="+userId+",classId="+classId);
    }
}

测试效果演示:
请添加图片描述
2)基于ajax构造json这种格式的请求.

1.在浏览器的前端代码中,通过js构造出bodyjson格式的请求

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- 前端HTML部分内容 -->
    <input type="text" id="userId">
    <input type="text" id="classId">
    <input type="button" id="submit" value="提交">

    <!-- 导入jQuery -->
    <script src="https://code.jquery.com/jquery-3.6.1.min.js"></script>

    <script>
        let userIdInput=document.querySelector('#userId');
        let classIdInput=document.querySelector('#classId');
        let button=document.querySelector('#submit');
        button.onclik=function() {
            $.ajax({
                type:'post',
                url:'postJson',
                contentType:'application/json',
                data:JSON.stringify({
                    userId:userIdInput.value,
                    classId:classIdInput.value
                }),
                success:function(body) {
                    console.log(body);
                }
            })
        }
    </script>
</body>
</html>

在这里插入图片描述

2.因为json格式的数据,不便于手动解析,所以在Java后端代码中,通过Jackson来进行处理(在maven中央仓库引入Jackson依赖)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
后端代码:

class User {
    public int userId;
    public int classId;
}
@WebServlet("/postJson")
public class PostJsonServlet extends HttpServlet {
    //1.创建一个jackson的核心对象
    private ObjectMapper objectMapper=new ObjectMapper();

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //2.读取body中的请求,然后使用ObjectMapper来解析成需要的对象
        //readValue就是把JSON格式的字符串,转成Java的对象
        //第一个参数,表示对哪个字符串进行转换(这个参数可以是一个String,也可以是
        // 一个InputStream对象,还可以是一个File对象)
        //第二个参数,表示要把这个JSON格式的字符串,转换成哪个Java对象
        User user=objectMapper.readValue(req.getInputStream(),User.class);
        resp.getWriter().write("userId:"+user.userId+",classId:"+user.classId);
    }
}

readValue方法解析:
在这里插入图片描述
1.先把getInputStream对应的流对象里面的数据读取出来。
2.针对这个json字符串进行解析,从字符串转换成键值对
3.遍历键值对,依次获取到每一个Key,根据这个Key的名字,和类对象Uer里面的属性名字对比(利用反射获取到内部属性),如果匹配就进行赋值,不匹配就跳过
4.当把所有的键值对都遍历过后,此时User对象就被构造好了。

测试效果演示:
请添加图片描述

🍅3.HttpServletResponse

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

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

3.1 核心方法

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

注意:响应对象是服务器要返回给浏览器的内容,这里的重要信息都是程序猿设置的。因此上面的方法都是“写”方法
对于状态码/响应头的设置,要放到getWriter/getOutputStream之前,否则可能设置失效

3.2 代码示例:设置状态码

代码:

@WebServlet("/status")
public class StatusServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setStatus(404);
        resp.getWriter().write("hello");
    }
}

效果预览:
在这里插入图片描述
状态码虽然是404,但页面仍然能够显示出内容,就像b站的404页面一样
在这里插入图片描述

3.3 代码示例:自动刷新

代码:

@WebServlet("/autoRefresh")
public class AutoRefreshServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setHeader("Refresh","1");
        resp.getWriter().write("timeStamp:"+System.currentTimeMillis());
    }
}

效果预览:
请添加图片描述

3.4 代码示例:重定向

代码:

@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.sendRedirect("https://www.bilibili.com");
    }
}

效果预览:
请添加图片描述

下期预告:Servlet综合案例:表白墙


⭐️最后的话⭐️
总结不易,希望uu们不要吝啬你们的👍哟(^U^)ノ~YO!!如有问题,欢迎评论区批评指正😁

请添加图片描述

  • 23
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 17
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

如风暖阳

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值