使用Idea创建一个Servlet项目并自动部署到Tomcat上
一、Servlet简介
Servlet技术背景
Servlet 是 Server Applet 的缩写,译为“服务器端小程序”,是一种使用 Java 语言来开发动态网站的技术。
Servlet 虽然被称作“小程序”,但是它的功能却异常强大,因为它是基于 Java 的,几乎可以使用所有的 Java API,Java 能做的事情,Servlet 也能做。
Java 是一种功能强大的通用型编程语言,可以处理 HTTP 请求,可以访问数据库,可以生成 HTML 代码,您完全可以使用原生 Java 来开发动态网站。但是,使用原生 Java 开发动态网站非常麻烦,需要自己解析 HTTP 请求的报头,需要自己分析用户的请求参数,需要自己加载数据库组件……种种原因导致使用原生 Java 开发动态网站几乎是一件不能被接受的事情。正是基于这种原因,Java 官方后来推出了 Servlet 技术,它对开发动态网站需要使用的原生 Java API 进行了封装,形成了一套新的 API,称为 Servlet API。
使用 Servlet 开发动态网站非常方便,程序员只需要集中精力处理业务逻辑,不需要再为那些基础性的、通用性的功能编写代码,这使得 Servlet 在动态网站开发领域具备了很高的实用性。
Servlet 基于 Java,可以使用几乎全部的 Java API,所以它的功能异常强大,完全可以胜任企业级开发,能够处理那些高并发、大吞吐量、业务逻辑复杂的应用场景。
您可以这样理解,Servlet 是 Sun 公司推出的一种基于 Java 的动态网站开发技术。编写 Servlet 代码需要遵循 Java 语法,一个 Servlet 程序其实就是一个按照 Servlet 规范编写的 Java 类。Servlet 程序需要先编译成字节码文件(.class文件),然后再部署到服务器运行。
Servlet 是一种规范
所有的 Servlet 功能都是通过一个名为Servlet
的接口(Interface)向外暴露的,编写 Servlet 代码,可以从实现 Servlet 接口开始,就像下面这样:
public class ServletDemo implements Servlet { //TODO:}
直接实现 Servlet 接口比较麻烦,需要实现很多方法,所以 Servlet 规范又提供了两个抽象类,分别是 GenericServlet 类和 HttpServlet 类,它们都实现了 Servlet 接口的很多常用功能。和 GenericServlet 类相比,HttpServlet 类更加方便,所以实际开发中一般都继承自 HttpServlet 类。
JSP是Servlet基础上的进一步封装
Servlet 是第一代 Java Web 开发技术,它将 HTML 代码以字符串的形式向外输出,编写 HTML 文档就是在拼接字符串,非常麻烦,所以 Java 官方又推出了第二代 Web 开发技术——JSP。
JSP 才是现代化的 Web 开发技术,它允许 HTML 代码和 JSP 代码分离,让程序员能够在 HTML 文档中直接嵌入 JSP 代码。
现在没有人直接使用 Servlet 开发动态网站,至少都要用 JSP。但是 JSP 依赖于 Servlet,用户访问 JSP 页面时,JSP 代码会被翻译成 Servlet 代码,最终,HTML 代码还是以字符串的形式向外输出的。您看,JSP 只是在 Servlet 的基础上做了进一步封装。
JSP 代码可以调用 Servlet 类,程序员可以将部分功能在 Servlet 中实现,然后在 JSP 中调用即可。
总之,Servlet 是 JSP 的基础,Servlet 虽然不直接面向用户,但是它依然是 JSP 的后台支撑。
Web容器
我们知道,Servlet 是基于 Java 语言的,运行 Servlet 必然少不了 JRE 的支持,它负责解析和执行字节码文件(.class文件)。然而 JRE 只包含了 Java 虚拟机(JVM)、Java 核心类库和一些辅助性性文件,它并不支持 Servlet 规范。要想运行 Servlet 代码,还需要一种额外的部件,该部件必须支持 Servlet 规范,实现了 Servlet 接口和一些基础类,这种部件就是 Servlet 容器。
Servlet 容器就是 Servlet 代码的运行环境(运行时),它除了实现 Servlet 规范定义的各种接口和类,为 Servlet 的运行提供底层支持,还需要管理由用户编写的 Servlet 类,比如实例化类(创建对象)、调用方法、销毁类等。
我们自己编写的 Servlet 类为什么需要 Servlet 容器来管理呢?这是因为我们编写的 Servlet 类没有 main() 函数,不能独立运行,只能作为一个模块被载入到 Servlet 容器,然后由 Servlet 容器来实例化,并调用其中的方法。
一个动态页面对应一个 Servlet 类,开发一个动态页面就是编写一个 Servlet 类,当用户请求到达时,Servlet 容器会根据配置文件(web.xml)来决定调用哪个类。
您看,Web 服务器是整个动态网站的“大门”,用户的 HTTP 请求首先到达 Web 服务器,Web 服务器判断该请求是静态资源还是动态资源:如果是静态资源就直接返回,此时相当于用户下载了一个服务器上的文件;如果是动态资源将无法处理,必须将该请求转发给 Servlet 容器。
Servlet 容器接收到请求以后,会根据配置文件(web.xml)找到对应的 Servlet 类,将它加载并实例化,然后调用其中的方法来处理用户请求;处理结束后,Servlet 容器将处理结果再转交给 Web 服务器,由 Web 服务器将处理结果进行封装,以 HTTP 响应的形式发送给最终的用户。
常用的 Web 容器有 Tomcat、Jboss、Jetty、WebLogic 等,其中 Tomcat 由 Java 官方提供,是初学者最常使用的。
为了简化部署流程,Web 容器往往也会自带 Web 服务器模块,提供基本的 HTTP 服务,所以您可以不用再安装 Apache、IIS、Nginx 等传统意义上的服务器,只需要安装一款 Web 容器,就能部署 Servlet 网站了。正是由于这个原因,有的教材将 Tomcat 称为 Web 容器,有的教材又将 Tomcat 称为 Web 服务器,两者的概念已经非常模糊了。
总之,Servlet 容器就是 Servlet 程序的运行环境,它主要包含以下几个功能:
- 实现 Servlet 规范定义的各种接口和类,为 Servlet 的运行提供底层支持;
- 管理用户编写的 Servlet 类,以及实例化以后的对象;
- 提供 HTTP 服务,相当于一个简化的服务器。
二、JavaWeb应用的目录结构
JavaWeb 应用由一组 Servlet/JSP、HTML 文件、相关 Java 类、以及其他的资源组成,它可以在由各种供应商提供的 Servlet 容器中运行。
由 JavaWeb 应用的定义可知, Servlet 是 JavaWeb 应用的一个组件。
为了让 Servlet 容器顺利地找到 JavaWeb 应用的各个组件,Servlet 规范规定,JavaWeb 应用必须采用固定的目录结构,即每种组件在 JavaWeb 应用中都有固定的存放目录。
以 Tomcat 为例,通常将 JavaWeb 应用存放到 Tomcat 的 webapps 目录下。在 webapps 下,每一个子目录都是一个独立的 Web 应用,子目录的名字就是 Web 应用的名字,也被称为 Web 应用的上下文根。用户可以通过这个上下文根来访问 JavaWeb 应用中的资源。
webapps 的目录结构如下图。
下表中对 webapps 下各个目录进行了介绍。
三、新建一个简单Servlet项目
创建一个普通的java项目
右键点击项目,再点击add framework support,勾选web Application(默认勾选上 create web.xml),点击ok。
在servlet包下创建一个servletTest类
package com.servlet; 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 { // super.doGet(req, resp); System.out.println("get请求"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // super.doPut(req, resp); System.out.println("post请求"); } }
在web下创建一个login.jsp页面(一定要在web下创建,不然访问不到)
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>登录</title> </head> <body> <form action="/servletTest/login" method="post"> 用户名:<input type="text" name="username"> <br> 密码:<input type="password" name="password"> <br> <input type="submit" value="提交"> </form> </body> </html>
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/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd" version="4.0"> <servlet> <servlet-name>servletTest</servlet-name> <servlet-class>com.servlet.servletTest</servlet-class> </servlet> <servlet-mapping> <servlet-name>servletTest</servlet-name> <url-pattern>/login</url-pattern> </servlet-mapping> </web-app>
在目录WEB-INF下,还缺少两个目录classes和lib,我们自己新建一下这两个目录即可。
我们知道JavaWeb应用的目录结构中:
- \WEB-INF\classes目录存放各种 .class 文件或者包含 .class 文件的目录,Servlet 类的 .class 文件也存放在此。
- \WEB-INF\lib目录存放应用所需的各种 jar 包,例如 JDBC 驱动程序的 jar 包。
因此我们要对编译生成的字节码文件的路径进行一下更改。
点击File-Project Structure,将Modules中的Paths改成你项目中的classes目录
继续,在Libraries中添加lib目录
此时我们想要新建一个servlet是新建不了的,因为JRE并没有包含这个包,这个包在Tomcat中存在,因此我们需要将这个包添加进来。
右键项目名,选择Open Module Settings,添加Tomcat安装目录下的servlet-api.jar包。
此时,servletTest.java提示可以找到servlet类了。
接下来设置Tomcat自动部署。
因为我们是需要在IDEA中启动Tomcat,并把我们的项目部署上去。因此我们需要对Tomcat进行设置。
点击菜单栏上的Run-Edit Configuration,点击加号,选择Tomcat server中的Local
配置一下Tomcat安装目录,然后系统会自动识别出Tomcat的版本。
点击切换到Deployment下,点击下面的加号,选择Artifact。
配置了一下热部署,当类代码或者JSP代码修改时会自动部署到Tomcat上,
点击绿色小三角,运行Tomcat。
浏览器栏输入:
http://localhost:8080/servlet_xxe_test_war_exploded/login.jsp
- servlet_xxe_test_war_exploded:部署到Tomcat上的app名称
- login:url映射路由,在web.xml中已经配置了对应的servlet处理类servletTest.class
随机输入用户名和密码并提交数据
控制台打印信息
说明我们的servlet项目已经成功部署在本地运行的Tomcat上。
POST /servletTest/login HTTP/1.1 Host: localhost:8080 Content-Length: 29 Cache-Control: max-age=0 sec-ch-ua: "Not=A?Brand";v="99", "Chromium";v="118" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "macOS" Upgrade-Insecure-Requests: 1 Origin: http://localhost:8080 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.5993.70 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Referer: http://localhost:8080/servlet_xxe_test_war_exploded/login.jsp Accept-Encoding: gzip, deflate, br Accept-Language: en-US,en;q=0.9 Connection: close username=admin&password=admin
参考链接:
https://blog.csdn.net/eadzsdad/article/details/123395673 https://blog.csdn.net/qq_41854911/article/details/122460601 https://blog.51cto.com/u_15319091/4575565