Hello,我是栋zzzz,先祝各位端午节快乐!!那么接下来就继续来学习Servlet吧,我给大家整理了一些前置知识,方便更好的理解Servlet:
- HTTP协议(上)
- HTTP协议(下)
- Tomcat
- Servlet
这里主要掌握Servlet提供的三个类,而要掌握一个类的使用,就得熟悉一下其的各种方法的使用,下面就来看一下下面三个类的各种方法吧
- init():在HTTPServlet实例化后进行一些初始化的操作(只进行一次);
- service(): 在收到HTTP请求的时候调用各种方法(可能会进行多次);
- destroy():在HTTPServlet实例不再被使用的时候进行一些资源释放的操作(只进行一次);上述三个方法也就是Servlet的生命周期了,不过一般不会重写这三个方法,主要会重写下面的方法!
- doGet():收到GET请求的时候调用这个方法(由service方法调用);
- doPost():收到POST请求的时候调用这个方法(由service方法调用);
- doPut()/doDelete()/doOptions()…:收到各种其他请求的时候调用相匹配的方法(由service方法调用);
这里使用ajax构造一个POST请求,调用doPost方法得到响应:
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">script>
<script>
$.ajax({
type: "post",
url: "method",
success: function(body){
console.log(body);
}
})
script>
注意url这里是相对路径,不能加/,相当于当前html所在的路径,访问这个html使用的路径是/servletMethod/method,test.html所在的路径就是/servletMehod,在这个基础上加上method总路径就是可以访问的路径,而加上/就是绝对路径了,然后两级路径就只剩下这一级路径了那当然就会出现404了;
Java代码:
//此处必须加/,这个斜杠和相对绝对路径不是一个东西,这是硬性要求
@WebServlet("/method")
public class MyHttpServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf8");//这样就可以指定数据的格式和编码了
resp.getWriter().write("POST 响应");
}
}
由于这里是使用idea其字符编码是utf8,而浏览器是GBK编码,所以直接输出中文的话,是会出现乱码的问题的,因此这里就需要统一编码才可以,因此就需要加上resp.setContentType(“text/html;charset=utf8”);然后就可以访问了,但是由于这里构造的是POST请求,因此不能直接通过url的形式来访问,因此这里就直接访问test.html页面了:
这里在控制台就打印出了body的内容,想要打印在页面的话,可以将内容放到dom树里面,就可以了这里就不演示了,通过fiddler也可以看到请求和响应:
请求:
响应:
这里的各种方法就对应到了HTTP请求报文里面有什么,这里就有什么方法:
- getProtocol():协议名和版本号;
- getMethod():返回HTTP请求的方法;
- getRequestURI():返回请求的url地址的一部分;
- getContextPath():返回上下文路径(一级路径);
- getQueryString():返回query string(路径后的查询字符串);
- getParameterNames():以枚举的形式返回查询字符串中的所有key值
- getParameter():返回通过查询字符串的key值得到的value值;
- getHeaderNames:以枚举的形式返回请求报头中的所有key值;
- getHeader():返回通过key值获得的value值;
- getInputStream():得到一个输出流对象,从这个对象中读取数据,就可以得到请求中的body!
来获取一下get请求中的内容:
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 MyHttpServletRequest extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//把api得到的结果放到stringBuilder中去,方便后面放入body
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("下面是首行部分
");
//得到协议名和版本
stringBuilder.append("协议名和版本:" + req.getProtocol());
stringBuilder.append("
");
//得到方法
stringBuilder.append("方法:" + req.getMethod());
stringBuilder.append("
");
//得到url(请求路径)
stringBuilder.append("url:" + req.getRequestURI());
stringBuilder.append("
");
//得到上下文路径(一级路径)
stringBuilder.append("context path:" + req.getContextPath());
stringBuilder.append("
");
//得到query string 有?后面的内容就是query string,没有就是null
stringBuilder.append("query string:" + req.getQueryString());
stringBuilder.append("
");
//得到header部分
stringBuilder.append("下面是header部分
");
//枚举
Enumeration<String> headerNames = req.getHeaderNames();
//迭代器
while(headerNames.hasMoreElements()){
//通过枚举得到每一个key
String headerName = headerNames.nextElement();
//再通过每一个key得到对应的value
String headerValue = req.getHeader(headerName);
stringBuilder.append(headerName + ":" + headerValue + "
");
}
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write(stringBuilder.toString());
}
}
这些方法中比较常用的就是getParameter(),通过查询中字符串的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;
@WebServlet("/getParameter")
public class GetParameterServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//构造一个形如/getParameter?userId=10&class=20的请求,通过name得到其value
String userId = req.getParameter("userId");
String classId = req.getParameter("classId");
resp.getWriter().write("userId=" + userId + ",classId=" + classId);
}
}
通过post请求来传递参数(一般会放在body中):
而post请求的body格式:①x-www-form-urlencoded②form-data③json,一般一和三用的多一些,二用的不是很多(主要用于上传数据)
而如果请求是x-www-form-urlencoded的话,服务器获取参数的方式也是和get一样使用getParameter:
通过form表单:
<form action="postParameter" method="post">
<input type="text" name="userId">
<input type="text" name="classId">
<input type="submit" 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;
/**
* Creared with IntelliJ IDEA.
* Description:
* User:yxd
* Date:2022-05-30
* Time:14:10
*/
@WebServlet("/postParameter")
public class PostRequest extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//假设传来的参数格式是形如:userId=10&classId=20
String userId = req.getParameter("userId");
String classId = req.getParameter("classId");
resp.getWriter().write("userId=" + userId + ",classId=" + classId);
}
}
json方式对于body为json格式来说,如果手动解析,其实并不容易解析(json里面的字段可以嵌套),因此这里就使用第三方库来解决这个问题,而处理json的第三方库有很多,这里就使用Jackson,引入Jackson的方式将如下代码放到pom.xml的dependencies标签里面就可以了
<dependency>
<groupId>com.fasterxml.jackson.coregroupId>
<artifactId>jackson-databindartifactId>
<version>2.12.6.1version>
dependency>
①先来写前端代码:
<input type="text" id="userId">
<input type="text" id="classId">
<input type="button" value="提交" id="submit">
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">script>
<script>
let button = document.querySelector('#submit');
let userIdInput = document.querySelector('#userId');
let classIdInput = document.querySelector('#classId');
button.onclick = function(){
$.ajax({
type: "post",
url: "postParameter2",
//另外contentType也是需要修改为json格式
contentType: "application/json",
//data就表示当前的body以什么样的方式来构造,对于post这样的请求,ajax就允许使用data属性来构造请求的body部分
data: JSON.stringify({
userId: userIdInput.value,
classId: classIdInput.value
}),
success:function(body){
console.log(body);
}
})
}
script>
而此处构造的body就是一个js对象,也就是这样的键值对的结构,然后把这个js对象通过JSON.stringify转成一个字符串的结构,而这个字符串的格式就正是JSON的格式
②然后再来写后端代码处理这样的请求:
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 int userId;
public int classId;
}
@WebServlet("/postJson")
public class PostJsonServlet extends HttpServlet {
//这里需要使用Jackson的核心对象:
ObjectMapper objectMapper = new ObjectMapper();
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//而这里就通过Jackson的对象把请求中的内容给读取出来
//有两个参数,第一个参数表示把哪个字符串进行转换,可以是一个String,也可以是一个inputStream,也可以是一个file,
//第二个参数表示要把读出来的JSON字符串放到哪个java对象里面
User user = objectMapper.readValue(req.getInputStream(),User.class);//(.class)
//然后这个对象里面的所能匹配的属性就表示了读取出来的JSON内容了
resp.getWriter().write("userId: " + user.userId + ",classId: " + user.classId);
}
}
请求:
响应:
通过JSON的格式构造body也就完成了!!!
postman:可以直接使用一个第三方软件来模拟构造请求来获取响应
这里的各种方法就对应到了HTTP响应报文里面有什么,这里就有什么方法:
- setStatus():为该响应设置状态码;
- setHeader():设置一个带有给定名称和值的header,如果name已存在,就会覆盖旧的值;
- addHeader():添加一个带有给定名称和值的header,如果name已经存在,就再添加新的键值对;
- setContentType():设置被发送到客户端的响应的内容类型;
- setCharacterEncoding():设置被发送到客户端的响应的字符编码;
- sendRedirect():构造一个302重定向响应;
- getWrite():往body里面写数据;
- getOutputStream();往body里面写入二进制格式数据;
下面通过一些例子来演示一下上面的方法:
通过直接改状态码,就可以来改变返回的响应的状态码
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.setStatus(404);
resp.getWriter().write("hello");
}
}
这里可以看到虽然响应是404,但是页面依然打印了hello,所以这里的状态码只是在告诉浏览器,当前的响应是什么状态的,而并不会影响到浏览器去正常显示body内容!
通过设置setHeader就可以实现自动刷新页面的效果:
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 AutoRefresh extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//通过设置setHeader就可以实现自动刷新
//第一参数就表示刷新,第二个参数表示每隔一秒刷新一次
resp.setHeader("Refresh","1");
//保证不会乱码
resp.setContentType("text/html;charset=utf8");
//为了更明显的看出来页面有刷新的痕迹,这里就设置一个时间戳
resp.getWriter().write("当前时间戳:" + System.currentTimeMillis());
}
}
时间也是在不停的发生变化,而且通过fiddler抓取看到的也是有很多请求和响应:
这样一个自动刷新页面的效果也就出来了!!!
通过修改状态码和header就可以实现重定向:
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.setStatus(302);
//在通过设置setHeader的方式来构造重定向页面,这里直接跳转到搜狗主页
resp.setHeader("Location","https://www.sogou.com");
}
}
然后输入url:http://127.0.0.1:8080/servletMethod/redirect,就可以直接重定向到搜狗主页了
通过响应也可以看出来:
而Servlet提供了更简单的构造重定向的方法sendRedirect,通过这一个方法就可以直接实现重定向了:
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.sendRedirect("https://www.sogou.com");
}
}