技术层面上快速突破Servlet,带你快速上手HttpServlet,HttpServletRequest,HttpServletResponse

本文深入介绍了ServletAPI的使用,重点讲解了HttpServlet、HttpServletRequest和HttpServletResponse的核心方法及生命周期。通过实例展示了如何处理GET和POST请求,以及如何通过HttpServletRequest获取HTTP请求信息,包括请求方法、请求路径、查询字符串等。同时,文章还详细解释了如何使用HttpServletResponse设置响应状态码、添加响应报头和实现页面重定向。最后,讨论了HttpServletRequest处理GET和POST请求参数的方法,包括解析application/x-www-form-urlencoded和application/json格式的正文参数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Servlet API

Servlet中有很多的类,其中HttpServletHttpServletRequestHttpServletResponse对于一开始使用Servlet是最关键的三个类。

HttpServlet

首先一个类需要继承HttpServlet类,然后重写其中的方法,这其实就是一种将我们自定义的代码逻辑插入到Tomcat框架的实现方式。

核心方法

  • init:在HttpServlet对象被创建的时候被调用
  • destroy:HttpServlet对象不再被使用的时候被调用
  • service:收到HTTP请求的时候调用
  • doGet/doPost/doPut/doDelete...:收到对应的请求时被调用

Servlet生命周期(创建出对象之后会自动调用哪些方法)也可以从上面的核心方法中看出来:Servlet对象被创建出来之后会调用init(),Servlet对象每一次收到请求都会调用service(),Servlet对象在被销毁之前会调用destroy()

注意:实际开发中的时候主要重写doxxx方法,很少会重写initdestroyservice方法

使用HttpServlet对象实现一个简单的Servlet项目:使用ajax模拟发送请求,服务器处理GET和POST请求

  • 前端代码
<!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>  
    <button onclick="sendGet()">发送 GET 请求</button>  
    <button onclick="sendPost()">发送 POST 请求</button>  
  
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>  
  
    <script>  
        // 使用ajax发送HTTP请求  
        const sendGet = () => {  
            $.ajax({  
                type: "GET",  
                // 注意:ajax的url有两种写法:  
                // 1.相对路径,和当前地址前面的部分是相同的。  
                // 例如当前地址是/test_servlet/index.html,那么就会跳转到/test_servlet/method  
                // 2.绝对路径,从web根目录开始  
                // 例如:直接写成url: "/test_servlet/method"  
                url: "method",  
                success: function(resp) {  
                    console.log(resp);  
                }  
            });  
        }  
        const sendPost = () => {  
            $.ajax({  
                type: "POST",  
                url: "method",  
                data: "post request body",  
                success: function(resp) {  
                    console.log(resp);  
                }  
            })  
        }  
    </script>  
</body>  
</html>

注意:ajax中路径的写法。如果一旦使用/开头,就一定要写成绝对路径。这个要和Servlet中的@WebServlet注释不同,在@WebServlet注解中一定要给相对路径的前面加上/,例如@WebServlet("/method")

  • Servlet代码
@WebServlet("/method")  
public class MethodServlet extends HttpServlet {  
    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        // 因为windows上的浏览器默认的编码格式是GBK,而Tomcat和IDEA中的编码格式是UTF-8,如果直接发送中文过去的话  
        // 就会看到乱码。因为UTF-8是通用编码格式,所以我们就不修改IDEA中的编码格式了,而是修改浏览么渲染的编码格式  
        // 通过在HTTP中的header调价Content-Type: charset=utf-8就可以修改浏览器的编码格式了  
        resp.setContentType("text/html; charset=utf-8;");  
        resp.getWriter().write("get 响应");  
    }  
  
    @Override  
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        resp.setContentType("text/plain; charset=utf-8;");  
        resp.getWriter().write("post 响应");  
    }  
}

注意:给浏览器设置编码格式。在HTTP请求的header中设置Content-Type: charset=utf-8

HttpServletRequest

HttpServletRequest就是Tomcat对HTTP请求的封装。Tomcat将字符串结构的HTTP请求转化成了一个一个键值对的结构化数据,即将HTTP请求字符串进行了“反序列化”操作,这样更方便对数据进行操作。

HTTP请求中包括:请求行(请求方法+URL(ContextPath+QueryString)+版本号)+ 请求头部 + 空行 + 请求正文

其中的每一个部分,HttpServletRequest对象都有对应的方法可以获取到。

核心方法

![[Pasted image 20220821155111.png]]

使用HttpServletRequest获取HTTP请求信息

  • Servelt代码
@WebServlet("/showrequest")  
public class ShowRequestServlet 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.getMethod() + "<br/>");  
        respBody.append("请求路径URI: " + req.getRequestURI() + "<br/>");  
        respBody.append("ContextPath: " + req.getContextPath() + "<br/>");  
        respBody.append("QueryString: " + req.getQueryString() + "<br/>");  
        respBody.append("版本号: " + req.getProtocol() + "<br/>");  
  
        respBody.append("<h3>HttpHeader</h3>");  
        Enumeration<String> headerNames = req.getHeaderNames();  
        while (headerNames.hasMoreElements()) {  
            String headerName = headerNames.nextElement();  
            respBody.append(headerName + ": " + req.getHeader(headerName) + "<br/>");  
        }  
  
        resp.getWriter().write(respBody.toString());  
    }  
}
  • 实验结果
    ![[Pasted image 20220821162134.png]]

案例:使用HttpServletRequest获得GET请求传递的参数信息

  • Servlet代码
@WebServlet("/getparameter")  
public class GetParameterServlet extends HttpServlet {  
    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        resp.setContentType("text/html; chatset=utf-8;");  
        // 获取url中querystring  
        String userId = req.getParameter("userId");  
        String userName = req.getParameter("userName");  
        // 对参数不存在需要判断querystring是否为null或者是否为""  
        // 因为不传递userId和userName这两个参数的话,那么对象就为null  
        // 如果传递的参数为userId=&userName=的话,那么对象就位""  
        if (userId == null || userId.equals("")) {  
            System.out.println("不存在userId");  
        }  
        resp.getWriter().write(String.format("userId: %s, userName: %s <br/>", userId, userName));  
    }  
}
  • 实验结果
    ![[Pasted image 20220821164347.png]]

案例:使用HttpServletRequest获得POST请求传递的参数信息

发起POST请求的时候,正文参数有三种格式:

  1. application/x-www-form-urlencoded格式,这种格式类似于直接使用url进行传递的参数。
  2. mutlipart/form-data,这种格式比较复杂,主要是用来提交文件的。(这种不详讲了)
  3. application/json,json类似于一个对象中有很多个key-value键值对。

解析application/x-www-form-urlencoded格式的正文参数

  • Servlet代码
@WebServlet("/postParameter")  
public class PostParameterServlet extends HttpServlet {  
    @Override  
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        resp.setContentType("text/html; charset=utf-8;");  
        // 直接使用getParamter就可以获取x-www-form-urlencoded格式的请求正文中的数据了  
        String userId = req.getParameter("userId");  
        String userName = req.getParameter("userName");  
        resp.getWriter().write(String.format("userId: %s, userName: %s <br/>", userId, userName));  
    }  
}
  • 前端发起post请求代码
<!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="/test_servlet/postParameter" method="POST">  
        userId: <input type="text" name="userId">  
        <br/>  
        userName: <input type="text" name="userName">  
        <br/>  
        <input type="submit" name="提交">  
    </form>  
</body>  
</html>
  • 实验结果

![[Pasted image 20220821171830.png]]

![[Pasted image 20220821171815.png]]

解析applicaion/jsno格式的正文参数

  • Servlet代码
class JsonData {  
    public int userId;  
    public String userName;  
}  
  
@WebServlet("/postParameterJson")  
public class PostParameterJsonServlet extends HttpServlet {  
    @Override  
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        // 将请求正文先读取出来  
        String body = readBody(req);  
        // 使用第三方库jackson(Spring中的内置的json解析库)对json格式的字符串进行解析  
        ObjectMapper objectMapper = new ObjectMapper();  
        JsonData jsonData = objectMapper.readValue(body, JsonData.class);  
        resp.getWriter().write(String.format("userId: %d, userName: %s <br>", jsonData.userId, jsonData.userName));  
    }  
  
    private String readBody(HttpServletRequest req) throws IOException {  
        // 使用HttpServletRequest中的inputStream流对象进行正文数据读取  
        InputStream inputStream = req.getInputStream();  
  
        int contentLength = req.getContentLength();  
        byte[] buffer = new byte[contentLength];  
        inputStream.read(buffer);  
        return new String(buffer, "utf-8");  
    }  
}

Jackson库基本原理就是先将json格式的字符串转换为键值对保存起来,然后根据类对象,通过反射机制获得类中有哪些属性,最后在前面保存的键值对结果中找类中属性对应的value。所以我们需要定义的JsonData这个类中属性和发送的json数据属性要一一对应,最后获得objectMapper.readValue()返回的对象就是解析完成的json数据。

  • 发送POST请求的前端代码
<!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>  
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js"></script>  
    <button onclick="sendJson()">发送 POST 请求</button>  
    <script>  
        const sendJson = () => {  
            let body = {  
                userId: 666,   
                userName: "zhy"  
            };  
  
            $.ajax({  
                url: "postParameterJson",  
                type: "POST",  
                contentType: "application/json",  
                data: JSON.stringify(body),  
                success: function(resp) {  
                    console.log(resp);  
                }  
            });  
        }  
    </script>  
</body>  
</html>

注意:使用ajax发送POST请求并带上json格式的数据的时候,需要将json数据使用JSON.stringify()转换为字符串进行发送。

小结HttpServletRequest

平时使用HttpServletRequest最常见的工作就是获得HTTP请求中的参数

  • 如果是GET请求,可以通过getParameter()获得url中的query string。
  • 如果是POST请求并且请求正文参数是application/x-www-form-urlencoded格式的,也是通过getParameter()获得正文中的参数
  • 如果是POST请求并且请求正文参数是application/json格式的,就需要先将请求正文数据读取出来,然后通过第三方库Jackson进行解析。

HttpServletResponse

核心方法

![[Pasted image 20220821200445.png]]

案例:使用HttpServletResponse对象设置响应状态码

  • Servlet代码
@WebServlet("/status")  
public class StatusServlet extends HttpServlet {  
    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        resp.setContentType("text/html; charset=utf-8");  
        // 用户通过query string传递一个status,然后服务器返回对应状态码的响应  
        String statusString = req.getParameter("status");  
        if (statusString == null || statusString.equals("")) {  
            resp.getWriter().write("status 参数不存在");  
            return ;  
        }  
        resp.setStatus(Integer.parseInt(statusString));  
        resp.getWriter().write("status: " + statusString);  
    }  
}
  • 实验结果
    ![[Pasted image 20220821203553.png]]

案例:使用HttpServletResponse对象在响应报头中添加键值对

  • Servlet代码
@WebServlet("/autoRefresh")  
public class AutoRefreshServlet extends HttpServlet {  
    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        resp.setContentType("text/html; charset=utf8");  
        // 在响应报头中添加一个键值对,将Refresh设置为1,那么浏览器就会每隔一秒进行一次刷新  
        resp.setHeader("Refresh", "1");  
        // 通过返回一个时间戳来看到浏览器每隔一秒都在进行刷新  
        long timeStamp = System.currentTimeMillis();  
        resp.getWriter().write("timeStamp: " + timeStamp);  
    }  
}
  • 实验结果
    ![[Pasted image 20220821204930.png]]

案例:使用HttpServletResponse对象设置页面重定向

  • Servlet代码
@WebServlet("/redirect")  
public class RedirectServlet extends HttpServlet {  
    @Override  
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {  
        // 设置重定向有两种方法:  
        // 1.设置响应报文的状态码,并添加Location字段在响应报头中  
//        resp.setStatus(302);  
//        resp.setHeader("Location", "https://www.baidu.com");  
                // 2.使用sendRedirect()进行重定向  
         resp.sendRedirect("https://www.baidu.com");  
    }  
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

hyzhang_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值