一、Servlet简介
Servlet是Sun公司开发动态Web的一门技术。Sun公司在这些API中提供了一个Servlet接口,如果你想开发一个Servlet程序只需要完成如下两个步骤:
1、编写一个Java类实现Servlet接口。
2、把开发好的Java类部署到Web服务器中。
我们把实现了Servlet接口的Java程序叫做Servlet。
注:
-
一个Servlet就是一个实现了Servlet接口的Java类。
-
一个Servlet对应一个URL。
二、父项目与子项目
关于父子项目的理解:
(1)父项目的pom.xml配置文件中存在
<modules><module>servlet-01</module>
</modules>
(2)相对应的,子项目(即:Module模块)中存在
<parent><artifactId>javaWeb-Servlet</artifactId><groupId>com.atangbiji</groupId><version>1.0-SNAPSHOT</version>
</parent>
(3)父项目中的依赖包,子项目可以直接使用。(类似于Java中的继承)
这样我们把所有项目的依赖都添加到父项目的pom.xml配置文件中后,那么所有的子项目就不用每次再重复导入依赖包了。
(4)Servlet接口在子项目中实现。
三、Hello Servlet
3.1 创建父项目
(1)创建一个普通的Maven项目(具体步骤参考《Maven详解》),项目名称为javaWeb-Servlet。
(2)删除项目中的src目录,所得到的空项目就是我们的Maven父项目,我们可以在其中创建多个子项目(即:Module)。
(3)在父项目的pom.xml文件中导入父/子工程需要的依赖,根据需求查询有哪些依赖需要导入。
以Servlet项目为例,需要在父项目的pom.xml文件中导入如下依赖:
<dependencies><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>4.0.1</version></dependency>
</dependencies>
注:若在父项目的pom.xml文件中已经添加了某个依赖后,则子项目的pom.xml文件中不要再重复添加该依赖
了,否则Maven项目编译会出错。
至此,父项目创建完毕。
3.2 创建子项目
(1)在父项目中新建一个模块(子项目)。
(2)使用Maven模板创建一个MavenWeb子项目。
(3)填写子项目名称和Maven项目GAV。
(4)配置子项目Maven。点击Finish按钮完成子项目创建,等待Maven依赖包导入完毕。
(5)由于使用Maven模板创建的MavenWeb项目的版本较低(“web-app_2_3”)。为了避免以后出现兼容性问题,建议我们先将该子项目中的web.xml文件替换成“web-app_4_0”版本。具体可以参考Tomcat安装目录下的(D:\Environment\apache-tomcat-9.0.65\webapps\examples\WEB-INF)web.xml文件。
web.xml
文件:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"></web-app>
注:Web.xml是Java Web项目的一个核心配置文件,主要用于配置首页、Servlet、Filter、Listener等。
(6)在子项目的main文件夹下新建一个java文件夹和一个resource文件夹,并将它们分别标记为“源码根目录”和“资源根目录”。(具体步骤参考《Maven详解》)
(7)至此,子项目创建完毕。编译父项目或子项目,此时父项目与子项目的目录结构如下图所示。
3.3 编写一个Java类实现Servlet接口(重点)
(1)在子项目的java目录下新建一个com.atangbiji.servlet包,并在该包下新建一个HelloServlet类,用于实现Servlet接口。
(2)让HelloServlet类继承(extends)HttpServlet类。(此时,Maven会通过父项目中的依赖自动导入依赖包。)
HelloServlet.java
文件:
public class HelloServlet extends HttpServlet {}
注:
-
Servlet是一个接口程序,也就是一个java程序,其存放于main-java文件夹中。
-
由于sun公司为我们提供了两个默认的
Servlet
接口实现类:①HttpServlet
,②GenericServlet
。因此,我们只需继承HttpServlet类便可实现Servlet接口。
附:Servlet接口、GenericServlet类和HttpServlet类详解
a、Servlet接口源码
public interface Servlet {void init(ServletConfig var1);ServletConfig getServletConfig();void service(ServletRequest var1, ServletResponse var2);//核心接口String getServletInfo();void destroy();
}
b、GenericServlet类源码(部分)
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {……public abstract void service(ServletRequest var1, ServletResponse var2);//直接继承,未做任何处理……
}
c、HttpServlet类源码(部分)
public abstract class HttpServlet extends GenericServlet {……//重写service方法public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {if (req instanceof HttpServletRequest && res instanceof HttpServletResponse) {HttpServletRequest request = (HttpServletRequest)req;HttpServletResponse response = (HttpServletResponse)res;this.service(request, response);} else {throw new ServletException("non-HTTP request or response");}}//重载service方法protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {String method = req.getMethod();long lastModified;//若请求方式为get,则调用doGet方法if (method.equals("GET")) {lastModified = this.getLastModified(req);if (lastModified == -1L) {this.doGet(req, resp);} else {long ifModifiedSince = req.getDateHeader("If-Modified-Since");if (ifModifiedSince < lastModified) {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);} else if (method.equals("POST")) {this.doPost(req, resp); //若请求方式为post,则调用doPost方法} 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);}}protected void doGet(HttpServletRequest req, HttpServletResponse resp) {……}protected void doPost(HttpServletRequest req, HttpServletResponse resp){……}……
}
分析源码,我们可以发现:
- 我们自定义的Servlet类与Servlet接口、GenericServlet类和HttpServlet类的关系如下图所示。
-
HttpServlet类重写的service(ServletRequest,ServletResponse)方法中会把ServletRequest和ServletResponse强转成HttpServletRequest和HttpServletResponse,然后再调用service(HttpServletRequest,HttpServletResponse)方法。
-
HttpServlet类重载了service(HttpServletRequest,HttpServletResponse)方法,该方法是 HttpServlet 自己重载的方法,而不是从Servlet继承来的。
【结论】:HttpServlet类在重载的service(HttpServletRequest,HttpServletResponse)方法中,会根据不同的Http请求方式,调用不同的处理方法。因此,我们需要在我们自己编写的Servlet类中重写相应的Http请求处理方法(重点掌握doGet和doPost方法)。
注
:我们可以通过IDEA为我们提供的Structure窗口来查看HttpServlet类的成员变量和成员函数。
(3)在HelloServlet类中重写doGet和doPost方法。
HelloServlet.java
文件:
public class HelloServlet extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {System.out.println("进入了doGet方法");//在控制台打印调试信息PrintWriter writer = resp.getWriter();//响应流writer.print("Hello Servlet!");//在浏览器显示Hello Servlet!}@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {doGet(req,resp); //因为`get`和`post`只是不同的Http请求方式,所以它们之间可以相互调用。}
}
注
:因为get和post只是不同的Http请求方式,所以它们之间可以相互调用。
3.4 编写Servlet的映射(重点)
注
:因为我们写的是一个Java程序,但是如果我们要通过浏览器去访问它,就需要连接web服务器。因此,我们需要在Web配置文件(web.xml)中注册(映射)我们自己编写的Servlet,并为其提供一个浏览器可以访问的路径。
web.xml
文件:
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaeehttp://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"version="4.0"metadata-complete="true"><!-- 注册Servlet --><servlet><servlet-name>servlet1</servlet-name><servlet-class>com.atangbiji.servlet.HelloServlet</servlet-class></servlet><!-- Servlet的访问路径 --><servlet-mapping><servlet-name>servlet1</servlet-name><url-pattern>/hello</url-pattern></servlet-mapping></web-app>
3.5 配置Tomcat服务器
(1)配置Tomcat服务器。(具体步骤参考《Tomcat详解》)
(2)deploy(发布)servlet-01:war包,并为该子项目添加虚拟路径映射:/s1。
3.6 启动测试
在IDEA中启动Tomcat。
(1)在浏览器中输入http://localhost:8080/s1/,访问结果如下:
注
:此时访问的是该Web项目的index.jsp文件。
index.jsp
文件:
<html>
<body>
<h2>Hello World!</h2>
</body>
</html>
(2)在浏览器中输入http://localhost:8080/s1/hello,访问结果如下:
注
:此时访问的是我们自己编写的Servlet类。
原创 阿汤笔迹