我们在写Servlet代码的时候,第一步就是创建一个类,继承HttpServlet,然后重写其中的方法。它里面的方法分为俩类,我们依次介绍:
注:
HttpServlet的实例只在程序启动的时候创建一次,而不是每次收到请求都要创建一次。因此,init方法也就只执行一次。
destory方法不一定能被调用到。只要tomcat关闭,就不再使用HttpServlet类,按理就应该调用destory方法,但是关闭有两种情况:
- 正常关闭:通过8005端口给tomcat发送关闭指令,tomcat就会正常关闭,会调用到destory方法
- 异常关闭:点击红色×关闭、通过任务管理器关闭、断电关闭,这些情况下tomcat会异常关闭,不会调用到destory方法
tomcat收到请求后实际会先调用service方法,再由service方法调用对应的do×××方法来处理请求。但是实际开发过程中直接重写do×××方法就行了。
注:tomcat每次收到不同类型的请求,调用不同类型的方法来处理请求。
在初始阶段,实例化的时候,会调用一次init()方法;在每次收到请求的时候,都会调用service()方法,再由service()方法分别调用do×××()方法进行处理请求;在结束之前,调用一次destroy()方法。
Tomcat通过SocketAPI读取HTTP请求(字符串),并按照HTTP协议的格式把字符串解析成HttpServletRequest对象。
请求中的参数是用来传递真实的数据的,我们往往需要通过这些数据来计算响应。因此,我们就需要对参数中的这些数据进行接收。根据数据传递的不同方式,我们总结出以下三种方式来对数据进行接收:
@WebServlet("/getParameter")
public class GetParameterServlet extends HelloServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 浏览器构造的quary String 的形式: ?studentId=1&studentName=张三
String studentId = req.getParameter("studentId");
String studentName = req.getParameter("studentName");
System.out.println(studentId);
System.out.println(studentName);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write(studentId + "," + studentName);
}
}
注:
- 使用getParameter()方法来接收请求中传递来的参数,这些参数都是以键值对的形式传递的;()里面写键值对的key,就可以得到键值对中的value
- 在将数据返回前端时要注意设置数据返回的格式,否则前端接收到数据后会随机选择一种格式展示在页面上,可能不是我们想要的格式。
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 预期请求的 body 里是 studentId=1&studentName=张三
String studentId = req.getParameter("studentId");
String studentName = req.getParameter("studentName");
System.out.println(studentId);
System.out.println(studentName);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write(studentId + "," + studentName);
}
注:
- 使用getParameter()方法来接收请求中传递来的参数,这些参数都是以键值对的形式传递的;()里面写键值对的key,就可以得到键值对中的value
- 在将数据返回前端时要注意设置数据返回的格式,否则前端接收到数据后会随机选择一种格式展示在页面上,可能不是我们想要的格式。
Servlet内部没有提供解析JSON格式的工具,那怎么办呢?
我们自己写一个嘛?
不需要,太麻烦了。我们知道JSON是支持嵌套的,如果我们自己写一段代码来解析就需要使用递归等途经,非常麻烦。
使用现成的第三方库—jackson
这种现成的第三方库就提供了解析JSON格式的工具,我们只需要在项目中引入依赖就可以使用这些功能。我们主要学习jackson提供的一个类俩个方法:
一个类:ObjectMapper
方法一:readValue()用来把JSON格式的数据转化为Java的对象
方法二:writeValue()用来把Java的对象转化为JSON格式的数据
@WebServlet("/json")
public class JsonServlet extends HelloServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 此处假设请求的 body 格式为
// { studentId: 1, studentName: "张三" }
// jackson 提供的核心的类
ObjectMapper objectMapper = new ObjectMapper();
// 一个方法叫做 readValue, 把 json 格式的数据转成 java 的对象
// readValue 第一个参数可以是字符串, 也可以是输入流.
// 第二个参数, 是一个类对象. 也就是要解析出来的结果的对象的类.
Student student = objectMapper.readValue(req.getInputStream(), Student.class);
System.out.println(student.studentId);
System.out.println(student.studentName);
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write(student.studentId + "," + student.studentName + "," + student.score.scores.toString());
}
}
注:
- 在接收JSON格式的数据时,要先创建出一个类用来接收数据。这个类中的属性要和JSON的键值对匹配(键的名字务必和属性名一一对应)。
- 一定要导入jackson依赖,使用jackson来获取数据
// 还有一个方法叫做 writeValueAsString, 把 java 对象转成 json 格式的字符串
resp.setContentType("application/json;charset=utf8");
//写法一:
resp.getWriter().write(objectMapper.writeValueAsString(student));
//写法二:
objectMapper.writeValue(resp.getWriter(),student);
注:
- 两种写法都可以,可以任选一种使用。
- 在返回JSON格式的数据时,要设置数据的返回格式为 application/json;charset=utf
@WebServlet("/autoRefresh")
public class AutoRefreshServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setHeader("refresh","2");
resp.getWriter().write(System.currentTimeMillis() + "");
}
}
注:
- 通过设置refresh这个Header来实现页面的自动刷新,第二个参数表示刷新的频率,单位是”秒“
- Header的种类很多,有许多默认存在的我们可以更改他们的值,也可以自定义的写入一些header
@WebServlet("/status")
public class StatusServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 约定, 浏览器 query string 传个参数过来.
// 形如 type=1
// 如果 type 为 1, 返回 200; type 为 2, 返回404; type 为 3 返回一个 500;
String type = req.getParameter("type");
if (type.equals("1")){
resp.setStatus(200);
}else if (type.equals("2")){
resp.setStatus(404);
}else {
resp.setStatus(500);
}
}
}
注:
- 这些状态码设置什么值、前端页面如何处理? 都是由程序员自定义的。
- 状态码表:描述了不同的状态码表示什么状态点击查看状态码表
@WebServlet("/redirect")
public class RedirectServlet extends HelloServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//方式一:
resp.sendRedirect("https://www.sogou.com");
//方式二:
resp.setStatus(302);
resp.setHeader("Location","https://www.sogou.com");
}
}
注:
- 方式一直接设置重定向,填写一个参数,表示重定向到的URL
- 方式二间接设置重定向,要同时设置 1.状态码302:表示重定向 2. 填写两个参数:第一个参数是重定向位置标志,第二个参数填入重定向的URL
@WebServlet("/getMessage")
public class GetMsgServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html;charset=utf8");
resp.getWriter().write("成功返回一条消息");
}
}
注:响应数据的格式有很多,点击此处查看所有的响应数据格式