目录
6. ServletConfig和ServletContext
1. Servlet简介
1.1 动态资源和静态资源
动态资源与静态资源是Web开发中常用的两种资源类型。
静态资源
指在服务器上保存的固定文件,如HTML、CSS、JavaScript、图片等。这些文件内容不会随用户请求的变化而变化,服务器只需将文件返回给客户端即可。静态资源可以直接通过URL进行访问,客户端每次请求静态资源时,服务器只需返回相应的文件内容即可。
动态资源
指根据用户请求的不同,服务器动态生成的内容,通常是一些经过处理的数据或页面。动态资源的生成过程需要依赖服务器端的程序处理,并根据用户请求来动态地生成响应结果,最终返回给客户端。常见的动态资源包括动态网页、动态图片、动态数据等。
区别:
- 静态资源不依赖服务器端的程序处理,直接返回给客户端,而动态资源需要经过服务器端程序的处理才能生成并返回给客户端。
- 静态资源的内容固定,不会随用户请求的变化而变化,而动态资源的内容是根据用户请求来动态生成的。
1.2 Servlet简介
Servlet (server applet) 是运行在服务端(tomcat)的Java小程序,是sun公司提供一套定义动态资源规范; 从代码层面上来讲Servlet就是一个接口
-
用来接收、处理客户端请求、响应给浏览器的动态资源。在整个Web应用中,Servlet主要负责接收处理请求、协同调度功能以及响应数据。我们可以把Servlet称为Web应用中的控制器
-
不是所有的JAVA类都能用于处理客户端请求,能处理客户端请求并做出响应的一套技术标准就是Servlet
-
Servlet是运行在服务端的,所以 Servlet必须在WEB项目中开发且在Tomcat这样的服务容器中运行
Servlet的主要作用包括:
- 接收和解析客户端发起的HTTP请求。
- 处理请求,包括获取请求参数、验证用户身份、调用业务逻辑等。
- 生成响应结果,包括设置响应头、写入响应内容等。
- 将响应结果发送给客户端。
相比于其他技术(如CGI、PHP等),Servlet具有以下优势:
- 跨平台性:Servlet基于Java语言,可以在不同的操作系统上运行,具备很好的跨平台性。
- 高性能:Servlet在Web容器中运行,与服务器进行直接交互,处理效率高。
- 可复用性:Servlet可以被多个Web应用共享,提高代码的复用性。
- 扩展性:Servlet API提供了丰富的功能和扩展点,可以方便地进行功能扩展和定制。
Servlet与静态资源的对比
Servlet与静态资源在使用上有一些区别和不同的应用场景。
Servlet主要用于处理动态内容的生成和业务逻辑的处理,它可以根据用户请求的不同动态生成响应结果,并可以与数据库、其他服务等进行交互。Servlet通常通过URL映射的方式来处理特定的请求路径。
静态资源则是用于存储和展示固定的文件内容,例如HTML、CSS、JavaScript和图片等。静态资源可以直接通过URL访问,服务器只需将相应的文件返回给客户端即可。
在实际开发中,通常会将动态资源与静态资源分开管理,以提高系统的性能和可维护性。静态资源可以由Web服务器(如Nginx、Apache)直接处理和缓存,而动态资源则交给Servlet容器(如Tomcat、Jetty)进行处理。
2. Servlet开发流程
Servlet是Java Web开发的核心组件之一,掌握Servlet的开发流程对于开发基于Java EE的Web应用至关重要。接下来,我们将详细介绍Servlet的基本开发流程,包括创建Servlet类、配置Servlet和编写业务逻辑。
2.1 开发Servlet的基本流程
2.1.1 创建Servlet类
1. 新建一个Java类:
- 打开你的IDE(如Eclipse、IntelliJ IDEA),并创建一个新的Java类。
- 该类需要继承
javax.servlet.http.HttpServlet
类,以便成为一个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 MyServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 处理GET请求
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 处理POST请求
}
}
2. 重写doGet
和doPost
方法:
- 通常我们会重写
doGet
和doPost
方法来分别处理GET和POST请求。 - 这两个方法接收
HttpServletRequest
和HttpServletResponse
对象,分别代表客户端请求和服务器响应。
2.1.2 配置Servlet
1. 在web.xml中配置Servlet:
- 在
WEB-INF
目录下的web.xml
文件中配置Servlet的映射路径,使得特定的URL可以被该Servlet处理。
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.example.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/myServlet</url-pattern>
</servlet-mapping>
2. 使用注解配置Servlet:
- Java EE 6引入了注解,可以通过在Servlet类上使用
@WebServlet
注解来配置Servlet。
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
@WebServlet("/myServlet")
public class MyServlet extends HttpServlet {
// ...
}
2.1.3 编写业务逻辑
1. 处理请求参数
- 使用
HttpServletRequest
对象的方法来获取请求参数。常用的方法有getParameter(String name)
、getParameterValues(String name)
等。
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String param = request.getParameter("paramName");
// 业务逻辑处理
}
2. 生成响应结果
- 使用
HttpServletResponse
对象的方法来生成响应结果。可以设置响应内容类型、状态码,并通过PrintWriter
对象写入响应内容。
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html><body>");
out.println("<h1>Hello, Servlet!</h1>");
out.println("</body></html>");
}
3. 处理业务逻辑
- 根据需求,在
doGet
或doPost
方法中编写具体的业务逻辑,如数据库操作、调用服务等。
2.2 目标:掌握Servlet开发流程
掌握Servlet的开发流程不仅仅是理解其基本步骤,更重要的是能够灵活运用这些步骤来开发功能丰富、性能良好的Web应用。以下是一些关键点:
-
理解Servlet生命周期:
掌握Servlet的生命周期,即初始化(init
)、处理请求(service
)、销毁(destroy
)的过程,对资源管理和性能优化至关重要。 -
熟悉常用API:
熟练掌握HttpServletRequest
和HttpServletResponse
对象的方法和用途,是高效开发Servlet的重要基础。 -
合理配置和管理Servlet:
能够灵活使用XML配置和注解配置来管理Servlet,理解不同配置方式的优势和适用场景。 -
编写和维护业务逻辑:
能够编写清晰、可维护的业务逻辑代码,理解MVC架构的基本思想和其在Servlet开发中的应用。 -
安全性和性能优化:
了解和应用Servlet开发中的安全性和性能优化技巧,如防止SQL注入、XSS攻击,提高响应速度等。
3. Servlet注解方式配置
Servlet注解配置是Java EE 6引入的一种简化配置方式,使得开发者可以在不编辑web.xml
文件的情况下完成Servlet的配置。通过使用注解,开发人员能够更直观、简洁地定义Servlet及其映射路径。
3.1 @WebServlet注解源码
官方JAVAEEAPI文档下载地址
-
@WebServlet注解的源码阅读
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @since Servlet 3.0
*/
@Target({ ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface WebServlet {
/**
* The name of the servlet
* 相当于 servlet-name
* @return the name of the servlet
*/
String name() default "";
/**
* The URL patterns of the servlet
* 如果只配置一个url-pattern ,则通过该属性即可,和urlPatterns属性互斥
* @return the URL patterns of the servlet
*/
String[] value() default {};
/**
* The URL patterns of the servlet
* 如果要配置多个url-pattern ,需要通过该属性,和value属性互斥
* @return the URL patterns of the servlet
*/
String[] urlPatterns() default {};
/**
* The load-on-startup order of the servlet
* 配置Servlet是否在项目加载时实例化
* @return the load-on-startup order of the servlet
*/
int loadOnStartup() default -1;
/**
* The init parameters of the servlet
* 配置初始化参数
* @return the init parameters of the servlet
*/
WebInitParam[] initParams() default {};
/**
* Declares whether the servlet supports asynchronous operation mode.
*
* @return {@code true} if the servlet supports asynchronous operation mode
* @see jakarta.servlet.ServletRequest#startAsync
* @see jakarta.servlet.ServletRequest#startAsync( jakarta.servlet.ServletRequest,jakarta.servlet.ServletResponse)
*/
boolean asyncSupported() default false;
/**
* The small-icon of the servlet
*
* @return the small-icon of the servlet
*/
String smallIcon() default "";
/**
* The large-icon of the servlet
*
* @return the large-icon of the servlet
*/
String largeIcon() default "";
/**
* The description of the servlet
*
* @return the description of the servlet
*/
String description() default "";
/**
* The display name of the servlet
*
* @return the display name of the servlet
*/
String displayName() default "";
}
3.2 @WebServlet注解的源码解析
注解的定义
@WebServlet
注解是Java EE提供的一个元数据注解,用于标记一个类为Servlet并定义该Servlet的映射信息。下面是@WebServlet
注解的定义:
@Target(TYPE) // 表示该注解用于类、接口(包括注解类型)或枚举声明
@Retention(RUNTIME) // 表示该注解将在运行时可用
@Documented // 表示该注解将包含在Javadoc中
public @interface WebServlet {
String name() default ""; // Servlet的名称,默认为空字符串
String[] value() default {}; // Servlet的URL映射路径,默认为空数组
String[] urlPatterns() default {}; // Servlet的URL映射路径,与value属性等价
int loadOnStartup() default -1; // Servlet的加载顺序,默认为不指定
WebInitParam[] initParams() default {}; // 初始化参数
boolean asyncSupported() default false; // 是否支持异步操作
String smallIcon() default ""; // 小图标
String largeIcon() default ""; // 大图标
String description() default ""; // Servlet的描述
String displayName() default ""; // Servlet的显示名
}
注解的属性与方法
name
:指定Servlet的名称。如果不设置,将使用默认的类名。value
:定义Servlet的URL映射路径。此属性是一个快捷方式,与urlPatterns
功能相同。urlPatterns
:定义Servlet的URL映射路径,可以同时指定多个路径。loadOnStartup
:指定Servlet的加载顺序。负值表示延迟加载,非负值表示Servlet应该在容器启动时加载,并按指定顺序初始化。initParams
:定义Servlet的初始化参数,通过一个WebInitParam
数组来设置。asyncSupported
:指示Servlet是否支持异步处理。默认为false
。smallIcon
和largeIcon
:分别定义小图标和大图标的路径,用于描述Servlet的图标。description
:对Servlet进行描述。displayName
:指定Servlet的显示名。
3.3 @WebServlet注解的使用示例
基本用法
以下是一个基本使用@WebServlet
注解的示例,展示如何定义一个简单的Servlet并映射到特定的URL模式:
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.getWriter().println("<h1>Hello, World!</h1>");
}
}
在这个示例中:
@WebServlet("/hello")
:定义了该Servlet映射到/hello
路径。doGet
方法:处理GET请求并生成响应内容。
参数配置
下面是一个更复杂的示例,展示如何使用更多的注解属性,包括初始化参数、异步支持等。
import javax.servlet.ServletException;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebServlet(
name = "AdvancedServlet",
urlPatterns = {"/advanced", "/complex"},
loadOnStartup = 1,
initParams = {
@WebInitParam(name = "param1", value = "value1"),
@WebInitParam(name = "param2", value = "value2")
},
asyncSupported = true,
description = "An advanced servlet with multiple configurations",
displayName = "AdvancedServlet"
)
public class AdvancedServlet extends HttpServlet {
@Override
public void init() throws ServletException {
super.init();
String param1 = getServletConfig().getInitParameter("param1");
String param2 = getServletConfig().getInitParameter("param2");
// 使用初始化参数
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
response.getWriter().println("<h1>Advanced Servlet</h1>");
response.getWriter().println("<p>Param1: " + getServletConfig().getInitParameter("param1") + "</p>");
response.getWriter().println("<p>Param2: " + getServletConfig().getInitParameter("param2") + "</p>");
}
}
在这个示例中:
name
:指定Servlet的名称为“AdvancedServlet”。urlPatterns
:定义了多个URL映射路径/advanced
和/complex
。loadOnStartup
:设置加载顺序为1(在应用启动时加载)。initParams
:定义了两个初始化参数param1
和param2
。asyncSupported
:启用异步支持。description
:描述Servlet。displayName
:定义Servlet的显示
4. Servlet生命周期
Servlet的生命周期是指从它被创建到被销毁的全过程。理解Servlet生命周期有助于开发者优化性能、管理资源和处理请求。
4.1 生命周期概述
什么是Servlet的生命周期
-
应用程序中的对象不仅在空间上有层次结构的关系,在时间上也会因为处于程序运行过程中的不同阶段而表现出不同状态和不同行为——这就是对象的生命周期。
-
简单的叙述生命周期,就是对象在容器中从开始创建到销毁的过程。
Servlet的生命周期主要包含三个阶段:初始化阶段、请求处理阶段和销毁阶段。
4.1.1 初始化阶段
在Servlet第一次被请求时(或者在web应用启动时,如果配置了加载顺序),Web容器会执行以下步骤进行Servlet的初始化:
-
实例化Servlet对象:
Web容器会创建Servlet类的实例。这通常是在Servlet第一次被访问时自动进行的,但也可以配置为在服务器启动时加载(通过<load-on-startup>
元素)。 -
调用
实例化后,容器会调用Servlet的init
方法:init
方法进行初始化。这个方法只会被调用一次,可以在这里执行一些启动操作,如资源分配或读取配置文件。
@Override
public void init() throws ServletException {
// 初始化代码,例如数据库连接初始化
System.out.println("Servlet is being initialized");
}
4.1.2 请求处理阶段
当Servlet被初始化后,每次客户端发送请求时,Servlet会进入请求处理阶段,执行以下步骤:
1. 调用service方法
每次请求,容器都会调用Servlet的service
方法。该方法根据请求类型(GET、POST等)调用相应的doGet
、doPost
等方法。
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 处理GET请求
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 处理POST请求
}
2. 处理请求与生成响应:
在doGet
、doPost
等方法中,开发者编写业务逻辑代码来处理请求,并生成响应返回给客户端。
4.1.3 销毁阶段
当Servlet被卸载或服务器关闭时,Servlet会进入销毁阶段:
1. 调用destory方法:
容器会在Servlet实例被销毁前调用destroy
方法。开发者可以在这个方法中进行清理工作,如释放资源、关闭数据库连接等。
@Override
public void destroy() {
// 清理代码,例如关闭数据库连接
System.out.println("Servlet is being destroyed");
}
2. 垃圾回收:
destroy
方法执行完毕后,Servlet实例会被垃圾回收。
4.2 生命周期测试
对Servlet生命周期的理解不仅停留在理论上,更需要通过实践和测试来深入掌握。
4.2.1 生命周期事件的监听与处理
可以使用Servlet API提供的监听器接口来监听和处理不同生命周期事件,常见的有:
1. ServletContextListener:
监听ServletContext的生命周期事件,适合进行全局资源的初始化和销毁。
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MyContextListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// 全局初始化代码
System.out.println("Context Initialized");
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// 全局清理代码
System.out.println("Context Destroyed");
}
}
2. HttpSessionListener:
监听HttpSession的创建和销毁事件,适合进行会话级资源管理。
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionListener;
import javax.servlet.annotation.WebListener;
@WebListener
public class MySessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
// 会话创建时的操作
System.out.println("Session Created");
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
// 会话销毁时的操作
System.out.println("Session Destroyed");
}
}
4.2.2 实际场景下的应用
-
资源初始化与释放:
在init
方法中进行数据库连接池的初始化,在destroy
方法中关闭数据库连接池。 -
日志记录:
在每个生命周期方法中记录日志,以便在开发和调试过程中了解Servlet的运行状态。
public class MyServlet extends HttpServlet {
private static final Logger logger = Logger.getLogger(MyServlet.class.getName());
@Override
public void init() throws ServletException {
logger.info("Servlet initialized");
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
logger.info("Handling GET request");
response.getWriter().write("Hello, Servlet!");
}
@Override
public void destroy() {
logger.info("Servlet destroyed");
}
}
4.3 生命周期总结
-
通过生命周期测试我们发现Servlet对象在容器中是单例的
-
容器是可以处理并发的用户请求的,每个请求在容器中都会开启一个线程
-
多个线程可能会使用相同的Servlet对象,所以在Servlet中,我们不要轻易定义一些容易经常发生修改的成员变量
-
load-on-startup中定义的正整数表示实例化顺序,如果数字重复了,容器会自行解决实例化顺序问题,但是应该避免重复
-
Tomcat容器中,已经定义了一些随系统启动实例化的servlet,我们自定义的servlet的load-on-startup尽量不要占用数字1-5
5. Servlet继承接口
5.1 Servlet接口与抽象类的比较
Servlet接口
javax.servlet.Servlet
接口是所有Servlet类的父接口,它定义了Servlet的生命周期方法和基本行为。开发者需要实现这个接口并重写其中的方法来创建自定义的Servlet类。
public interface Servlet {
void init(ServletConfig config) throws ServletException;
void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
void destroy();
String getServletInfo();
ServletConfig getServletConfig();
}
GenericServlet抽象类
javax.servlet.GenericServlet
是实现了Servlet
接口的抽象类,它简化了实现Servlet接口所需的工作。开发者可以直接继承这个抽象类,并重写其中的service
方法来处理请求。
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
// 其他方法和属性省略
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// 处理请求的具体逻辑
}
}
HttpServlet抽象类
javax.servlet.http.HttpServlet
是实现了GenericServlet
抽象类的子类,专门用于处理HTTP请求。它提供了对HTTP方法(如GET、POST)的直接支持,以及对HTTP头部信息的访问。
5.2 GenericServlet抽象类详解
GenericServlet抽象类提供了对Servlet接口的基本实现,开发者可以继承这个抽象类来编写自定义的Servlet类。
源码分析
以下是GenericServlet
抽象类的一部分源码,展示了它的基本结构和service
方法的默认实现:
public abstract class GenericServlet implements Servlet, ServletConfig, Serializable {
// 省略其他属性和方法
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// 默认的请求处理逻辑
}
// 省略其他方法
}
使用示例
以下是一个简单的示例,演示了如何继承GenericServlet
抽象类并实现自定义的Servlet类:
import javax.servlet.*;
import java.io.IOException;
public class MyServlet extends GenericServlet {
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
// 自定义的请求处理逻辑
}
}
5.3 HttpServlet抽象类
HttpServlet抽象类是GenericServlet
的子类,专门用于处理HTTP请求,提供了对HTTP方法和头部信息的直接支持。
源码分析
以下是HttpServlet
抽象类的一部分源码,展示了它对HTTP方法的处理和doGet
、doPost
等方法的默认实现:
public abstract class HttpServlet extends GenericServlet {
// 省略其他属性和方法
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
// 默认的GET请求处理逻辑
}
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
// 默认的POST请求处理逻辑
}
// 省略其他方法
}
使用示例
以下是一个简单的示例,演示了如何继承HttpServlet
抽象类并实现自定义的Servlet类:
import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
public class MyHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
// 自定义的GET请求处理逻辑
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
// 自定义的POST请求处理逻辑
}
}
5.4 自定义Servlet类的步骤与技巧
-
选择合适的抽象类:
如果要处理通用的Servlet请求,可以选择继承GenericServlet
抽象类;如果要处理HTTP请求,可以选择继承HttpServlet
抽象类。 -
重写关键方法:
在自定义的Servlet类中,重写service
方法(如果继承GenericServlet
)或者重写doGet
、doPost
等方法(如果继承HttpServlet
),实现具体的请求处理逻辑。 -
使用Servlet API提供的功能:
在自定义Servlet中,可以利用Servlet API提供的功能,如获取请求参数、设置响应头、重定向等,来实现丰富的业务逻辑。 -
遵循规范和最佳实践:
在编写自定义Servlet时,要遵循Servlet规范和最佳实践,确保代码健壮、可维护和安全。
6. ServletConfig和ServletContext
在Servlet开发中,ServletConfig
和ServletContext
是两个非常重要的接口,它们用于配置和管理Servlet的运行环境。本节将详细介绍这两个接口的使用与配置方法,并探讨它们在实践中的应用场景。
6.1 ServletConfig的使用与配置
ServletConfig
接口提供了Servlet的配置信息,用于传递初始化参数,并且可以获取Servlet的上下文信息。每个Servlet都有一个对应的ServletConfig
对象,由Servlet容器创建并传递给Servlet。
初始化参数的获取与使用
1. 配置初始化参数: 初始化参数在web.xml文件中定义,可以为每个Servlet指定不同的初始化参数。以下是一个示例:
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>com.example.MyServlet</servlet-class>
<init-param>
<param-name>param1</param-name>
<param-value>value1</param-value>
</init-param>
<init-param>
<param-name>param2</param-name>
<param-value>value2</param-value>
</init-param>
</servlet>
2.获取初始化参数: 在Servlet类中,可以通过ServletConfig
对象获取初始化参数:
public class MyServlet extends HttpServlet {
private String param1;
private String param2;
@Override
public void init(ServletConfig config) throws ServletException {
super.init(config);
param1 = config.getInitParameter("param1");
param2 = config.getInitParameter("param2");
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
res.getWriter().write("Param1: " + param1 + ", Param2: " + param2);
}
}
在上述代码中,init
方法被重写以获取并存储初始化参数。然后,这些参数可以在Servlet的其他方法中使用。
6.2 ServletContext的使用详解
ServletContext
接口提供了一个Servlet与其运行环境之间的接口,用于共享数据、资源管理以及与Servlet容器的交互。它在整个Web应用程序范围内是唯一的,生命周期从Web应用程序启动到停止。
ServletContext的作用范围与生命周期
-
作用范围:
ServletContext
对象在一个Web应用程序中是全局共享的,因此可以用来在多个Servlet之间共享数据。例如,应用程序的配置信息、共享的资源(如数据库连接池)等。 -
生命周期:
ServletContext
的生命周期与Web应用程序的生命周期一致。当Web应用程序启动时,Servlet容器会创建ServletContext
对象;当Web应用程序停止时,ServletContext
对象也会被销毁。
共享数据与资源管理
1. 共享数据: 可以使用ServletContext
对象在多个Servlet之间共享数据。例如,将数据存储在ServletContext
的属性中:
// 存储数据
getServletContext().setAttribute("sharedData", "someValue");
// 获取数据
String sharedData = (String) getServletContext().getAttribute("sharedData");
2. 资源管理: ServletContext
可以用来管理和访问Web应用程序中的资源,如读取配置文件或其他静态资源:
InputStream inputStream = getServletContext().getResourceAsStream("/WEB-INF/config.properties");
Properties properties = new Properties();
properties.load(inputStream);
6.3 ServletContext的其他重要API
ServletContext
提供了许多重要的API,用于更高级的Web应用程序管理和配置。这些API包括Listener和Filter的配置和使用。
Listener与Filter的配置与使用
1. Listener配置: Listener用于监听Web应用程序的事件,如启动、销毁、会话创建和销毁等。以下是在web.xml中配置一个监听器的示例:
<listener>
<listener-class>com.example.MyListener</listener-class>
</listener>
在Java代码中,实现ServletContextListener
接口:
public class MyListener implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
// Web应用程序启动时执行的逻辑
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
// Web应用程序停止时执行的逻辑
}
}
2. Filter配置: Filter用于拦截请求和响应,并在Servlet处理之前或之后对其进行修改。以下是在web.xml中配置一个过滤器的示例:
<filter>
<filter-name>MyFilter</filter-name>
<filter-class>com.example.MyFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>MyFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
在Java代码中,实现Filter
接口:
public class MyFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
// 过滤器初始化逻辑
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
// 请求处理前的逻辑
chain.doFilter(request, response); // 调用下一个过滤器或目标Servlet
// 响应处理后的逻辑
}
@Override
public void destroy() {
// 过滤器销毁逻辑
}
}
7. HttpServletRequest
7.1 HttpServletRequest简介
HttpServletRequest是什么
-
HttpServletRequest是一个接口,其父接口是ServletRequest
-
HttpServletRequest是Tomcat将请求报文转换封装而来的对象,在Tomcat调用service方法时传入
-
HttpServletRequest代表客户端发来的请求,所有请求中的信息都可以通过该对象获得
7.2 HttpServletRequest常见API
HttpServletRequest怎么用
-
获取请求行信息相关(方式,请求的url,协议及版本)
API | 功能解释 |
---|---|
StringBuffer getRequestURL(); | 获取客户端请求的url |
String getRequestURI(); | 获取客户端请求项目中的具体资源 |
int getServerPort(); | 获取客户端发送请求时的端口 |
int getLocalPort(); | 获取本应用在所在容器的端口 |
int getRemotePort(); | 获取客户端程序的端口 |
String getScheme(); | 获取请求协议 |
String getProtocol(); | 获取请求协议及版本号 |
String getMethod(); | 获取请求方式 |
-
获得请求头信息相关
API | 功能解释 |
---|---|
String getHeader(String headerName); | 根据头名称获取请求头 |
Enumeration<String> getHeaderNames(); | 获取所有的请求头名字 |
String getContentType(); | 获取content-type请求头 |
-
获得请求参数相关
API | 功能解释 |
---|---|
String getParameter(String parameterName); | 根据请求参数名获取请求单个参数值 |
String[] getParameterValues(String parameterName); | 根据请求参数名获取请求多个参数值数组 |
Enumeration<String> getParameterNames(); | 获取所有请求参数名 |
Map<String, String[]> getParameterMap(); | 获取所有请求参数的键值对集合 |
BufferedReader getReader() throws IOException; | 获取读取请求体的字符输入流 |
ServletInputStream getInputStream() throws IOException; | 获取读取请求体的字节输入流 |
int getContentLength(); | 获得请求体长度的字节数 |
-
其他API
API | 功能解释 |
---|---|
String getServletPath(); | 获取请求的Servlet的映射路径 |
ServletContext getServletContext(); | 获取ServletContext对象 |
Cookie[] getCookies(); | 获取请求中的所有cookie |
HttpSession getSession(); | 获取Session对象 |
void setCharacterEncoding(String encoding) ; | 设置请求体字符集 |
8. HttpServletResponse
8.1 HttpServletResponse简介
HttpServletResponse是什么
-
HttpServletResponse是一个接口,其父接口是ServletResponse
-
HttpServletResponse是Tomcat预先创建的,在Tomcat调用service方法时传入
-
HttpServletResponse代表对客户端的响应,该对象会被转换成响应的报文发送给客户端,通过该对象我们可以设置响应信息
8.2 HttpServletResponse的常见API
HttpServletRequest怎么用
-
设置响应行相关
API | 功能解释 |
---|---|
void setStatus(int code); | 设置响应状态码 |
-
设置响应头相关
API | 功能解释 |
---|---|
void setHeader(String headerName, String headerValue); | 设置/修改响应头键值对 |
void setContentType(String contentType); | 设置content-type响应头及响应字符集(设置MIME类型) |
-
设置响应体相关
API | 功能解释 |
---|---|
PrintWriter getWriter() throws IOException; | 获得向响应体放入信息的字符输出流 |
ServletOutputStream getOutputStream() throws IOException; | 获得向响应体放入信息的字节输出流 |
void setContentLength(int length); | 设置响应体的字节长度,其实就是在设置content-length响应头 |
-
其他API
API | 功能解释 |
---|---|
void sendError(int code, String message) throws IOException; | 向客户端响应错误信息的方法,需要指定响应码和响应信息 |
void addCookie(Cookie cookie); | 向响应体中增加cookie |
void setCharacterEncoding(String encoding); | 设置响应体字符集 |
MIME类型
-
MIME类型,可以理解为文档类型,用户表示传递的数据是属于什么类型的文档
-
浏览器可以根据MIME类型决定该用什么样的方式解析接收到的响应体数据
-
可以这样理解: 前后端交互数据时,告诉对方发给对方的是 html/css/js/图片/声音/视频/... ...
-
tomcat/conf/web.xml中配置了常见文件的拓展名和MIMIE类型的对应关系
-
常见的MIME类型举例如下
文件拓展名 | MIME类型 |
---|---|
.html | text/html |
.css | text/css |
.js | application/javascript |
.png /.jpeg/.jpg/... ... | image/jpeg |
.mp3/.mpe/.mpeg/ ... ... | audio/mpeg |
.mp4 | video/mp4 |
.m1v/.m1v/.m2v/.mpe/... ... | video/mpeg |
9. 请求转发和响应重定向
9.1 请求转发与响应重定向概述
在Web开发中,请求转发和响应重定向是两种常用的页面跳转技术,它们在实现页面间的导航和数据传递时起着重要作用。
-
请求转发:请求转发是指服务器接收到客户端的请求后,将请求转发给另一个资源进行处理,并将结果返回给客户端。在请求转发过程中,浏览器只发起了一次请求,客户端感知不到服务器进行了转发操作。
-
响应重定向:响应重定向是指服务器接收到客户端的请求后,向客户端发送一个特殊的响应码和新的URL,客户端收到响应后会重新发送请求到新的URL地址。因此,响应重定向会导致浏览器发起两次请求。
9.2 请求转发的实现与用例
转发路径的配置与实现方式:
- 在Servlet中,请求转发通过
RequestDispatcher
接口实现,可以从当前Servlet上下文获取到RequestDispatcher
对象,然后调用其forward()
方法实现转发。
// 获取RequestDispatcher对象
RequestDispatcher dispatcher = request.getRequestDispatcher("/targetServlet");
// 执行转发
dispatcher.forward(request, response);
应用场景:
- 某个Servlet处理完请求后,需要将请求转发给另一个Servlet进行进一步处理。
- 实现页面的模块化设计,将不同功能模块拆分成多个Servlet,通过请求转发实现页面的动态拼装。
9.3 响应重定向的实现与用例
重定向URL的构建与跳转方式:
- 在Servlet中,响应重定向通过设置
response
对象的sendRedirect()
方法实现,指定重定向的URL地址。
response.sendRedirect("/newPage.jsp");
应用场景:
- 当处理完请求后,需要将用户重定向到另一个页面或站点。
- 处理表单提交后,为避免表单重复提交而使用重定向。
通过请求转发和响应重定向,开发者可以灵活地控制页面跳转和数据传递,实现更加丰富和动态的Web应用程序。在实际开发中,根据具体需求选择合适的跳转方式可以提高用户体验和系统性能。