⭐️前言⭐️
本文我们主要介绍Servlet里的关键API,也就是HttpServlet、HttpServletRequest、HttpServletResponse这三个类中一些方法的使用。
🍉博客主页: 🍁【如风暖阳】🍁
🍉精品Java专栏【JavaSE】、【备战蓝桥】、【JavaEE初阶】、【MySQL】、【数据结构】
🍉欢迎点赞 👍 收藏 ⭐留言评论 📝私信必回哟😁🍉本文由 【如风暖阳】 原创,首发于 CSDN🙉
🍉博主将持续更新学习记录收获,友友们有任何问题可以在评论区留言
我们在写Servlet代码的时候,首先第一步就是先创建类,继承自HttpServlet,并重写其中的某些方法。
方法名称 | 调用时机 |
---|---|
init | 在HttpServlet实例化后被调用一次 |
destory | 在HttpServlet实例不再使用的时候调用一次 |
service | 收到HTTP请求的时候调用 |
doGet | 收到GET请求的时候调用(由service方法调用) |
doPost | 收到POST请求的时候调用(由service方法调用) |
doPut/doDelete/doOptions/… | 收到其他请求的时候调用(由service方法调用) |
在实际开发中主要重写doXXX方法,很少会重写init/destory/service.
这些方法的调用时机,就称为“Servlet生命周期”(也就是描述了一个Servlet实例从生到死的过程)
注意:HttpServlet的实例只是在程序启动时创建一次,而不是每次收到HTTP请求都重新创建实例。
创建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请求,现在我们来测试服务器的处理:
在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进行复制,也可本地导入)
最后使用jQuery
的ajax
函数.
注意:ajax请求中的URL不能加/
,但是Servlet类的注解必须加上/
.
我们访问http://localhost:8080/maven_1102/testMethod.html
,出现如下图结果:
也就是出现了乱码的情况,这是因为我们在编译器上,字体的默认编码方式为utf-8
,而浏览器字体的默认编码方式为GBK
,因为编码方式的不同,导致同一文件在不同地方的展示出现了乱码的情况;我们可以通过响应,显式的告诉浏览器通过utf8
的方式进行编码,就可以避免乱码的情况了。
上述红框中代码的含义为,响应的返回类型为html
格式,编码方式为utf8
.
重新打包部署并测试:
当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 对象的枚举,包含在该请求中包含的参数的名称(即键值对中的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对象 |
通过这些方法可以获取到一个请求中的各个方面的信息。
注意:请求对象是服务器收到的内容,不应该修改。因此上面的方法也都只是“读”方法,而不是“写”方法。
创建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("首行部分
");
stringBuilder.append(req.getProtocol());
stringBuilder.append("
");
stringBuilder.append(req.getMethod());
stringBuilder.append("
");
stringBuilder.append(req.getRequestURI());
stringBuilder.append("
");
stringBuilder.append(req.getContextPath());
stringBuilder.append("
");
stringBuilder.append(req.getQueryString());
stringBuilder.append("
");
stringBuilder.append("header部分
");
Enumeration<String> headerNames=req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName= headerNames.nextElement();
String headerValue=req.getHeader(headerName);
stringBuilder.append(headerName+":"+headerValue+"
");
}
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write(stringBuilder.toString());
}
}
最常用的其实是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);
}
}
浏览器构造如下请求。
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>Documenttitle>
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>
服务器获取参数的方式和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构造出body
为json
格式的请求
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>Documenttitle>
head>
<body>
<input type="text" id="userId">
<input type="text" id="classId">
<input type="button" id="submit" value="提交">
<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对象就被构造好了。
测试效果演示:
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中写入二进制格式数据 |
注意:响应对象是服务器要返回给浏览器的内容,这里的重要信息都是程序猿设置的。因此上面的方法都是“写”方法
对于状态码/响应头的设置,要放到getWriter/getOutputStream之前,否则可能设置失效
代码:
@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页面一样
代码:
@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());
}
}
效果预览:
代码:
@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!!如有问题,欢迎评论区批评指正😁