目录
前言
一 . Servlet简介
1.1 动态资源和静态资源
1.2 Servlet简介
二 . Servlet开发流程
2.1 目标
2.2 开发过程
三 . Servlet注解方式配置
编辑
四 . servlet生命周期
4.1 生命周期简介
4.2 生命周期测试
4.3 生命周期总结
五 . servlet继承结构
5.1 servlet接口
5.2 GenericServlet抽象类
5.3 HttpServlet抽象类
5.4 自定义Servlet
六 . ServletConfig和ServletContext
6.1 ServletConfig
6.2 ServletContext
七 . HttpServletRequest && HttpServletResponse
7.1 HttpServletRequest
7.2 HttpServletResponse
八 . 请求转发和响应重定向
8.1 概述
8.1 请求转发
8.2 响应重定向
总结
大家好,今天给大家带来的是一个在web中非常重要的一门技术,如果这门技术学不好,那么web大概率也是学不好的,很重要!!
静态资源
静态资源是指在服务器上存储的不会改变的文件,如HTML、CSS、JavaScript、图片等。这些资源可以直接通过URL访问,并且服务器在接收到请求后会直接将文件发送给客户端,不需要进行任何处理。
动态资源
图解:
Servlet (server applet) 是运行在服务端(tomcat)的Java小程序,是sun公司提供一套定义动态资源规范; 从代码层面上来讲Servlet就是一个接口
可以用以下类比来理解Servlet的概念:
假设您去餐厅用餐,您是客户端,餐厅是服务器。您点菜并提交给服务员,服务员将您的点菜单传递给厨师,厨师根据点菜单准备食物,并将食物送到您的桌子上。
在这个类比中,客户端就是发送HTTP请求的浏览器,服务器就是接收和处理请求的Servlet。您的点菜单就是HTTP请求,厨师根据点菜单准备食物就是Servlet根据请求生成动态内容,食物送到您桌子上就是服务器将生成的内容发送给浏览器。
前端页面
我们要做的是,在输入账号和密码后,判断账号密码是不是等于'zuiacsn' 'zuiacsn' 如果等于返回Yes,如果不等于返回NO
前端页面代码
Title 博客系统
首先先创建一个web项目,准备com.zuiacsn.servlet包(大家根据实际自行定义)
步骤:
自定义一个类,要继承HttpServlet类
重写service方法,该方法主要就是用于处理用户请求的服务方法
HttpServletRequest 代表请求对象,是有请求报文经过tomcat转换而来的,通过该对象可以获取请求中的信息
HttpServletResponse 代表响应对象,该对象会被tomcat转换为响应的报文,通过该对象可以设置响应中的信息
Servlet对象的生命周期(创建,初始化,处理服务,销毁)是由tomcat管理的,无需我们自己new
HttpServletRequest HttpServletResponse 两个对象也是有tomcat负责转换,在调用service方法时传入给我们用的
在service方法中实现我们的业务逻辑
调用HttpServletRequest对象中的getParameter方法得到传入的用户名和密码
判断传入的信息是否等于"zuiacsn" 如果不等于向前端响应NO,如果校验正确,向前端响应YES
现在类定义好了,代码逻辑也敲完了,但是现在这个类只是普通的java类,如果想要通过url进行访问我们需要去xml配置文件中处理请求映射路径
web.xml文件中有两个标签就是用来处理请求映射的
helloServlet com.zuiacsn.servlet.HelloServlet helloServlet /helloServlet
现在我们还差最后一步,配置tocmat服务器
点击Apply,OK,启动服务来测试效果,上面那个路径有问题,改成/demo01
测试成功!
我们来复分析一下执行流程
通过index.html中的action找到web.xml文件并找到Servlet组件解析
上面的配置方式是通过配置文件进行配置的,在开发中我们以效率为主,通过注解来进行配置应为上上之选,等学到了框架,那注解多的,记不住,根本记不住!
@WebServlet是Java EE中的一个注解,用于标识一个类为Servlet。通过在Servlet类上添加@WebServlet注解,可以指定Servlet的访问路径、初始化参数、加载顺序等配置信息。
在这里补充一点servlet-mapping可以配置多个但是与之相对应的servlet只能有一个
Ok,我们来测试一下
这个错误信息我不太了解,可以说我对错误信息没几个了解的,不过我知道如果我们配置的路径不唯一,在web.xml文件中配置了,在类上又加上了这一个注解,那么便会报这个错误,我们只需要把配置文件中的信息删除即可
ok再来试一下
完美
什么是Servlet的生命周期
应用程序中的对象不仅在空间上有层次结构的关系,在时间上也会因为处于程序运行过程中的不同阶段而表现出不同状态和不同行为——这就是对象的生命周期。
简单的叙述生命周期,就是对象在容器中从开始创建到销毁的过程。
Servlet容器
Servlet对象是Servlet容器创建的,生命周期方法都是由容器(目前我们使用的是Tomcat)调用的。这一点和我们之前所编写的代码有很大不同。在今后的学习中我们会看到,越来越多的对象交给容器或框架来创建,越来越多的方法由容器或框架来调用,开发人员要尽可能多的将精力放在业务逻辑的实现上。
来,创建web项目 demo02-web-servletLiftcycle 在com.zuiacsn.servlet包下创建类ServletCycleTest
配置tomcat
OK,来测试一下
上面的测试说明了servlet在Tomcat中是单例的,所以servlet的成员变量在多个线程栈中是共享的
不建议在servlet中修改成员变量,会引发线程安全问题
图解:
通过生命周期测试我们发现Servlet对象在容器中是单例的
容器是可以处理并发的用户请求的,每个请求在容器中都会开启一个线程
多个线程可能会使用相同的Servlet对象,所以在Servlet中,我们不要轻易定义一些容易经常发生修改的成员变量
load-on-startup中定义的正整数表示实例化顺序,如果数字重复了,容器会自行解决实例化顺序问题,但是应该避免重复
Tomcat容器中,已经定义了一些随系统启动实例化的servlet,我们自定义的servlet的load-on-startup尽量不要占用数字1-5
Servlet 规范接口,所有的Servlet必须实现
public void init(ServletConfig config) throws ServletException;
初始化方法,容器在构造servlet对象后,自动调用的方法,容器负责实例化一个ServletConfig对象,并在调用该方法时传入
ServletConfig对象可以为Servlet 提供初始化参数
public ServletConfig getServletConfig();
获取ServletConfig对象的方法,后续可以通过该对象获取Servlet初始化参数
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
处理请求并做出响应的服务方法,每次请求产生时由容器调用
容器创建一个ServletRequest对象和ServletResponse对象,容器在调用service方法时,传入这两个对象
public String getServletInfo();
获取ServletInfo信息的方法
public void destroy();
Servlet实例在销毁之前调用的方法
GenericServlet 抽象类是对Servlet接口一些固定功能的粗糙实现,以及对service方法的再次抽象声明,并定义了一些其他相关功能方法
private transient ServletConfig config;
初始化配置对象作为属性
public GenericServlet() { }
构造器,为了满足继承而准备
public void destroy() { }
销毁方法的平庸实现
public String getInitParameter(String name)
获取初始参数的快捷方法
public Enumeration
返回所有初始化参数名的方法
public ServletConfig getServletConfig()
获取初始Servlet初始配置对象ServletConfig的方法
public ServletContext getServletContext()
获取上下文对象ServletContext的方法
public String getServletInfo()
获取Servlet信息的平庸实现
public void init(ServletConfig config) throws ServletException()
初始化方法的实现,并在此调用了init的重载方法
public void init() throws ServletException
重载init方法,为了让我们自己定义初始化功能的方法
public void log(String msg)
public void log(String message, Throwable t)
打印日志的方法及重载
public abstract void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
服务方法再次声明
public String getServletName()
获取ServletName的方法
abstract class HttpServlet extends GenericServlet HttpServlet抽象类,除了基本的实现以外,增加了更多的基础功能
private static final String METHOD_DELETE = "DELETE";
private static final String METHOD_HEAD = "HEAD";
private static final String METHOD_GET = "GET";
private static final String METHOD_OPTIONS = "OPTIONS";
private static final String METHOD_POST = "POST";
private static final String METHOD_PUT = "PUT";
private static final String METHOD_TRACE = "TRACE";
上述属性用于定义常见请求方式名常量值
public HttpServlet() {}
构造器,用于处理继承
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
对服务方法的实现
在该方法中,将请求和响应对象转换成对应HTTP协议的HttpServletRequest HttpServletResponse对象
调用重载的service方法
public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
重载的service方法,被重写的service方法所调用
在该方法中,通过请求方式判断,调用具体的do***方法完成请求的处理
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doHead(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doOptions(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
对应不同请求方式的处理方法
除了doOptions和doTrace方法,其他的do*** 方法都在故意响应错误信息
自定义Servlet中,必须要对处理请求的方法进行重写
要么重写service方法
要么重写doGet/doPost方法
什么是ServletConfig?
为Servlet提供初始配置参数的一种对象,每个Servlet都有自己独立唯一的ServletConfig对象
容器会为每个Servlet实例化一个ServletConfig对象,并通过Servlet生命周期的init方法传入给Servlet作为属性
servletconfig中常用API
getServletName() | 获取 |
getServletContext() | 获取ServletContext对象 |
getInitParameter() | 获取配置Servlet时设置的『初始化参数』,根据名字获取值 |
getInitParameterNames() | 获取所有初始化参数名组成的Enumeration对象 |
ServletContext是什么
ServletContext对象有称呼为上下文对象,或者叫应用域对象
容器会为每个app创建一个独立的唯一的ServletContext对象
ServletContext对象为所有的Servlet所共享
ServletContext可以为所有的Servlet提供初始配置参数
常用API
获取资源的真实路径
String realPath = servletContext.getRealPath("资源在web目录中的路径");
例如我们的目标是需要获取项目中某个静态资源的路径,不是工程目录中的路径,而是部署目录中的路径;我们如果直接拷贝其在我们电脑中的完整路径的话其实是有问题的,因为如果该项目以后部署到公司服务器上的话,路径肯定是会发生改变的,所以我们需要使用代码动态获取资源的真实路径. 只要使用了servletContext动态获取资源的真实路径,那么无论项目的部署路径发生什么变化,都会动态获取项目运行时候的实际路径,所以就不会发生由于写死真实路径而导致项目部署位置改变引发的路径错误问题
获取项目的上下文路径
String contextPath = servletContext.getContextPath();
项目的部署名称,也叫项目的上下文路径,在部署进入tomcat时所使用的路径,该路径是可能发生变化的,通过该API动态获取项目真实的上下文路径,可以帮助我们解决一些后端页面渲染技术或者请求转发和响应重定向中的路径问题
域对象的相关API
域对象: 一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同
ServletContext代表应用,所以ServletContext域也叫作应用域,是webapp中最大的域,可以在本应用内实现数据的共享和传递
webapp中的三大域对象,分别是应用域,会话域,请求域
三大域对象都具有的API如下
API | 功能解释 |
---|---|
void setAttribute(String key,Object value); | 向域中存储/修改数据 |
Object getAttribute(String key); | 获得域中的数据 |
void removeAttribute(String key); | 移除域中的数据 |
HttpServletRequest是什么
HttpServletRequest是一个接口,其父接口是ServletRequest
HttpServletRequest是Tomcat将请求报文转换封装而来的对象,在Tomcat调用service方法时传入
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 getContentType(); | 获取content-type请求头 |
HttpServletResponse是一个接口,其父接口是ServletResponse
HttpServletResponse是Tomcat预先创建的,在Tomcat调用service方法时传入
HttpServletResponse代表对客户端的响应,该对象会被转换成响应的报文发送给客户端,通过该对象我们可以设置响应信息
常用API
设置响应行相关
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); | 设置响应体字符集 |
什么是请求转发和响应重定向
请求转发和响应重定向是web应用中间接访问项目资源的两种手段,也是Servlet控制页面跳转的两种手段
请求转发通过HttpServletRequest实现,响应重定向通过HttpServletResponse实现
请求转发生活举例: 张三找李四借钱,李四没有,李四找王五,让王五借给张三
响应重定向生活举例:张三找李四借钱,李四没有,李四让张三去找王五,张三自己再去找王五借钱
图示:
请求转发特点(背诵)
请求转发通过HttpServletRequest对象获取请求转发器实现
请求转发是服务器内部的行为,对客户端是屏蔽的
客户端只发送了一次请求,客户端地址栏不变
服务端只产生了一对请求和响应对象,这一对请求和响应对象会继续传递给下一个资源
因为全程只有一个HttpServletRequset对象,所以请求参数可以传递,请求域中的数据也可以传递
请求转发可以转发给其他Servlet动态资源,也可以转发给一些静态资源以实现页面跳转
请求转发可以转发给WEB-INF下受保护的资源
请求转发不能转发到本项目以外的外部资源
代码测试
以下是一个简单的示例代码,演示如何使用请求转发进行页面跳转:
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 {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 执行一些逻辑处理
// 获取RequestDispatcher对象,参数是要转发的目标页面的路径
RequestDispatcher dispatcher = request.getRequestDispatcher("/targetPage.jsp");
// 使用RequestDispatcher的forward方法进行请求转发
dispatcher.forward(request, response);
}
}
在上面的示例中,当收到一个GET请求时,Servlet会执行一些逻辑处理,然后使用request.getRequestDispatcher("/targetPage.jsp")
获取到一个RequestDispatcher对象。然后,使用该对象的forward
方法将请求转发到目标页面targetPage.jsp
。
图示:
响应重定向特点(背诵)
响应重定向通过HttpServletResponse对象的sendRedirect方法实现
响应重定向是服务端通过302响应码和路径,告诉客户端自己去找其他资源,是在服务端提示下的,客户端的行为
客户端至少发送了两次请求,客户端地址栏是要变化的
服务端产生了多对请求和响应对象,且请求和响应对象不会传递给下一个资源
因为全程产生了多个HttpServletRequset对象,所以请求参数不可以传递,请求域中的数据也不可以传递
重定向可以是其他Servlet动态资源,也可以是一些静态资源以实现页面跳转
重定向不可以到给WEB-INF下受保护的资源
重定向可以到本项目以外的外部资源
以下是一个简单的示例代码,演示如何使用响应重定向进行页面跳转:
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 {
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 执行一些逻辑处理
// 使用HttpServletResponse的sendRedirect方法进行响应重定向
response.sendRedirect("/targetPage.jsp");
}
}
在上面的示例中,当收到一个GET请求时,Servlet会执行一些逻辑处理,然后使用response.sendRedirect("/targetPage.jsp")
进行响应重定向,将用户重定向到目标页面targetPage.jsp
。
这篇博客就到这了,以后等学的更好了,再来改吧