⭐相关阅读推荐⭐
WebAPI—DOM (HTTL、CSS、Java Script应用及案例)
🌙 前端项目—待办事项(HTML+CSS+JavaScript实现)🌙
Servlet : Servlet部署教程(基于Tomcat)
Tomcat :Tomcat使用教程
前端网络:Fiddler使用教程(HTTP抓包 前端debug)
本章目录
♦ GET, query string => getParameter
x-www-form-urlencoded => getParameter
♦ 自动刷新页面(setHeader("Refresh","xxs"))
Servlet 实现上传文件(MultipartConfig)
※ 服务器响应流程
读取请求并解析(Tomcat 完成)
根据请求计算响应(用户代码,doXXX)
把响应返回给客户端(Tomcat 完成)
- HttpServlet
- HttpServletRequest
- HttpServletResponse
※
Servlet
的生命周期生命周期就是
Servlet
对象从诞生到消亡的过程:
Servlet
对象是由Tomcat
来进行实例化的,并且在实例化完毕之后调用init
方法
Tomcat
收到的每个请求,都通过对应的Servlet
的service
方法来进行处理(这里面会调用到 doXXX 方法)在服务器结束之前,会调用
destroy
方法来回收资源
HttpServlet(doXXX)
写一个 Servlet 程序,主要就是需要继承 HttpServlet 并且重写其中的doXXX方法
- 发的是GET请求,就重写doGet;发的是POST请求,就重写doPost
HttpServletRequest(getXXX)
对标 HTTP 请求报文格式,提供的方法(getXXX)都是和 HTTP 协议格式来匹配的。
ShowRequestServlet.java 文件
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 {
resp.setContentType("text/html;charset=utf-8");
// 此处返回一个 HTML, 在 HTML 里面显示刚才看到的这些 API 的接口
// 把这些 API 的返回结果往这个 StringBuilder 里面来拼
StringBuilder html = new StringBuilder();
html.append(req.getProtocol()); // HTTP版本号
html.append("<br>");
html.append(req.getMethod()); // 方法
html.append("<br>");
html.append(req.getRequestURI()); // 请求路径
html.append("<br>");
html.append(req.getContextPath()); // 上下文路径
html.append("<br>");
html.append(req.getQueryString()); // QueryString
html.append("<br>");
html.append("<br>");
html.append("<br>");
html.append("<br>");
// 获取到请求的 header 头
Enumeration<String> headers = req.getHeaderNames();
// 请求中的 header 是一组键值对结构,循环相当于拿到键值对中所有的 key
while (headers.hasMoreElements()) {
String headerName = headers.nextElement();
html.append(headerName);
html.append(":");
html.append((req.getHeader(headerName))); // 根据 key 来获取 value
html.append("<br>");
}
resp.getWriter().write(html.toString());
}
}
GET, query string => getParameter
getParameter(按照键值对,能够获取到指定的 value)
GetParameterServlet.java 文件
@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 约定请求是一个:getParameter?username=123&password=456
// 通过 getParameter 方法拿到用户名和密码的值
resp.setContentType("text/html;charset=utf-8");
String username = req.getParameter("username");
String password = req.getParameter("password");
resp.getWriter().write("username=" + username + "<br>" + "password=" + password);
}
}
POST (body)
body的数据格式:
- 如果 body 里的内容格式,是按照x-www-form-urlencoded 也是使用 getParameter 来处理(和QueryString一样)
- 如果 body 里的内容格式,是按照 form-data 此时有单独方式处理
- 如果 body 里的内容格式,是 json 此时需要借助第三方库来处理
x-www-form-urlencoded => getParameter
postParameterServlet.java 文件
@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");
// 此处是要获取 body 的数据,由于 GET 一般没有 body, 就使用 POST 方法来演示
String username = req.getParameter("username");
String password = req.getParameter("password");
resp.getWriter().write("username=" + username + "<br>" + "password=" + password);
}
}
form 表单绑定实现(webapp -> login.html)
<form action="postParameter" method="post">
<input type="text" name="username">
<input type="text" name="password">
<input type="submit" value="提交">
</form>
json => 先读出body,再通过Jackson库解析
(核心操作:objectMapper.readValue,注意第二个参数的用法(类对象))
- 引入第三方库 Jackson Databind 来解析 json 语句
- 在中央仓库WebAPI—DOM (HTTL、CSS、Java Script应用及案例),搜索 jackson 2.13.1 版本即可
- XML代码如下👇,放入 pom.xml 的依赖中,记得刷新 Maven :
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.1</version>
</dependency>
JsonParameterServlet.java 文件
class UserInfo {
public String username;
public String password;
}
@WebServlet("/jsonParameter")
public class JsonParameterServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 1. 先把整个请求的 body 都取出来
String body = readBody(req);
System.out.println(body);
// 2. 按照 json 的格式来进行解析,(对于 json 的解析,Java标准库没有内置的方法,Servlet也没有现成的方法,就需要使用第三方库来完成)
// 使用第三方库来完成,在 Java 中解析 json 的第三方库有很多,此处使用 Jackson 这个库
ObjectMapper objectMapper = new ObjectMapper();
UserInfo userInfo = objectMapper.readValue(body, UserInfo.class); //告诉 objectMapper 把json字符串转成哪个类的对象
resp.getWriter().write("username=" + userInfo.username + "<br>" + "password=" + userInfo.password);
}
private String readBody(HttpServletRequest req) throws IOException {
// 通过这个方法来读取请求中的整个 body
// 核心操作是 req.getInputStream 这个方法,这个方法会得到 InputStream 对象,然后进一步读取里面的内容
// InputStream 文件操作
// 1. 先拿到 body 的长度,单位是字节
int contentLength = req.getContentLength();
// 2. 准备一个字节数组,来存放 body 内容
byte[] buffer = new byte[contentLength];
// 3. 获取到 inputStream 对象
InputStream inputStream = req.getInputStream();
// 4. 读取数据,就是从 inputStream 对象中,读取到数据,放到 buffer 这个字节数组中
inputStream.read(buffer);
// 5. 得到的结果构造成一个 String
return new String(buffer, "utf-8");
}
}
在 Postman 中构造 POST json语句:
{
"username":"123",
"password":"1561561"
}
HttpServletResponse(setXXX)
HttpServletResponse对象和 HTTP 的响应报文格式密切相关
因此其提供的方法都是 setXXX 系列。
构造状态码(setStatus)
StatusServlet.java 文件
// 通过这个代码,来构造出不同的响应状态码
@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");
int status = 200;
resp.setStatus(status);
resp.getWriter().write("status=" + status);
}
}
自动刷新页面(setHeader("Refresh","xxs"))
在响应报头里设置一个字段,用 setHeader 实现刷新自动页面
AutoRefreshServlet.java 文件
@WebServlet("/autoRefresh")
public class AutoRefreshServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 给响应设置一个 Refresh 的 header,每隔 1s 刷新一次
resp.setHeader("Refresh","1");
resp.getWriter().write("timestamp=" + System.currentTimeMillis());
}
}
重定向(sendRedirect)
RedirectServlet.java 文件
@WebServlet("/redirect")
public class RedirectServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 构造一个 302 这样的响应,重定向到百度主页
// resp.setStatus(302);
// resp.setHeader("Location","https://www.baidu.com/");
// 也可以直接使用 sendRedirect 完成
resp.sendRedirect("https://www.baidu.com/");
}
}
Servlet 实现上传文件(MultipartConfig)
upload.html 文件
<!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>上传文件</title>
</head>
<body>
<form action="upload" method="post" enctype="multipart/form-data">
<input type="file" name="MyFile">
<input type="submit" name="上传">
</form>
</body>
</html>
UploadServlet.java 文件
@MultipartConfig
@WebServlet("/upload")
public class UploadServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 通过 req.getPart 获取到前端传来的文件
Part part = req.getPart("MyFile");
System.out.println(part.getSubmittedFileName());
System.out.println(part.getSize());
System.out.println(part.getContentType());
// 此处假设上传的是一个图片
part.write("C:/Users/Zincy/Pictures/myfile.jpg");
resp.getWriter().write("upload ok");
}
}