三. Servlet常用API
3.1 HttpServlet
HttpServlet是Servlet接口的一个实现类,并且它是一个抽象类,servlet.http包中定义了采用HTTP通信协议(一个无状态协议)的HttpServlet类;
核心方法:
方法名称 |
调用时机 |
init |
在 HttpServlet 实例化之后被调用一次 |
destory | 在 HttpServlet 实例不再使用的时候调用一次 |
service | 收到 HTTP 请求的时候调用 |
doGet | 收到 GET 请求的时候调用(由 service 方法调用) |
doPost | 收到 POST 请求的时候调用(由 service 方法调用) |
doPut/doDelete/doOptions/... | 收到其他请求的时候调用(由 service 方法调用) |
1)关于 init 方法:
HttpServlet被实例化之后,当首次收到匹配的请求的时候,才会调用到,一般使用这个方法来做一些初始化相关的工作,init只会调用一次;
2)关于 destroy 方法:
这个方法是webapp被销毁前执行一次,用来做一些收尾工作(不建议使用);
3)关于 servlet 方法:
每次收到路径匹配的请求调用一次;
✅常见面试题:让你说一说Servlet的生命周期?
- init 是初始情况下调用一次;
- destroy 是结束之前调用一次;
- service 是每次收到路径匹配的请求调用一次;
3.2 HttpServletRequest
HttpServletRequest对象代表客户端的请求,当客户端通过HTTP协议访问服务器时,HTTP请求头中的所有信息都封装在这个对象中,通过这个对象提供的方法,可以获得客户端请求的所有信息;
核心方法:
方法 | 描述 |
String getProtocol() | 返回请求协议的名称和版本。 |
String getMethod() | 返回请求的 HTTP 方法的名称,例如,GET、POST 或 PUT。 |
String getRequestURI() | 从协议名称直到 HTTP 请求的第一行的查询字符串中,返回该请 求的 URL 的一部分。 |
String getQueryString() | 返回指示请求上下文的请求 URI 部分。 |
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 对象 |
@WebServlet("/ServletRequest") public class ServletRequest extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { StringBuilder stringBuilder = new StringBuilder(); // 返回请求协议的名称和版本 stringBuilder.append(req.getProtocol()); stringBuilder.append("<br>"); // 返回请求的 HTTP 方法的名称 stringBuilder.append(req.getMethod()); stringBuilder.append("<br>"); // 返回URI stringBuilder.append(req.getRequestURI()); stringBuilder.append("<br>"); // 返回在路径后的请求 URL 中的查询字符串 stringBuilder.append(req.getQueryString()); stringBuilder.append("<br>"); // 在响应中设置body的类型 resp.setContentType("text/html;charset=utf8"); resp.getWriter().write(stringBuilder.toString()); } }
这里介绍一个最常用的API,就是getParameter,我们在开发的需求中,前端给后端传递数据时是非常常见的需求,假设这里我们把前端的姓名和密码传到后端,就可以这样写:
1)通过 query string 传递
@WebServlet("/getParameter") public class GetParameter extends HttpServlet { // 通过 query string 传递 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String username = req.getParameter("username"); String password = req.getParameter("password"); if(username == null){ System.out.println("username 在 query string 中不存在"); } if(password == null){ System.out.println("password 在 query string 中不存在"); } System.out.println("username = " + username + " ,password = " + password); resp.getWriter().write("ok"); } }
2)通过body传递
@Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置编码方式,以防乱码 req.setCharacterEncoding("utf8"); // 前端通过body,以form表单的格式,把用户名和密码传给服务器 String username = req.getParameter("username"); String password = req.getParameter("password"); if(username == null){ System.out.println("username 在 query string 中不存在"); } if(password == null){ System.out.println("password 在 query string 中不存在"); } System.out.println("username = " + username + " ,password = " + password); resp.getWriter().write("ok"); }
我们通过Postman构造请求可以发现:
3)通过json传递(最常用的)
在使用json之前,我们引入一个第三方库,这里可以去Maven中央仓库下载:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.15.0</version> </dependency>
class User { public String username; public String password; } @WebServlet("/json") public class JsonServlet extends HttpServlet { // 这个对象可以把 json 格式的字符串解析成 java 对象,同时也可以把 java 对象转化成一个 json 格式字符串 private ObjectMapper objectMapper = new ObjectMapper(); @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 通过 post 请求的 body 传递一个 json 格式的字符串 User user = objectMapper.readValue(req.getInputStream(), User.class); System.out.println("username = " + user.username + ", password = " + user.password); resp.getWriter().write("ok"); } }
通过Postman构造请求可以发现:
上述的 readValue 方法主要做的是:
1.解析json字符串,转换成若干个字符串;
2.根据第二个参数类对象(Use.class),去找到 User 里的 public 的属性;
3.遍历属性,根据属性的名字,去查询键值对,看看这个属性的名字是否存在对应的 value,如果存在,就把 value 赋值到该属性中;
3.2 HttpServletResponse
HttpServletResponse表示一个HTTP响应
核心方法:
方法 | 描述 |
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 中写入二进制格式数据. |
@WebServlet("/response") public class ServletResponse extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setStatus(200); resp.setContentType("text/html;charset=utf8"); resp.getWriter().write("返回200响应"); } }
设置重定向:
@WebServlet("/redirect") public class ServletRedirect extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 设置状态码 resp.setStatus(302); // 设置重定向的网页地址 resp.setHeader("location","https://www.baidu.com"); } }
这里就直接跳转到了百度的网页了!