Servlet
Servlet 是啥?
Java Servlet 是运行在 Web 服务器或应用服务器上的程序,它是作为来自 Web 浏览器或其他 HTTP 客户端的请求和 HTTP 服务器上的数据库或应用程序之间的中间层。
使用 Servlet,我们可以收集来自网页表单的用户输入,呈现来自数据库或者其他源的记录,还可以动态创建网页。
Servlet 环境配置
- 从 tomcat.apache.org/ 上下载最新版本的 Tomcat(作者下载的是Version 10.1)
- 解压缩到一个合适的路径后,创建 CATALINA_HOME 环境变量指向这些位置
- 在 Windows 上,可以在cmd中执行下面的命令来启动 Tomcat:
"%CATALINA_HOME%\bin\startup.bat"
出现了如下窗口则代表运行成功
Tomcat 成功启动后,可以通过在浏览器地址栏输入 http://localhost:8080/ 访问 Tomcat 中的默认应用程序。如果一切顺利,那么会显示以下结果:
在 Windows 上,可以通过执行下面的命令来停止 Tomcat:
"%CATALINA_HOME%\bin\shutdown"
如此,我们的准备工作就完成了
Servle 生命周期
它定义了Servlet在Web容器中创建、初始化、接收请求、处理请求和销毁的过程。以下是Servlet生命周期的主要阶段:
1. 创建阶段
在这个阶段,Servlet容器创建一个Servlet实例并分配内存空间。这个阶段只会在Servlet被第一次请求时发生。
public class MyServlet extends HttpServlet {
public MyServlet() {
super();
System.out.println("Servlet实例已经创建");
}
}
2. 初始化阶段
在这个阶段,Servlet容器会调用Servlet的 init() 方法来进行初始化。在这个方法中,我们可以编写一些代码来设置Servlet的初始状态。
public void init() throws ServletException {
super.init();
System.out.println("Servlet已经初始化");
}
3. 请求处理阶段
在这个阶段,Servlet容器会调用Servlet的 service() 方法来处理客户端请求。在这个方法中,我们可以编写一些代码来处理客户端请求并生成响应。
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// 处理客户端请求并生成响应
}
4. 销毁阶段
在这个阶段,Servlet容器会调用Servlet的 destroy() 方法来释放资源并销毁Servlet实例。
public void destroy() {
System.out.println("Servlet实例已经被销毁");
super.destroy();
}
Servlet 生命周期方法
- init()方法 :只在第一次创建 Servlet 时调用,用于初始化 Servlet
- service()方法 :是执行任务的主要方法,我们可以调用 service() 方法来处理来自客户端(浏览器)的请求
- doGet()方法 :处理 GET 请求
GET请求:从服务器请求数据后获取服务端数据
- doPost()方法 :处理 POST 请求
POST请求:就是发送、提交。向服务器提交/发送要被处理的数据
- destroy()方法 :只会被调用一次,在 Servlet 生命周期结束时被调用。
下图显示了一个典型的 Servlet 生命周期方案(网上找的)
这个图片显示了 init() 和 destroy() 方法只会被调用一次,而 service() 方法会随来自浏览器的请求而被调用多次
写一个servlet实例
-
在CATALINE_HOME下找到webapps
-
在webapps下创建一个文件夹,名字就是webapp的名字,这个文件夹就是webapp的根目录
-
在根目录下新建一个名为WEB-INF的文件夹(必须大写)
-
在WEB-INF下新建lib(导入第三方jar包)和classes(存放字节码)文件夹以及web.xml(用来注册Servlet,最好从别的webapp中拷贝)
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="https://jakarta.ee/xml/ns/jakartaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd" version="6.0" metadata-complete="true"> <servlet> <!--随便起个名--> <servlet-name>abc</servlet-name> <!--全限定名--> <servlet-class>Bluemsun.Hello</servlet-class> </servlet> <servlet-mapping> <!--要与上面一致--> <servlet-name>abc</servlet-name> <!--要以/开头--> <url-pattern>/zdf/</url-pattern> </servlet-mapping> </web-app> -
编写一个Java程序
在此之前! 因为我们需要用到Servlet接口,而JavaSE中不包含Servlet。因为Tomcat服务器实现了Servlet,所以我们可以在Tomcat里找到这个接口——就在servlet-api.jar里,然后我们只需要把它复制到工程项目的External Libraries下就行了
package Bluemsun; import jakarta.servlet.*; import java.io.IOException; public class Hello implements Servlet{ @Override public void init(ServletConfig servletConfig) throws ServletException { } @Override public ServletConfig getServletConfig() { return null; } @Override public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException { System.out.println("HelloServlet"); } @Override public String getServletInfo() { return null; } @Override public void destroy() { } } -
编译这个Java文件,得到Hello.class,再把它与包一起copy到webapp--->WEB-INF-->classes里面去
-
然后我们启动Tomcat,在浏览器中打开 http://localhost:8080/Hello/zdf/ (请求路径 = web.xml的url-pattern + 项目名),就会在终端看到service()方法被调用,如下:
适配器设置模式
为什么需要?
很多情况下,我们实现一个接口,只是想要用到其中的个别方法,可仍然要把全部方法写上,就像上面我们实现Servlet接口,用到的只有service()方法,可仍然需要把五个方法全部写上,不甚美观。而适配器就可以解决这种问题
如何操作?
我们只需要在你要写的类(C)与它要实现的接口(I)中间加入一个Adapter抽象类,这个Adapter要去实现I,其中把你想要在C中使用的方法写成抽象的,再让C继承Adapter,如此一来,C中便只用重写需要用到的方法了,代码变得非常好看。
演示一下
就用上面的Hello来演示一下:
- 首先,我们先写一个HelloAdapter抽象类,把其中再Hello中要用到的service()方法写成抽象的。
- 然后,我们让 Hello 继承 HelloAdapter,类体里就只需要重写service一个方法了
- 最后,让我们把字节码文件复制过去运行一下,一切正常
当然一般我们不用自己写的,用的是写好的GenericServlet
ServletConfig
是什么?
ServletConfig是一个接口,用于获取Servlet的初始化参数。当一个Servlet被容器实例化时,Servlet容器会通过调用Servlet的init(ServletConfig config)方法将ServletConfig对象传递给Servlet。Servlet可以通过这个对象来获取在web.xml文件或注解中配置的初始化参数。
包含的方法
- public String getInitParameter(String name) :根据参数名获取指定的初始化参数值。
- public Enumeration<String> getInitParameterNames() :获取Servlet的所有初始化参数名的枚举对象。
- public ServletContext getServletContext() :获取Servlet所在的ServletContext对象。
- public String getServletName() :获取Servlet的名称。
ServletContext
是什么?
ServletContext是一个接口,代表了Servlet运行在的Web应用程序的上下文。它提供了一种在Servlet和Servlet容器之间共享信息的机制。每个Web应用程序都有一个ServletContext对象,可以通过ServletConfig对象获取。
包含的方法
方法有亿点点多,在这里给出最常用的:
- public String getContextPath() :获取Web应用程序的上下文路径。
- public String getRealPath(String path) :获取指定路径在服务器上的真实路径。
- public RequestDispatcher getRequestDispatcher(String path) :获取用于将请求转发到指定路径的RequestDispatcher对象。
- public Object getAttribute(String name) :获取具有给定名称的上下文范围属性的值。
- public void setAttribute(String name, Object object) :将具有给定名称的对象设置为上下文范围属性。
- public void removeAttribute(String name) :从上下文范围中移除具有给定名称的属性。
应用域对象
当数据满足:
- 是所有用户共享的
- 这个共享的数据量很小
- 这个共享的数据修改操作
这三条条件的时候,使用这个应用域对象,可以大大提高我们程序的运行效率
向应用域中绑定数据,就相当于把数据放到了缓存(cache)中。
HTTP协议
是什么?
- HTTP协议是W3C指定的一种超文本传输协议。
- B(Browser)与S(Server)之间传输数据都需要遵循HTTP协议,这使得B与S互不依赖。
- 包含请求协议与相应协议。
HTTP请求协议(B-->S)
包含四部分:
- 请求行
- 请求头
- 空白行
- 请求体
报文样例
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 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.9
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
分析: 在上面的HTTP请求报文中,我们使用了GET请求方法,请求了名为index.html的资源。请求的HTTP版本为HTTP/1.1,请求头中指定了请求的主机名为 www.example.com 此外,还包含了一些请求头,比如User-Agent、Accept等
HTTP响应协议(S-->B)
也包含四部分
- 状态行
- 响应头
- 空白行
- 响应体
报文样例
HTTP/1.1 200 OK
Date: Fri, 16 Apr 2021 02:55:00 GMT
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/5.4.16
Last-Modified: Tue, 13 Apr 2021 07:15:00 GMT
ETag: "123456-7890-5a2e6c6543210"
Accept-Ranges: bytes
Content-Length: 1234
Content-Type: text/html; charset=UTF-8
<html>
<head>
<title>Welcome to Example.com</title>
</head>
<body>
<h1>Hello, world!</h1>
<p>This is an example page.</p>
</body>
</html>
在上面的HTTP响应报文中,我们让服务器返回了一个HTTP状态码为200的响应,表示请求成功。响应头中包含了一些元数据,比如Date、Server、Last-Modified等。此外,还包含了一个ETag头,用于指定响应的缓存标识符。最后,响应体中包含了一个HTML页面的内容
HttpServlet
是什么?
HttpServlet类是专门为HTTP协议准备的。它是GenericServlet的子类,更加适合HTTP协议下的开发。
包含的方法
- doGet(HttpServletRequest request, HttpServletResponse response) :用于处理HTTP GET请求,通常用于获取资源。
- doPost(HttpServletRequest request, HttpServletResponse response) :用于处理HTTP POST请求,通常用于提交数据。
- doPut(HttpServletRequest request, HttpServletResponse response) :用于处理HTTP PUT请求,通常用于更新资源。
- doDelete(HttpServletRequest request, HttpServletResponse response) :用于处理HTTP DELETE请求,通常用于删除资源。
- init(ServletConfig config) :初始化Servlet,在Servlet第一次被创建时调用,通常用于初始化一些资源。
- destroy() :销毁Servlet,在Servlet被销毁时调用,通常用于释放资源。
- getServletContext() :获取ServletContext对象,该对象提供了访问Web应用程序上下文信息的方法。
- getInitParameter(String name) :获取Servlet初始化参数,通常用于获取一些在web.xml配置文件中的参数。
- getSession() :获取HttpSession对象,用于管理用户的会话信息。
HttpServlet实例
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class MyServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.getWriter().println("<h1>Hello, World!</h1>");
}
}
这个程序实现了在客户端发起HTTP GET请求时返回一个简单的HTML页面,页面上有一个大号的“Hello, World!”字样,效果如下:
HttpServletRequest
是什么?
HttpServletRequest是一个接口,用于表示HTTP请求。它提供了访问HTTP请求信息的方法,例如请求参数、请求头、请求体等等。
包含的方法
以下是HttpServletRequest常用的方法:
- getMethod() :获取HTTP请求的方法(如GET、POST等)。
- getRequestURI():获取HTTP请求的URI(Uniform Resource Identifier),包括查询参数(如果有的话)。
- getParameter(name) :获取HTTP请求中指定名称的参数的值。
- getParameterMap():获取HTTP请求中所有参数的键值对。
- getHeader(name):获取HTTP请求头中指定名称的值。
- getHeaderNames():获取HTTP请求头的名称列表。
- getInputStream():获取HTTP请求的输入流,用于读取请求体中的数据。
- getLocale():获取HTTP请求的语言环境。
- getSession():获取与HTTP请求相关联的会话对象。
请求域对象
- 请求域对象要比应用域对象范围小很多,生命周期短很多。只在一次请求内有效。
请求域与应用域如何选择?
- 选择作用域小的,因为占用资源少。
session机制(会话机制)
是什么?
- 会话就是用户打开浏览器,在浏览器中进行各种操作,最后关闭浏览器,这就是一次会话。
- 一次会话包含多次请求
- 是B/S结构的一部分
- session对象可以保存会话状态
怎么用?
在Java Web开发中,可以通过以下代码来获取和使用Session对象:
// 获取Session对象
HttpSession session = request.getSession();
// 在Session中存储数据
session.setAttribute("key", "value");
// 从Session中获取数据
Object value = session.getAttribute("key");
// 从Session中删除数据
session.removeAttribute("key");
// 使Session失效
session.invalidate();
会话域对象
- 会话域对象存在于一次会话内
- 作用范围:
应用域>会话域>请求域
- 使用原则还是尽量使用作用域小的。
Cookie
是什么?
Cookie是一种存储在客户端的小型文本文件,用于在客户端和服务器之间传递数据
Cookie的特点
- Cookie与Session类似,但Cookie是在客户端存储的,而Session是在服务器端存储的。
- Cookie是由服务器发送给客户端的,客户端会将其存储在本地,以便在以后的请求中将其发送回服务器。
- Cookie可以存储在客户端的硬盘驱动器上(永久),也可以存储在内存中(关闭浏览器则消失),但无论存储在哪里,它都是明文存储的,所以不适合存储敏感信息。
怎么使用?
在Java Web开发中,我们可以通过以下代码来使用Cookie:
// 创建一个Cookie对象
Cookie cookie = new Cookie("name", "value");
// 设置Cookie的过期时间(以秒为单位)
cookie.setMaxAge(3600);
// 将Cookie添加到响应中
response.addCookie(cookie);
// 从请求中获取Cookie
Cookie[] cookies = request.getCookies();
// 遍历Cookie数组并获取Cookie的值
for (Cookie cookie : cookies) {
String name = cookie.getName();
String value = cookie.getValue();
}
MVC
MVC是啥?
MVC是一种软件设计模式,它将应用程序分为三个组成部分:模型(Model)、视图(View)和控制器(Controller)
在Java Web开发中,MVC模式通常被用于设计Web应用程序。例如,可以使用Servlet作为控制器,JSP作为视图,JavaBean作为模型。控制器接收HTTP请求,并将请求参数传递给JavaBean模型,模型根据请求参数进行业务逻辑处理并返回结果,控制器再将结果传递给视图进行呈现。
三个组件
- 模型(Model):模型代表应用程序的数据和业务逻辑。模型负责数据的存储、检索、更新和删除等操作。模型通常是一个独立的组件,可以被多个视图和控制器共享。
- 视图(View):视图代表应用程序的用户界面。视图负责将模型的数据呈现给用户,以及接受用户的输入。视图通常是与具体的平台和UI框架相关的。
- 控制器(Controller):控制器负责协调模型和视图之间的交互。控制器接受用户的输入,并根据用户的请求来操作模型,然后更新视图以反映最新的数据。
特点
在MVC模式中,视图和控制器之间是相互分离的,它们之间的通信是通过模型来进行的。这种分离的设计使得代码更加可维护和可重用,可以更好地适应变化和扩展。
Jar包
Jar包是啥?
JAR(Java Archive)是Java中常用的一种压缩文件格式,它将Java程序的类、资源文件和元数据打包到一个文件中,方便在不同的Java应用程序之间共享和重用代码
何时需要导入Jar包?
在Java开发中,如果需要使用一些第三方库或框架提供的代码,通常需要将这些代码打包成JAR文件,并将其添加到项目的classpath中,以便在程序运行时可以访问到这些类。
在Idea中如何导入并使用Jar包?
- 打开IntelliJ IDEA,选择要导入JAR包的项目。
- 在项目面板中右键点击“External Libraries”,选择“Add as Library”。
- 在弹出的“Choose Libraries”窗口中,选择“Java”选项卡。
- 点击“New Project Library”按钮,输入Library名称,并选择“Java”或“Kotlin”作为Library的语言。
- 在弹出的“New Project Library”窗口中,选择“Java”或“Kotlin”选项卡,然后选择要导入的JAR包文件。
- 点击“OK”按钮,完成导入。
在使用JAR包的时候,可以在代码中使用import + 全限定名来导入JAR包中的类
总结
- Servlet 是 Java EE(现在叫 Jakarta EE)规范中的一部分,用于处理 HTTP 请求和响应。
- Servlet 通常运行在 Web 容器中,如 Tomcat、Jetty、WebSphere 等。
- Servlet 生命周期包括初始化、服务和销毁阶段。
- Servlet 使用 ServletConfig 和 ServletContext 对象来获取配置
-
- Servlet 可以处理各种 HTTP 方法,如 GET、POST、PUT、DELETE 等。
- Servlet 可以通过 request 对象获取客户端发送的请求参数、请求头、Cookie 等信息。
- Servlet 可以使用 response 对象设置响应的状态码、响应头、Cookie、重定向等。
- Servlet 可以使用 session 对象在多个请求之间共享数据,如用户身份验证信息、购物车数据等。
- Servlet 可以使用 JSP(JavaServer Pages)或其他模板引擎来生成 HTML、XML 等内容,从而将业务逻辑和显示逻辑分离开来。
- Servlet 可以使用注解或 XML 配置来定义 URL 映射和其他配置信息。
- Servlet 容器可以自动重载 Servlet 类和配置,从而实现动态部署和更新。