JAVA学习(四)

374 阅读14分钟

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"

image.png

出现了如下窗口则代表运行成功

image.png

Tomcat 成功启动后,可以通过在浏览器地址栏输入 http://localhost:8080/  访问 Tomcat 中的默认应用程序。如果一切顺利,那么会显示以下结果:

image.png 在 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 生命周期方案(网上找的)

Servlet-LifeCycle.jpg

这个图片显示了 init()destroy() 方法只会被调用一次,而 service() 方法会随来自浏览器的请求而被调用多次

写一个servlet实例

  1. 在CATALINE_HOME下找到webapps

  2. 在webapps下创建一个文件夹,名字就是webapp的名字,这个文件夹就是webapp的根目录 image.png

  3. 在根目录下新建一个名为WEB-INF的文件夹(必须大写)

  4. 在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>
    
  5. 编写一个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() {  
    
            }  
        }
    
  6. 编译这个Java文件,得到Hello.class,再把它与包一起copy到webapp--->WEB-INF-->classes里面去

  7. 然后我们启动Tomcat,在浏览器中打开 http://localhost:8080/Hello/zdf/ (请求路径 = web.xml的url-pattern + 项目名),就会在终端看到service()方法被调用,如下:

    image.png

适配器设置模式

为什么需要?

很多情况下,我们实现一个接口,只是想要用到其中的个别方法,可仍然要把全部方法写上,就像上面我们实现Servlet接口,用到的只有service()方法,可仍然需要把五个方法全部写上,不甚美观。而适配器就可以解决这种问题

如何操作?

我们只需要在你要写的类(C)与它要实现的接口(I)中间加入一个Adapter抽象类,这个Adapter要去实现I,其中把你想要在C中使用的方法写成抽象的,再让C继承Adapter,如此一来,C中便只用重写需要用到的方法了,代码变得非常好看。

演示一下

就用上面的Hello来演示一下:

  • 首先,我们先写一个HelloAdapter抽象类,把其中再Hello中要用到的service()方法写成抽象的。

image.png

  • 然后,我们让 Hello 继承 HelloAdapter,类体里就只需要重写service一个方法了

image.png

  • 最后,让我们把字节码文件复制过去运行一下,一切正常

image.png

当然一般我们不用自己写的,用的是写好的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!”字样,效果如下:

image.png

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包?

  1. 打开IntelliJ IDEA,选择要导入JAR包的项目。
  2. 在项目面板中右键点击“External Libraries”,选择“Add as Library”。
  3. 在弹出的“Choose Libraries”窗口中,选择“Java”选项卡。
  4. 点击“New Project Library”按钮,输入Library名称,并选择“Java”或“Kotlin”作为Library的语言。
  5. 在弹出的“New Project Library”窗口中,选择“Java”或“Kotlin”选项卡,然后选择要导入的JAR包文件。
  6. 点击“OK”按钮,完成导入。

在使用JAR包的时候,可以在代码中使用import + 全限定名来导入JAR包中的类

总结

  1. Servlet 是 Java EE(现在叫 Jakarta EE)规范中的一部分,用于处理 HTTP 请求和响应。
  2. Servlet 通常运行在 Web 容器中,如 Tomcat、Jetty、WebSphere 等。
  3. Servlet 生命周期包括初始化、服务和销毁阶段。
  4. Servlet 使用 ServletConfig 和 ServletContext 对象来获取配置
    1. Servlet 可以处理各种 HTTP 方法,如 GET、POST、PUT、DELETE 等。
  5. Servlet 可以通过 request 对象获取客户端发送的请求参数、请求头、Cookie 等信息。
  6. Servlet 可以使用 response 对象设置响应的状态码、响应头、Cookie、重定向等。
  7. Servlet 可以使用 session 对象在多个请求之间共享数据,如用户身份验证信息、购物车数据等。
  8. Servlet 可以使用 JSP(JavaServer Pages)或其他模板引擎来生成 HTML、XML 等内容,从而将业务逻辑和显示逻辑分离开来。
  9. Servlet 可以使用注解或 XML 配置来定义 URL 映射和其他配置信息。
  10. Servlet 容器可以自动重载 Servlet 类和配置,从而实现动态部署和更新。