2022.5.6 servlet简介
Servlet
Servlet简介
介绍
什么是 Servlet
-
Servlet 是 JavaEE 规范之一,规范就是接口
-
Servlet 就 JavaWeb 三大组件之一。三大组件分别是:Servlet 程序、Filter 过滤器、Listener 监听器。
-
Servlet 是运行在服务器上的一个 java 小程序,它可以接收客户端发送过来的请求,并响应数据给客户端。
手动实现 Servlet 程序
-
编写一个类去实现 Servlet 接口
-
实现 service 方法,处理请求,并响应数据 service(ServletRequest req, ServletResponse res)
-
到 web.xml 中去配置 servlet 程序的访问地址
依赖
1 <dependency> 2 <groupId>javax.servlet</groupId> 3 <artifactId>javax.servlet-api</artifactId> 4 <version>4.0.1</version> 5 <scope>provided</scope> 6 </dependency>
1、构建一个普通的Maven项目,删掉里面的src目录,以后我们的学习就在这个项目里面建立Moudel;这个空的工程就是Maven主工程;
pom.xml文件中properties有什么用
properties标签的作用:在标签内可以把版本号作为变量进行声明,后面dependency中用到版本号时可以用${变量名}的形式代替,这样做的好处是:当版本号发生改变时,只有更新properties标签中的变量就行了,不用更新所有依赖的版本号
2、尽可能将所需要的依赖导入pom文件
建servlet子项目
关于maven父子工程理解
-
父项目pom文件多出
1 <modules> 2 <module>servlet-01</module> 3 </modules>
-
子项目pom文件多出
1 <parent> 2 <artifactId>javaweb-02-Servlet</artifactId> 3 <groupId>com.xing</groupId> 4 <version>1.0-SNAPSHOT</version> 5 </parent>
父项目中的jar包子项目可以直接使用,类似于java中的继承
maven环境优化
1、将子项目web.xml配置成最新的
2、将maven结构搭建完整
测试
HelloServlet
1 package com.xing.servlet; 2 3 import javax.servlet.*; 4 import javax.servlet.http.HttpServletRequest; 5 import java.io.IOException; 6 7 public class HelloServlet implements Servlet { 8 9 @Override 10 public void init(ServletConfig servletConfig) throws ServletException { 11 12 } 13 14 @Override 15 public ServletConfig getServletConfig() { 16 return null; 17 } 18 19 /** 20 * service方法是专门用来处理请求和响应的 21 * @param servletRequest 22 * @param servletResponse 23 * @throws ServletException 24 * @throws IOException 25 */ 26 @Override 27 public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 28 System.out.println("Hello Servlet 被访问了"); 29 } 30 31 @Override 32 public String getServletInfo() { 33 return null; 34 } 35 36 @Override 37 public void destroy() { 38 39 } 40 } 41
web.xml
在子项目的web.xml中编写Servlet的映射
为什么需要映射:我们写的是JAVA程序,但是要通过浏览器访问,而浏览器需要连接web服务器,所以我们需要再web服务中注册我们写的Servlet,还需给他一个浏览器能够访问的路径
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 5 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 6 version="4.0"> 7 8 <!-- servlet 标签给 Tomcat 配置 Servlet 程序 --> 9 <servlet> 10 <!--servlet-name 标签 Servlet 程序起一个别名(一般是类名) --> 11 <servlet-name>HelloServlet</servlet-name> 12 <!--servlet-class 是 Servlet 程序的全类名--> 13 <servlet-class>com.xing.servlet.HelloServlet</servlet-class> 14 </servlet> 15 16 <!--servlet-mapping 标签给 servlet 程序配置访问地址--> 17 <servlet-mapping> 18 <!--告诉服务器,我当前配置的地址给哪个 Servlet 程序使用,对应上面的servlet标签--> 19 <servlet-name>HelloServlet</servlet-name> 20 <!--url-pattern 标签配置访问地址 <br/> 21 / 斜杠在服务器解析的时候,表示地址为:http://ip:port/工程路径 <br/> 22 /hello 表示地址为:http://ip:port/工程路径/hello <br/> 23 --> 24 <url-pattern>/hello</url-pattern> 25 </servlet-mapping> 26 </web-app>
启动tomcat,访问 localhost:8080/06_servlet/hello 控制台打印
常见的错误
-
url-pattern 中配置的路径没有以斜杠打头。
-
servlet-mapping标签中servlet-name 配置的值不存在
-
servlet标签中servlet-class 标签的全类名配置错误
Web 中的相对路径和绝对路径
在javaWeb中,路径分为相对路径和绝对路径两种:
相对路径:
-
. 表示当前目录
-
.. 表示上一级目录
-
资源名 表示当前目录/资源名
绝对路径:
-
http://ip:port/工程路径/资源路径
在实际开发中,路径都使用绝对路径,而不简单的使用相对路径。
1 、绝对路径
2 、base+相对
web 中 / 斜杠的不同意义
在web中 /斜杠是一种绝对路径。
-
/斜杠 如果被浏览器解析,得到的地址是:http://ip:port/
-
< a href="/" >斜杠</ a >
-
-
/斜杠 如果被服务器解析,得到的地址是:http://ip:port/工程路径
-
< url-pattern >/servlet 1 </ url-pattern >
-
servletContext.getRealPath(“/”)
-
request.getRequestDispatcher(“/”)
-
-
特殊情况:response.sendRediect(“/”); 把斜杠发送给浏览器解析。得到http://ip:port/
url 地址到 Servlet 程序的访问
Servlet是由Web服务器Tomcat调用,web服务器在收到浏览器请求之后,会:
Servlet 的生命周期
-
执行 Servlet 构造器方法
-
执行 init 初始化方法
-
第一、二步,是在第一次访问请求的时候创建 Servlet 程序会调用。
-
-
执行 service 方法 ,每次访问都会调用。
-
执行 destroy 销毁方法,在 web 工程停止的时候调用。
研究:服务器在启动的Servlet对象有没有被创建出来(默认情况下)?
在Servlet中提供一个无参数的构造方法,启动服务器的时候看看构造方法是否执行
HelloServlet
1 package com.xing.servlet; 2 3 import javax.servlet.*; 4 import javax.servlet.http.HttpServletRequest; 5 import java.io.IOException; 6 7 public class HelloServlet implements Servlet { 8 9 public HelloServlet() { 10 System.out.println("1 构造器方法"); 11 } 12 13 @Override 14 public void init(ServletConfig servletConfig) throws ServletException { 15 System.out.println("2 init初始化方法"); 16 17 } 18 19 @Override 20 public ServletConfig getServletConfig() { 21 return null; 22 } 23 24 /** 25 * service方法是专门用来处理请求和响应的 26 * @param servletRequest 27 * @param servletResponse 28 * @throws ServletException 29 * @throws IOException 30 */ 31 @Override 32 public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 33 System.out.println("3 server === Hello Servlet 被访问了"); 34 35 } 36 37 @Override 38 public String getServletInfo() { 39 return null; 40 } 41 42 @Override 43 public void destroy() { 44 System.out.println("4 . destroy销毁方法"); 45 } 46 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 5 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 6 version="4.0"> 7 8 <servlet> 9 <servlet-name>HelloServlet</servlet-name> 10 <servlet-class>com.xing.servlet.HelloServlet</servlet-class> 11 </servlet> 12 13 <servlet-mapping> 14 <servlet-name>HelloServlet</servlet-name> 15 <url-pattern>/hello</url-pattern> 16 </servlet-mapping> 17 </web-app>
-
经过测试得出结论:默认情况下,服务器在启动的时候Servlet对象并不会被实例化。
-
怎么让服务器启动的时候创建Servlet对象呢?
1 <servlet> 2 <servlet-name>HelloServlet</servlet-name> 3 <servlet-class>com.xing.servlet.HelloServlet</servlet-class> 4 <load-on-startup>0</load-on-startup> 5 </servlet> 6 7 <servlet-mapping> 8 <servlet-name>HelloServlet</servlet-name> 9 <url-pattern>/hello</url-pattern> 10 </servlet-mapping>
启动tomcat,控制台没有输出
"1 构造器方法"
用户发送第一次请求的时候(访问 localhost:8080/06_servlet/hello),控制台输出了以下内容
-
用户在发送第一次请求的时候Servlet对象被实例化(HelloServlet的构造方法被执行了。并且执行的是无参数构造方法。)
-
HelloServlet对象被创建出来之后,Tomcat服务器马上调用了HelloServlet对象的init方法。(init方法在执行的时候,HelloServlet对象已经存在了。已经被创建出来了。)
-
之后每次访问请求都会再次调用server方法(例如刷新当前请求页面)
-
第一:Servlet对象是单例的(单实例的。但是要注意:Servlet对象是单实例的,但是Servlet类并不符合单例模式。我们称之为假单例。之所以单例是因为Servlet对象的创建我们javaweb程序员管不着,这个对象的创建只能是Tomcat来说了算,Tomcat只创建了一个,所以导致了单例,但是属于假单例。真单例模式,构造方法是私有化的。)
-
第二:无参数构造方法、init方法只在第一次用户发送请求的时候执行。也就是说无参数构造方法只执行一次。init方法也只被Tomcat服务器调用一次。
-
停止当前tomcat服务会调用destroy方法
-
-
Servlet的destroy方法只被Tomcat服务器调用一次。
-
destroy方法是在什么时候被调用的?
-
在服务器关闭的时候。
-
因为服务器关闭的时候要销毁HelloServlet对象的内存。
-
服务器在销毁HelloServlet对象内存之前,Tomcat服务器会自动调用HelloServlet对象的destroy方法。
-
-
-
请问:destroy方法调用的时候,对象销毁了还是没有销毁呢?
-
总结
-
-
Servlet的无参数构造方法执行:标志着你出生了。
-
Servlet对象的init方法的执行:标志着你正在接受教育。
-
Servlet对象的service方法的执行:标志着你已经开始工作了,已经开始为人类提供服务了。
-
Servlet对象的destroy方法的执行:标志着临终。有什么遗言,抓紧的。要不然,来不及了。
-
-
关于Servlet类中方法的调用次数?
-
构造方法只执行一次。
-
init方法只执行一次。
-
service方法:用户发送一次请求则执行一次,发送N次请求则执行N次。
-
destroy方法只执行一次。
-
-
当我们Servlet类中编写一个有参数的构造方法,如果没有手动编写无参数构造方法会出现什么问题?
-
报错了:500错误。
-
注意:500是一个HTTP协议的错误状态码。
-
500一般情况下是因为服务器端的Java程序出现了异常。(服务器端的错误都是500错误:服务器内部错误。)
-
如果没有无参数的构造方法,会导致出现500错误,无法实例化Servlet对象。
-
所以,一定要注意:在Servlet开发当中,不建议程序员来定义构造方法,因为定义不当,一不小心就会导致无法实例化Servlet对象。
-
-
思考:Servlet的无参数构造方法是在对象第一次创建的时候执行,并且只执行一次。init方法也是在对象第一次创建的时候执行,并且只执行一次。那么这个无参数构造方法可以代替掉init方法吗?
-
不能。
-
Servlet规范中有要求,作为javaweb程序员,编写Servlet类的时候,不建议手动编写构造方法,因为编写构造方法,很容易让无参数构造方法消失,这个操作可能会导致Servlet对象无法实例化。所以init方法是有存在的必要的。
-
-
init、service、destroy方法中使用最多的是哪个方法?
-
使用最多就是service方法,service方法是一定要实现的,因为service方法是处理用户请求的核心方法。
-
什么时候使用init方法呢?
-
init方法很少用。
-
通常在init方法当中做初始化操作,并且这个初始化操作只需要执行一次。例如:初始化数据库连接池,初始化线程池....
-
-
什么时候使用destroy方法呢?
-
destroy方法也很少用。
-
-
-
GET 和 POST 请求的分发处理
HelloServlet
1 package com.xing.servlet; 2 3 import javax.servlet.*; 4 import javax.servlet.http.HttpServletRequest; 5 import java.io.IOException; 6 //一般不会这么实现Servlet程序,而是继承HttpServlet去实现servlet程序 7 public class HelloServlet implements Servlet { 8 9 public HelloServlet() { 10 System.out.println("1 构造器方法"); 11 } 12 13 @Override 14 public void init(ServletConfig servletConfig) throws ServletException { 15 System.out.println("2 init初始化方法"); 16 } 17 18 @Override 19 public ServletConfig getServletConfig() { 20 return null; 21 } 22 23 /** 24 * service方法是专门用来处理请求和响应的 25 * @param servletRequest 26 * @param servletResponse 27 * @throws ServletException 28 * @throws IOException 29 */ 30 @Override 31 public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { 32 System.out.println("3 server === Hello Servlet 被访问了"); 33 34 35 // 类型转换(因为HttpServletRequest有getMethod()方法,ServletRequest没有 HttpServletRequest继承了ServletRequest) 36 HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest; 37 // 获取请求的方式 38 String method = httpServletRequest.getMethod(); 39 40 if ("GET".equals(method)) { 41 doGet(); 42 } else if ("POST".equals(method)) { 43 doPost(); 44 } 45 46 } 47 48 /** 49 * 做get请求的操作 50 */ 51 public void doGet(){ 52 System.out.println("get请求"); 53 System.out.println("get请求"); 54 } 55 /** 56 * 做post请求的操作 57 */ 58 public void doPost(){ 59 System.out.println("post请求"); 60 System.out.println("post请求"); 61 } 62 63 @Override 64 public String getServletInfo() { 65 return null; 66 } 67 68 @Override 69 public void destroy() { 70 System.out.println("4 . destroy销毁方法"); 71 } 72 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 5 http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 6 version="4.0"> 7 8 <servlet> 9 <servlet-name>HelloServlet</servlet-name> 10 <servlet-class>com.xing.servlet.HelloServlet</servlet-class> 11 </servlet> 12 13 <servlet-mapping> 14 <servlet-name>HelloServlet</servlet-name> 15 <url-pattern>/hello</url-pattern> 16 </servlet-mapping> 17 </web-app>
a.html
1 <!DOCTYPE html> 2 <html lang="zh_CN"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="http://localhost:8080/06_servlet/hello" method="post"> 9 <input type="submit"> 10 </form> 11 </body> 12 </html>
访问http://localhost:8080/06_servlet/a.html 点击提交 因为提交的是post请求,所以走doPost()方法
结果:
通过继承 HttpServlet 实现 Servlet 程序
一般在实际项目开发中,都是使用继承 HttpServlet 类的方式去实现 Servlet 程序。
1、编写一个类去继承 HttpServlet 类
2、根据业务需要重写 doGet 或 doPost 方法
3、到 web.xml 中的配置 Servlet 程序的访问地址
HelloServlet2
1 package com.xing.servlet; 2 3 import javax.servlet.ServletConfig; 4 import javax.servlet.ServletException; 5 import javax.servlet.http.HttpServlet; 6 import javax.servlet.http.HttpServletRequest; 7 import javax.servlet.http.HttpServletResponse; 8 import java.io.IOException; 9 10 public class HelloServlet2 extends HttpServlet { 11 12 /** 13 * doGet()在get请求的时候调用 14 * @param req 15 * @param resp 16 * @throws ServletException 17 * @throws IOException 18 */ 19 @Override 20 protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 21 22 System.out.println("HelloServlet2 的doGet方法"); 23 24 } 25 /** 26 * doPost()在post请求的时候调用 27 * @param req 28 * @param resp 29 * @throws ServletException 30 * @throws IOException 31 */ 32 @Override 33 protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 34 System.out.println("HelloServlet2 的doPost方法"); 35 } 36 }
web.xml
1 <?xml version="1.0" encoding="UTF-8"?> 2 <web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" 5 version="4.0"> 6 7 <servlet> 8 <servlet-name>HelloServlet2</servlet-name> 9 <servlet-class>com.xing.servlet.HelloServlet2</servlet-class> 10 </servlet> 11 12 <servlet-mapping> 13 <servlet-name>HelloServlet2</servlet-name> 14 <url-pattern>/hello2</url-pattern> 15 </servlet-mapping> 16 </web-app>
a.html
1 <!DOCTYPE html> 2 <html lang="zh_CN"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <form action="http://localhost:8080/06_servlet/hello2" method="post"> 9 <input type="submit"> 10 </form> 11 </body> 12 </html>
访问http://localhost:8080/06_servlet/a.html 点击提交 因为提交的是post请求,所以走doPost()方法
使用 IDEA 创建 Servlet 程序
会自动给你创建Servlet类(重写doGet与doPost)并在web.xml中配置servlet标签(Servlet-mapping标签还需自己配置)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 字符编码:从基础到乱码解决
· 提示词工程——AI应用必不可少的技术