Servlet API 详细讲解
API就是一组类和方法的集合,servlet 中的 类是非常多的,咱们只需要学习 3个类即可。
- HttpServlet
- HttpServletRequest(服务器如何读取客户端响应)
- HttpServletResponse(服务器如何把响应返回给客户端)
1. HttpServlet
这是我们编程写 servlet 代码用到的核心的类。通过继承这个类,并重写其中的方法,让 tomcat 去调用这里的逻辑。
方法名称 | 调用时机 |
---|---|
init | 在 HttpServlet 实例化后被调用一次 |
destory | 在 HttpServlet 实例不再使用的时候调用一次 |
service | 收到 HTTP 请求的时候调用 |
doGet | 收到 GET 请求的时候调用(由service方法调用) |
doPost | 收到 POST 请求的时候调用(由service方法调用) |
doPut/doDelete/doOptions/… | 收到其他请求的时候调用(由service方法调用) |
谈谈 tomcat 的生命周期
生命周期就是在什么阶段,做什么事情。下面三个阶段就是tomcat的生命周期。
- webapp 刚被加载的时候,调用 servlet 的 init 方法。
- 每次收到请求的时候,调用 service 方法。
- webapp 要结束的时候,调用 destory 方法。
2.HttpServletRequest
核心方法 | 描述 |
---|---|
String getProtocol() | 返回请求协议的名称和版本。 |
String getMethod() | 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。 |
String getRequestURI() | 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请求的 URL 的一部分。 |
String getContextPath() | 返回指示请求上下文的请求 URI 部分。 |
String getQueryString() | 返回包含在路径后的请求 URL 中的查询字符串。 |
Enumeration getParameterNames() | 返回一个 String 对象的枚举,包含在该请求中包含的参数的名称。 |
String getParameter(String name) | 以字符串形式返回请求参数的值,或者如果参数不存在则返回null。 |
String[] getParameterValues(String name) | 返回一个字符串对象的数组,包含所有给定的请求参数的值,如果参数不存在则返回 null. |
Enumeration getHeaderNames() | 返回一个枚举,包含在该请求中包含的所有的头名。 |
String getHeader(String name) | 以字符串形式返回指定的请求头的值。 |
String getCharacterEncoding() | 返回请求主体中使用的字符编码的名称。 |
String getContentType() | 返回请求主体的 MIME 类型,如果不知道类型则返回 null。 |
int getContentLength() | 以字节为单位返回请求主体的长度,并提供输入流,或者如果长度未知则返回 -1。 |
InputStream getInputStream() | 用于读取请求的 body 内容. 返回一个 InputStream 对象. |
getRequestURI() 中 URI 是唯一资源标识符,URL 是唯一资源定位符。URL也可以理解成 URI 的一种实现方式。此处谈到的 URI 其实就是URL。实际使用中,这两个术语也会经常混着用。
getParameterNames() 和 getParameter() 就是通过一些方式,给服务器传递自定义数据,比如说 query string 和 body。query string 本身就是键值对结构的数据。tomcat收到这个请求之后,就会把这个 query string 解析成 Map 这样的键值对。使用 getParameter 就可以根据 key 获取到 value.
getHeaderNames() 和 getHeader() 是获取到请求头里的键值对,tomcat 收到请求之后 请求头 解析成 Map.
@WebServlet("/request")
public class Method_Servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// 告诉浏览器,你拿到的数据是 html
resp.setContentType("text/html");
// 把得到的数据汇总到一个字符串,统一返回到页面上。
StringBuilder splice = new StringBuilder();
// 下面内容是在浏览器上按照 html 的方式来展示的,此时 \n 在 html 中并不是换行
// 使用 <br> 标签表示换行
splice.append(req.getProtocol());
splice.append("<br>");
splice.append(req.getMethod());
splice.append("<br>");
splice.append(req.getRequestURI());
splice.append("<br>");
splice.append(req.getContextPath());
splice.append("<br>");
splice.append(req.getQueryString());
splice.append("<br>");
splice.append("<br>");
Enumeration<String> headerNames = req.getHeaderNames();
while (headerNames.hasMoreElements()) {
String header = headerNames.nextElement();
splice.append(header + ":" + req.getHeader(header));
splice.append("<br>");
}
resp.getWriter().write(splice.toString());
}
}
服务器如何获取到 query string 和 body 的数据 ??
-
获取 query string。获取 body (只考虑 form 表单的格式)。用 postman 来发送。
URL;127.0.0.1:8080/java_hello/Parameter?name=zhangsan&password=123(method:Get )
URL:127.0.0.1:8080/java_hello/Parameter(method:Post)
-
获取 body(考虑 body 为 json 格式)
这里需要借助第三方库(jackson),也需要通过 maven 从中央仓库把这个库下载下来并导入到项目中。 (导入pox.xml)
Maven第三方库点击跳转
这里需要使用到 ObjectMapper 类,把一个对象映射到 JSON 字符串,也可以把 JSON 映射到对象。这个方法有很多版本,作用就是把 JSON 字符串解析成java对象。其中这里的第一个参数,是一个流对象,也就表示json从哪里读来。第二个参数则是指定的类型,当前得到的 JSON 字符串 需要转成一个啥样的 Java 对象,需要指定一下对象的类型。
class User { public String username; public String password; } @WebServlet("/Parameter3") public class Parameter3_servlet extends HttpServlet { // Json实例 // { // username = "zhangsan", // password = "123" // } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ObjectMapper objectMapper = new ObjectMapper(); User user = objectMapper.readValue(req.getInputStream(),User.class); System.out.println("username = " + user.username + " password = " + user.password); //jackson 还提供了一种方法,能够把 java 对象,转成 json 字符串 String UserString = objectMapper.writeValueAsString(user); System.out.println("UserString:" + UserString); resp.getWriter().write("okk" ); } }
最后需要借助 Postman 来发送 Json(充当客户端)。
接收到客户端发送的请求后,服务器显示。
3.HttpServletResponse
HttpServletResponse 同样也是和 HTTP 响应数据,是相匹配的。比如说 状态码、各种 header、body……针对这些属性,服务器就可以进行响应的编写。
核心方法 | 描述 |
---|---|
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 中写入二进制格式数据. |
代码演示
// 为响应设置对应的状态码 URL:http://127.0.0.1:8080/java_hello/Status
//效果:postman 中会显示505,该服务器无法处理请求。
@WebServlet("/Status")
public class Status_servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置报头的状态码为505
resp.setStatus(505);
}
}
//设置任意的响应报头(这里用Refresh举例) URL:http://127.0.0.1:8080/java_hello/Refresh
//效果:浏览器每隔两秒钟就会自动刷新一次,我们可以看到时间每隔两秒钟变动一次。
@WebServlet("/Refresh")
public class Refresh_servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置报头
resp.setHeader("refresh","2");
resp.getWriter().write("time: " + System.currentTimeMillis());
}
}
//构造一个重定向的响应 URL:http://127.0.0.1:8080/java_hello/Redirect
//效果:当浏览器访问到上面URL的时候,会自动跳转搜狗搜索引擎。
//这里我们用 Fiddler 抓包可以观察到,header 中的状态码。
@WebServlet("/Redirect")
public class Redirect_servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置报头状态码302(重定向)
resp.setStatus(302);
resp.setHeader("Location","https://www.sogou.com/");
}
}
//设置被发送到客户端的响应的内容类型
@WebServlet("/ContentType")
public class ContentType_servlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType(" text/html; charset = utf-8 ");
//文本文件就用getWriter,二进制文件就用getOutputStream
resp.getWriter().write("<div> 你好</div>");
}
}
到此 Servle API 篇就分享完啦。
etException, IOException {
resp.setContentType(" text/html; charset = utf-8 ");
//文本文件就用getWriter,二进制文件就用getOutputStream
resp.getWriter().write("<div> 你好</div>");
}
}
到此 Servle API 篇就分享完啦。