目录

这些方法的调用时机,就构成了“Servlet”的生命周期

注:
HttpServletResponse关键方法:
请求对象提供的都是getXXX方法,用来获取的,修改是setXXX方法
对于请求的信息,我们运用HttpServletRequest类的方法来进行请求信息的获取:
比如我们访问的url为http://127.0.0.1:8080/Test/requestServlet?key=10&a=100&b=200,很明显这是使用查询字符串构造的一个GET请求,通过HttpServletRequest类一系列对应的方法,我们可以获取到这个请求的方法类型,协议版本,URL,查询字符串,头部的一些信息等。其中查询字符串与头部信息的获取先要使用getParameterNames方法或者getHeaderNames方法获取所有的查询字符串或头部信息的所有key值,这个一个枚举对象,然后在根据getParameter或者getHeader方法通过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;
- import java.util.Enumeration;
-
- @WebServlet("/requestServlet")
- public class ShowRequestServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //访问链接:http://127.0.0.1:8080/hello_servlet/showreq?key=10&a=100&b=200
- StringBuilder stringBuilder = new StringBuilder();
- resp.setContentType("text/html; charset=utf-8");
- //1协议名称与版本
- stringBuilder.append("协议版本:");
- stringBuilder.append(req.getProtocol());
- stringBuilder.append("
"); - //2方法类型
- stringBuilder.append("方法:");
- stringBuilder.append(req.getMethod());
- stringBuilder.append("
"); - //3获取查URL路径
- stringBuilder.append("URL路径:");
- stringBuilder.append(req.getRequestURI());
- stringBuilder.append("
"); - //4URL(不包括查询字符串后面的部分)
- stringBuilder.append("URL(不包括查询字符串后面的部分):");
- stringBuilder.append(req.getRequestURL());
- stringBuilder.append("
"); -
- //5一级路径
- stringBuilder.append("一级路径:");
- stringBuilder.append(req.getContextPath());
- stringBuilder.append("
"); - //6查询字符串
- stringBuilder.append("查询字符串:");
- stringBuilder.append(req.getQueryString());
- stringBuilder.append("
"); - //7正文编码格式
- stringBuilder.append("正文编码格式:");
- stringBuilder.append(req.getCharacterEncoding());
- stringBuilder.append("
"); - //8mine
- stringBuilder.append("mine:");
- stringBuilder.append(req.getContentType());
- stringBuilder.append("
"); - //9正文长度
- stringBuilder.append("正文长度:");
- stringBuilder.append(req.getContentLength());
- stringBuilder.append("
"); - //10获得每一个查询字符串的键值:
- stringBuilder.append("
获得每一个查询字符串的键值:
"); - Enumeration query = req.getParameterNames();
- while(query.hasMoreElements()) {
- String key = (String)query.nextElement();
- stringBuilder.append(key);
- stringBuilder.append(":");
- stringBuilder.append(req.getParameter(key));
- stringBuilder.append("
"); - }
- //11获得头部的键值
- stringBuilder.append("
获得头部的键值:
"); - Enumeration header = req.getHeaderNames();
- while(header.hasMoreElements()) {
- String key = (String)header.nextElement();
- stringBuilder.append(key);
- stringBuilder.append(":");
- stringBuilder.append(req.getHeader(key));
- stringBuilder.append("
"); - }
- resp.getWriter().write(stringBuilder.toString());
- }
- }
其中查询字符串与头部信息的获取先要使用getParameterNames方法或者getHeaderNames方法获取所有的查询字符串或头部信息的所有key值,这个一个枚举对象,然后在根据getParameter或者getHeader方法通过key值遍历枚举对象获取value。
成功启动后(如何部署程序,前面说过了,感兴趣的小伙伴可以自行去查看一下0,去浏览器查看结果:

这里如果你出现乱码了,中文的编码有很多种,其中最常见就是utf8,如果没有显式的指定编码方式,则浏览器不能正确的识别编码,就会出现乱码,可以在代码中,通过resp.setContentType("text/html;charset=utf8");显式指定编码方法,一般情况就不会再有乱码了,但是,如果你还是乱码,可以去检查一下IDEA:


这样设置后,应该就不会有问题啦!
在同一webapp里面,关联路径不能够相同,不然Tomcat跑不起来,对于GET请求,可以使用URL的查询字符串进行构造,但是POST请求不行,需要使用form或者ajax。
构造Post请求(使用ajax构造):
在webapp目录下创建一个HTML文件,用来构造POST请求,首先我们先的引入jquery依赖(https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js导入依赖),然后调用ajax构造请求。
- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.min.js">script>
- <script>
- $.ajax({
- type: "post",
- url: "method",
- success: function (body){
- console.log(body);
- }
- })
- script>
注意上面的URL属性不能加/,加上表示的就是绝对路径了,当然你也可以使用./来表示相对路径,但是在Servlet注解关联路径必须得加上/。
- 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 doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- resp.setContentType("text/html; charset=utf8");
- resp.getWriter().write("POST请求");
- }
- }
打包部署,刷新页面:
我们知道post请求的请求信息在http格式中的body部分当中,而body中的请求内容的格式是有很多种的,比如最常见的有:
key=value&key=value&...
form表单创建x-www-form-urlencode格式请求:
- html>
- <html lang="ch">
- <head>
- <meta charset="UTF-8">
- <title>posttitle>
- head>
- <body>
- <form action="./postParameter" method="post" accept-charset="utf-8">
- <span>userIdspan>
- <input type="text" name="userId">
- <span>classIdspan>
- <input type="text" name="classId">
- <input type="submit" value="提交">
- form>
- body>
- html>
Servlet程序接收和处理请求:
对于x-www-form-urlencode格式请求可以直接使用HttpServletRequest中的getParameter方法依据key来获取value,然后再将获取到的数据返回,form表单构造的请求会自动跳转页面。
- 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 GetPostParameterServlet extends HttpServlet {
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //获取post请求body请求中的参数
- //设置请求与响应编码格式
- req.setCharacterEncoding("utf-8");
- resp.setContentType("text/html; charset=utf8");
- //比如useId = classId=
- String userId = req.getParameter("userId");
- String classId = req.getParameter("classId");
- //写会数据
- resp.getWriter().write("userId=" + userId + ", " + "classId=" + classId);
- }
- }
结果:

{ \{{
k e y : v a l u e , key:value,key:value,
k e y : v a l u e , key:value,key:value,
k e y : v a l u e , key:value,key:value,
. . . ......
} \}}
对于json格式,手动解析不容易,因为json里面的字段是可以嵌套的,但我们可以借助第三方库来解析处理json,比如Jackson,Jackson依赖导入过程如下【中央仓库】:
复制到pom.xml中:

处理json请求步骤:
第一步,在前端js代码中构造出格式为json格式的请求。
其中ajax构造post请求,使用contentType来说明请求的类型,data属性来设置body的内容。
- html>
- <html lang="cn">
- <head>
- <meta charset="UTF-8">
- <title>jsontitle>
- head>
- <body>
-
- <input type="text" id="userId">
- <input type="text" id="classId">
- <input type="button" id="submit" value="提交">
-
- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.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: "getJsonPost",
- contentType: "appliaction/json",
- data:JSON.stringify({
- userId: userIdInput.value,
- classId:classIdInput.value
- }),
- success: function(body){
- console.log(body);
- }
- })
- }
- script>
- body>
- html>
第二步,在java后端代码中使用Jackson处理。
- 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 User {
- public String userId;
- public String classId;
- }
- @WebServlet("/JsonPost")
- public class GetJsonPostServlet extends HttpServlet {
- //1.创建一个Jackson的核心对象
- private ObjectMapper objectMapper = new ObjectMapper();
- @Override
- protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //格式
- resp.setContentType("text/html; charset=utf8");
- //处理
- //2.读取body请求的内容,使用ObjectMapper对象的readValue方法来解析
- //就是将字符串转换成java的对象,readValue方法的第一个参数可以是路径字符串可以是输入流对象,引入可以是File对象
- //第二个参数,表示需要将请求的json格式数据转换成哪一个java对象
- User user = objectMapper.readValue(req.getInputStream(), User.class);
- System.out.println(user.userId);
- System.out.println(user.classId);
- resp.getWriter().write("userId=" + user.userId + " ,classId=" + user.classId);
- }
- }
结果;

readValue方法基本原理:
读取json格式的数据,并解析成键值对。
便利这些键值对,获得key,并与所需传入的对象中的属性(反射)相比,如果key与属性的名字相同,则把key对应的value赋值给这个属性,否则就跳过,所有的键值对便利完后,这个对象差不多就被构造的差不多了。
设置方法很简单,只需要调用httpServletResponse对象中的setStatus方法就可以了
- 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("/status")
- public class StatusServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //格式
- resp.setContentType("text/html; charset=utf8");
- //设置状态码
- int status = 200;
- resp.setStatus(status);
-
- resp.getWriter().write("hello,这是" + status + "状态码的响应内容!");
- }
- }
网页显示:
我把状态码修改为404,网页显示如下:
自动页面刷新只要在响应中设置一个header: Refresh就能实现页面的定时刷新了,对于响应header的设置,我们可以通过HttpServletResponse对象中的setHeader方法来设置Refresh属性和刷新频率。
- 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("/autorefresh")
- public class AutoRefreshServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //格式
- resp.setContentType("text/html; charset = utf8");
- //设置Refresh,第二个参数表示刷新频率,单位是秒
- resp.setHeader("Refresh", "1");
- //响应
- resp.getWriter().write("时间戳:" + System.currentTimeMillis());
- }
- }
页面显示:

第一步,设置状态码为302。
第二步,设置header:Location,调用setHeader方法时,第一个参数填Location,表示设置header字段为Location,第二个参数为重定向的目的地址,你要重定向到哪一个网址就传入哪一个地址的字符串。
- 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.setContentType("text/html; charset = utf8");
- //设置状态码
- resp.setStatus(302);
- //设置重定向字段与地址,如跳转到力扣官网
- resp.setHeader("Location", "https://leetcode.cn/");
- }
- }
效果:

当然,servlet提供了更为简便的重定向方法,就是使用HttpServletResponse类中的sendRedirect方法。
- @WebServlet("/redirect")
- public class RedirectServlet extends HttpServlet {
- @Override
- protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
- //格式
- resp.setContentType("text/html; charset = utf8");
- //设置状态码
- // resp.setStatus(302);
- // //设置重定向字段与地址,如跳转到力扣官网
- // resp.setHeader("Location", "https://leetcode.cn/");
- resp.sendRedirect("https://leetcode.cn/");
- }
- }
-
效果与上面是一样的。
本期结束啦!下期见~