目录
一. Servlet介绍
1.1 概念
2.2 Servlet架构
二. 创建一个Servlet程序
2.1 创建一个Maven项目
2.2 引入 jar 包
2.3 创建目录
2.4 编写代码
2.5 打包程序
2.6 部署程序
2.7 验证程序
三. Servlet常用API
3.1 HttpServlet
3.2 HttpServletRequest
3.2 HttpServletResponse
一. Servlet介绍
1.1 概念
Servlet 是一种实现动态页面的技术. 是一组 Tomcat 提供给程序猿的 API, 帮助程序猿简单高效的开发一个 web app,使用 Servlet,您可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页;
2.2 Servlet架构
二. 创建一个Servlet程序
一般创建一个简单的 Servlet 程序需要一下几个步骤:
2.1 创建一个Maven项目
2.2 引入 jar 包
打开创建好的Maven工程,点击pro.xml文件,我们需要去中央仓库去引入相对应的依赖,可以去官网复制相应的代码,点击这个网址直接跳转到中央仓库:
https://mvnrepository.com/https://mvnrepository.com/
注意:这里要选择3.1.0的版本,因为这个版本是和 Tomcat8.5 相匹配的,不同的Servlet就要对应不同的Tomcat;
<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency>
把这段代码复制粘贴到Maven工程的pro.xml文件里就OK了,这里需要新增一个<dependencies>标签,这样IDEA就会自动识别并且下载相对应的jar包了;
2.3 创建目录
在main的目录下创建一个webapp的目录,在此目录下创建一个WEB-INF目录,在WEB-INF目录下创建web.xml文件,这里的文件目录和文件名字要保证正确;创建好之后在web.xml中写入相应的代码,这里代码给出了,直接用即可:
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd" > <web-app> <display-name>Archetype Created Web Application</display-name> </web-app>
2.4 编写代码
@WebServlet("/hello") public class HelloServlet extends HttpServlet { // 这里的rep是HTTP请求,resp是HTTP响应 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { resp.setContentType("text/html;charset=utf8"); resp.getWriter().write("hello world"); resp.getWriter().write("你好 世界"); } }
2.5 打包程序
打包做的事情有:
- 检查代码中是否存在一些依赖,依赖是否下载好;
- 把代码进行编译,生成.class文件;
- 把这些.class文件或者.xml文件按照一定格式进行打包;
这里我们双击package,同时我们要在pom.xml文件中插入相应代码,来调整打包生成的格式,如果双击package打出来的包就是jar包,但是我们需要的war包;
// 指定打包格式 <packaging>war</packaging> <build> // 生成包的名字 <finalName>helloServlet</finalName> </build>
这里我们看见就打包成功了;
2.6 部署程序
我们需要把打好的war包移到 tomcat 的webapp目录下
2.7 验证程序
这里我们需要再IDEA上安装一个Smart Tomcat,安装的过程就不细说了,安装完成后,点击运行,在浏览器输入url,localhost:8080/servlet/hello,就可以看到你想显示的东西了;
但是要正确启动一个servlet程序,还需要注意一下路径的问题,否则就会启动失败:
三. 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 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 对象 @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"); } }
这里就直接跳转到了百度的网页了!