Servlet规范介绍,Servlet接口实现类以及Servlet接口实现类的开发过程及测试

tech2022-07-10  172

本文由博主本人编写,文中有错误的地方欢迎大家批评指正,您的建议将给予我莫大的帮助!😘

Servlet规范介绍

1.Servlet规范是JavaEE规范的一种

2.作用:

1)在Servlet规范中,指定**动态资源文件**的开发步骤(在本篇文章中介绍) 2)在Servlet规范中,指定Http服务器调用动态资源文件的规则(在本篇中介绍) 3)在Servlet规范中,指定Http服务器管理动态资源文件的规则(实际上就是创建动态资源文件实例对象的过程【Servlet对象的生命周期】https://blog.csdn.net/qq_45930996/article/details/108384399)

*Servlet接口的实现类(动态资源文件)

注意:在Servlet规范中认为,Http能调用的动态资源文件必须是Servlet接口的实现类,也就是说,只有Servlet接口的实现类才是动态资源文件Servlet接口是Servlet规范下的一个接口,这个接口存在于Http服务器提供的jar包在Tomcat服务器下的lib文件中,有一个servlet-api.jar的jar包,里面存放着Servlet接口(javax.servlet.Servlet接口)

由上面的叙述可以看出来,在Servlet规范中,动态资源文件其实就是Servlet接口的实现类

动态资源文件的开发步骤

首先创建一个类,这个类要继承自HttpServlet类,从而实现Servlet接口

代码如下: package com.hubu.controller; import javax.servlet.http.HttpServlet; public class ServletTest extends HttpServlet { }

注意以下这里的包名,一般我们将动态资源文件存放在controller这个包下

大家可能会有疑问,为什么这里要继承HttpServlet,而不是直接实现Servlet接口,关于这个问题,建议大家先跳到下面介绍Http服务器调用动态资源文件的规则部分,将会有详细的讲解 请大家阅读了下面的规则再接着看哦,否则看不懂的

重写HttpServlet父类中的doGet()和doPost方法

问题又来了,刚刚规则里(Http服务器调用动态资源文件的规则 ☟ 没看的小伙伴快去看看)明明调用的是service方法,为啥要实现doGet()和doPost()方法呢?而且这两个方法是干什么用的呢?

还记得在规则里面说过service()方法是交给HttpServlet来实现的吗,是时候看看他的源码了,下面的代码比较多,大家不用全看,只需要看我标注出来的部分

/* HttpServlet对于service()方法的实现 */ protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { //这里:定义了一个method变量,用于获取用户请求这个动态资源文件的方式 //方式包括:get,post,head,put,delete,options,trace //一般用到的是get和post String method = req.getMethod(); long lastModified; //这里是如果请求方式是get的话 if (method.equals("GET")) { lastModified = this.getLastModified(req); if (lastModified == -1L) { //这里就会调用当前对象doGet()方法 this.doGet(req, resp); } else { long ifModifiedSince; try { ifModifiedSince = req.getDateHeader("If-Modified-Since"); } catch (IllegalArgumentException var9) { ifModifiedSince = -1L; } if (ifModifiedSince < lastModified / 1000L * 1000L) { this.maybeSetLastModified(resp, lastModified); this.doGet(req, resp); } else { resp.setStatus(304); } } } else if (method.equals("HEAD")) { lastModified = this.getLastModified(req); this.maybeSetLastModified(resp, lastModified); this.doHead(req, resp); } //这里是如果请求方式是post的话 else if (method.equals("POST")) { //就会调用当前对象的doPost()方法 this.doPost(req, resp); } else if (method.equals("PUT")) { this.doPut(req, resp); } else if (method.equals("DELETE")) { this.doDelete(req, resp); } else if (method.equals("OPTIONS")) { this.doOptions(req, resp); } else if (method.equals("TRACE")) { this.doTrace(req, resp); } else { String errMsg = lStrings.getString("http.method_not_implemented"); Object[] errArgs = new Object[]{method}; errMsg = MessageFormat.format(errMsg, errArgs); resp.sendError(501, errMsg); } }

标注的已经比较清楚了,HttpServlet已经帮我们实现了service()方法,在它实现的service()方法中实际用到了doGet()、doPost()、doHead()等方法,所以在自己的类中,只需要重写这些方法就可以了

代码如下:

package com.hubu.controller; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class ServletTest extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("浏览器正通过get请求的方式访问该动态资源文件"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { System.out.println("浏览器正通过post请求的方式访问该动态资源文件"); } }

将Servlet接口实现类的信息【注册】到Tomcat服务器中

在当前网站项目下的web文件夹下WEB-INF文件夹下的web.xml中进行配置 当前网站 —> web —> WEB-INF —> web.xml

<!-- Servlet接口实现类类路径交给Tomcat服务器 --> <servlet> <!--为该动态文件放在一个变量上面--> <servlet-name>testServlet</servlet-name> <!--动态资源文件的类路径--> <servlet-class>com.hubu.controller.ServletTest</servlet-class> </servlet> <!-- 为Servlet接口实现类提供简短的别名 --> <servlet-mapping> <!--指定的变量名--> <servlet-name>testServlet</servlet-name> <!--别名,注意这里,别名必须以"/"开头--> <url-pattern>/test</url-pattern> </servlet-mapping>

Http服务器调用动态资源文件的规则

以Tomcat服务器为例

Tomcat服务器调用Servlet服务器的规则:

Tomcat服务器有权创建Servlet接口实现类的实例对象 Servlet oneServlet = new OneServlet(); Tomcat服务器根据实例对象调用service()方法 onServlet.service();

对于上面我们遗留了一个问题,为什么Servlet接口实现类选择继承HttpServlet而不是直接实现Servlet接口

这里我们首先看一下HttpServlet类的源码 可以看到它是继承自GenericServlet,然后我们看一下GenericServlet的源码 可以看到他是实现了Servlet接口的 因此,类通过继承HttpServlet类相当于实现了Servlet接口 重点: 我们再看一下Servlet接口的源码

package javax.servlet; import java.io.IOException; public interface Servlet { void init(ServletConfig var1) throws ServletException; ServletConfig getServletConfig(); void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException; String getServletInfo(); void destroy(); }

可以看到,这个接口里面有五个方法,而上面介绍的Tomcat服务器调用动态资源文件的规则中,他只用到了service()方法 如果我们选择直接实现Servlet接口,那五个抽象方法我们都要实现,这样难度还是很大的 所以开发者为我们提供了抽象类,预先实现了这些不太重要的抽象方法,这里我们首先看一下GenericServlet这几个抽象方法的实现

/* 这是GenericServlet中几个方法的源码 */ public void init(ServletConfig config) throws ServletException { this.config = config; this.init(); } public ServletConfig getServletConfig() { return this.config; } public String getServletInfo() { return ""; } public void destroy() { } //注意这里的service方法,并没有被实现,他将在HttpServlet类中实现 public abstract void service(ServletRequest var1, ServletResponse var2) throws ServletException, IOException;

这里的service方法,并没有被实现,他将在HttpServlet类中实现

所以这就解释了为什么我们选择继承HttpServlet类的方式而不是直接实现Servlet接口的方式创建动态资源文件

另外在这里讲一下抽象类的作用,大家学了抽象类可能并不知道他有什么作用哈哈哈: 抽象类作用:

降低接口实现类对接口实现过程中的开发难度 将接口中不需要使用抽象方法交给抽象类完成 这样接口实现类只需要对接口必要的方法进行重写

好了大家可以回去继续阅读啦

测试

创建好了一个动态资源文件后我们来测试一下

启动Tomcat服务器

用get请求该动态资源文件 可以看到服务器端运行了doGet()方法,打印了一段信息

用post请求该动态资源文件 可以看到服务器端运行了doPost()方法,打印了一段信息

最新回复(0)