Servlet API

HttpServlet

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

咱们自己写的代码就是继承这个类,然后重写其中的方法,来被Tomcat执行到 (多态)

核心方法

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

我们实际开发的时候主要重写 doXXX 方法, 很少会重写 init / destory / service .

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

image-20220531161716166

处理POST请求

image-20220531163849492

image-20220531163859765

image-20220531164045817

HttpServletRequest

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

核心方法

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

​ 在初步了解了这个方法之后,接下来通过实例加深理解

代码示例: 打印请求信息

@WebServlet("/showRequest")
public class ShowRequestServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //调用HttpServletRequest涉及到的几个关键API
        StringBuilder stringBuild = new StringBuilder();
        stringBuild.append(req.getProtocol());
        stringBuild.append("<br>");
        stringBuild.append(req.getMethod());
        stringBuild.append("<br>");
        stringBuild.append(req.getRequestURI());
        stringBuild.append("<br>");
        stringBuild.append(req.getContextPath());
        stringBuild.append("<br>");
        stringBuild.append(req.getQueryString());
        stringBuild.append("<br>");
        stringBuild.append("<h3>headers:</h3>");
        Enumeration<String> headerNames = req.getHeaderNames();
        while (headerNames.hasMoreElements()){
            String headerName = headerNames.nextElement();
            String headerValue = req.getHeader(headerName);
            stringBuild.append(headerName+":"+headerValue+"<br>");
        }
        resp.setContentType("text/html;charset=utf8");
        resp.getWriter().write(stringBuild.toString());
    }
}

image-20220531171217729

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

GET 请求中的参数一般都是通过 query string 传递给服务器的.

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

创建GetParameter类

image-20220531203330278

重新部署程序, 在浏览器中通过http://127.0.0.1:8080/hello02/getParameter访问, 可以看到

image-20220531203439417

当没有 query string的时候, getParameter 获取的值为 null

如果通过http://127.0.0.1:8080/hello02/getParameter?userId=123&classId=456访问, 可以看到

image-20220531203535949

此时说明服务器已经获取到客户端传递过来的参数.

getParameter 的返回值类型为 String. 必要的时候需要手动把 String 转成 int.

POST请求body格式

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

1 x-www-from-urlencoded

如果请求是这个方式,获取方式和get一样,也是使用getParameter

如何在前端创建这种格式?

  1. form表单
  2. postman

通过form表单:

创建类 PostParameterServlet

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

创建 test.html, 放到 webapp 目录中

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

在页面中的样式:

image-20220531205227778

点击提交按钮之后:

image-20220531205243370

通过fiddler抓包之后的结果如下

image-20220531204921994

3 json

上面的数据结构为userId=123&classId=456

json的数据结构为

{
	userId:123,
	classId:456
}

此时这种body为json的格式来说,如果手动解析,其实不是很容易 (JSON里面的字段可以嵌套) 可以使用第三方库,直接处理json处理数据

这里使用的是jackson

前端代码:

<body>
    <input type="text" id="userId">
    <input type="text" id="classId">
    <input type="button" value="提交" id="submit">
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <script>
        let userIdInput = document.querySelector('#userId');
        let classIdInput = document.querySelector('#classId');
        let button = document.querySelector('#submit');
        button.onclick = 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>

后端代码

class User{
   public int userId;
   public int classId;
}

@WebServlet("/postJson")
public class PostJsonServlet extends HelloServlet{
    ObjectMapper objectMapper = new ObjectMapper();
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        User user = objectMapper.readValue(req.getInputStream(), User.class);
        resp.getWriter().write("userId="+user.userId+" classId="+user.classId);
    }
}

image-20220531210824266

HttpServletResponse

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

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

核心方法

方法描述
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 中写入二进制格式数据.

代码示例: 设置状态码

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LUfDoNkz-1654141414193)(C:/Users/78581/AppData/Roaming/Typora/typora-user-images/image-20220601151411755.png)]

image-20220601151348873

此时通过fiddler抓包就看状态码为404,但是页面仍然显示了输出结果,原因是:服务器返回状态码,只是告诉服务器,当前的响应是什么状态,并不会影响浏览器照常的去显示body部分的内容

代码示例: 自动刷新

实现一个程序, 让浏览器每秒钟自动刷新一次. 并显示当前的时间戳.

创建AutoRefreshServlet类

@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());
    }
}

浏览器显示结果为

image-20220601152616178

通过fiddler抓包可以看到,

image-20220601152526314

通过setHeader方法,设置响应报头中的Refreash属性

代码示例: 重定向

实现一个程序, 返回一个重定向 HTTP 响应, 自动跳转到另外一个页面

创建 RedirectServlet 类

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

image-20220601153610491

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值