目录
一、介绍
Servlet(Java Servlet的简称),是用Java编写的服务器端程序,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
Servlet是Java语言实现的一个接口,通常我们说的Servlet是该接口的实现类(如HttpServlet)。Servlet运行于支持Java的应用服务器中。从原理上讲,Servlet可以响应任何类型的请求,但绝大多数情况下Servlet只用来扩展基于HTTP协议的Web服务器,它具有独立于平台和协议的特性。
二、Servlet生命周期
1. Servlet的生命周期包括加载、实例化、服务、销毁四个阶段。
2. init方法在服务器装入Servlet时执行一次,负责初始化Servlet对象。
3. service方法(Servlet的核心),负责响应客户的请求。每当一个客户请求一个HttpServlet对象时,service方法会被调用,并传递一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。
4. destroy方法在服务器停止且卸载Servlet时执行一次,负责释放占用的资源。
5. Servlet与Servlet容器的交互:Servlet容器(如Tomcat)负责监听端口,接收客户端的请求,并根据URL等信息确定将请求交给哪个Servlet处理。Tomcat创建HttpRequest和HttpResponse对象,调用Servlet的service()方法,并将请求和响应对象作为参数传递。Servlet处理请求后,Tomcat将响应结果返回给客户端。Servlet的原理涉及到一个规范化的接口定义、明确的方法实现以及与容器之间的协作机制,使得Java Web应用程序能够处理客户端的请求并返回响应。
三、 Servlet实践
我们通过Maven和Tomcat服务器构建一个简单的Servet程序来演示下效果。Maven和Tomcat的安装不做赘述。
3.1. HelloServlet代码
package com.example.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("你好呀世界");
PrintWriter writer = response.getWriter();
writer.print("Hello, Servlet");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
3.2. Error代码
package com.example.servlet;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.annotation.*;
import java.io.IOException;
import java.io.PrintWriter;
@WebServlet(name = "ErrorServlet", value = "/ErrorServlet")
public class ErrorServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("application/json;charset=utf-8");
PrintWriter writer = response.getWriter();
writer.print("<H1>系统忙碌中</H1>");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
}
3.3. 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">
<display-name>Archetype Created Web Application</display-name>
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.example.servlet.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>error</servlet-name>
<servlet-class>com.example.servlet.ErrorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>error</servlet-name>
<url-pattern>/error</url-pattern>
</servlet-mapping>
</web-app>
3.4. 父pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>Javaweb</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>servlet02</module>
</modules>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<!-- Servlet API -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
</dependency>
<!-- Servlet JSP API -->
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
</dependency>
<!-- 其他依赖 -->
</dependencies>
</project>
3.5. 子pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.example</groupId>
<artifactId>Javaweb</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>servlet02</artifactId>
<packaging>war</packaging>
<name>servlet02 Maven Webapp</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>servlet02</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.3.1</version>
</plugin>
</plugins>
</build>
</project>
2.3.6. 完整项目结构
2.3.7. 项目整体的服务配置
这里选择servlet02这个Module作为构建的目标对象。
create Artifact是构建,将项目打包。Artifact(构件)是指将项目打包、部署和发布所需的相关文件和资源的集合。
四、ServletContext
4.1. 介绍
ServletContext是Servlet中最大的一个接口,它是应用级对象,在服务器启动Web应用后,由服务器(如Tomcat)创建的。一个Web应用对应一个ServletContext示例,且Web应用中的所有Servlet共享同一个ServletContext对象,它在服务器关闭后销毁。
4.2. 常用方法
1. getInitParameter通过初始化参数的name获取指定初始化参数值
2. getInitParameterNames 获取所有的初始化参数Name
3. getContextPath 获取应用的根路径
4. getRealPath 获取文件真实路径
5. setAttribute(String name, String value) 往ServletContext应用域中存放数据
6. getAttribute(String name) 往ServletContext应用域中取数据
4.3. ServletContext使用准则
1. 被其他所有用户共享的数据
ServletContext只有一个对象,不被共享的数据存放进ServletContext中没有意义还占用资源。
- 数据量少
数据量大的话,太占用内存,因为ServletContext在服务器关闭才销毁,因此会影响性能占用资源。
3. 极少可能性被修改
所有用户共享的数据,如果涉及修改操作,必然会带来线程并发的安全问题。
4.4. 常规应用
4.4.1. 获取web应用里配置的一些初始化参数
下图展示了获取初始化参数url,该参数便位于应用上下文ServletContext中
4.4.2. 请求转发(请求的路径不会变)
4.4.3. 读取资源文件
读取资源的路径
target
-----classes
-----generated-sources
-----servlet-02-1.0-SNAPSHOT
----------META-INF
----------WEB-INF
---------------classes
--------------------com
--------------------db.properties
---------------lib
---------------web.xml
五、 Request/Response
web服务器接收到客户端的http请求,针对每个请求,会分别创建一个代表请求的HttpServletRequest对象,代表响应的一个HttpServletResponse对象。
5.1. HttpServletRequest
可以获取客户端过来的请求参数。
HttpServletRequest常用方法:
1. 获取请求的基本信息
getMethod():获取HTTP请求的方法,如GET、POST等。
getRequestURI():获取请求的URI(统一资源标识符)。
getRequestURL():获取请求的完整URL。
getQueryString():获取请求中的查询字符串。
getPathInfo():获取请求URL中的额外路径信息,位于Servlet的路径之后和查询参数之前。2. 获取客户端信息:
getRemoteAddr()] 和 getLocalAddr():分别获取客户端和服务器IP地址。
getRemoteHost()] 和 getLocalName():分别获取客户端和服务器的主机名。
getRemotePort():获取客户端使用的网络端口号。
2. 获取请求头信息
getHeader(String name):通过名称获取指定的请求头信息。
3. 获取请求参数
getParameter(String name)]和getParameterValues(String name):分别通过名称获取单个和多个请求参数。
4. 设置和获取属性
setAttribute(Object attribute)] 和getAttribute(String name):在请求的作用域内设置和获取属性。
5. 其他方法
getAuthType():返回请求的身份验证模式。
getCookies():返回一个包含当前所有cookie的数组。
getDateHeader(String name):返回指定的请求头日期信息。
request提交应用示例代码:
5.2. HttpServletResponse
可以配置响应给客户端的一些信息。
设置响应头:setHeader(String name,value)
设置状态码:setStatus(int sc)
获取向客户端输出内容的PrintWriter对象:getWriter()
设置内容类型:setContentType(“text/html;charset=utf-8”)
设置字符集:setCharacterEncoding(java.lang.String charset)
设置文件下载:文件下载需要设置response.addHeader(“Content-Disposition”, “attachment;filename=” + filename)响应头。
5.2.1. 下载文件
5.2.2. 获取验证码
5.2.3. 请求重定向
请求重定向和请求转发的区别
相同点:页面都会实现跳转。
不同点:请求转发地址栏的url不会变,重定向地址栏的url会变。