无需在程序运行时通过代码运行生成的资源
需要在程序运行时通过代码生成的资源,在程序运行之前无法确定的数据,运行时动态生成,例如Servlet,Thymeleaf……
Servlet是JavaWeb中后端的重点
- tomcat接受到请求后,将请求报文的信息转换为一个HttpServletRequest对象,该对象中包含了请求中的所有信息。
- tomcat同时创建了一个HttpServletResponse对象,该对象用于承装要响应给客户端的信息,后面,该对象会被转化为响应的报文。
- tomcat根据请求中的资源路径找到对应的servlet,将servlet实例化,调用service方法,同时将HttpServletRequest和HttpServletResponse对象传入。
- 创建JavaWeb项目,同时将tomcat添加为当前项目的依赖
- 重写service方法
- 在service方法中,定义业务处理代码
- 在web.xml中,配置Servlet对应的请求映射路径
例:校验输入的用户名是否不为ergou
index.html文件:
Title
java文件:
package com.ergou.servlet;
import jakarta.servlet.Servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServlet;
import java.io.IOException;
import java.io.PrintWriter;
public class UserServlet extends HttpServlet {
@Override
public void service(HttpServletRequest servletRequest, HttpServletResponse servletResponse) throws ServletException, IOException {
//从servletRequest对象中获取请求中的信息
String username = servletRequest.getParameter("username");//该方法是根据参数名获取参数值,即根据key获取value
//处理业务的代码
String info = "YES";
if("ergou".equals(username)){
info = "NO";
}
//将要响应的数据放入response
//应该设置Content-type响应头,也可以使用servletResponse.setContentType()
servletResponse.setHeader("Content-type","text/html");
PrintWriter writer = servletResponse.getWriter();//该方法返回的是一个向响应体中打印字符串的打印流
writer.write(info);
writer.close();
}
}
web.xml文件:
userServlet
com.ergou.servlet.UserServlet
userServlet
/userServlet
Content-type响应头,决定响应报文的响应体会被客户端当作什么文件类型处理。
使用ServletResponse对象调用方法setContentType()
在web.xml中:
- servlet-class 告诉Tomcat对应的要实例化的Servlet类
- servlet-name 用于关联请求的映射路径
- servlet-mapping 用来设置对应servlet-name的映射路径
- url-pattern 用来设置路径名
注:
- 一个servlet-name可以对应多个url-pattern
- 一个servlet标签可以对应多个servlet-mapping标签
- 每个url-pattern设置的路径名不能重复
格式:/路径名
要输入完全一样的路径名才能访问
*作为通配符, *在哪里,哪里就是模糊不确定的
格式①:/
只有一个/符号,意味着无论后面的内容是什么,都认作为此路径,jsp文件除外
格式②:/*
无论后面的内容是什么,都认作为此路径,jsp文件不除外
格式③:/(字符或字符串)*
匹配前缀,以指定字符为开头的路径,即都认作此路径
格式④:*(字符或字符串)
匹配后缀,以指定字符为开头的路径,即都认作此路径
使用注解@WebServlet()即可快速配置路径名
参数直接写一个路径名格式的字符串即可(也可以是value=”路径名“或urlPattern=”路径名”),若要给一个servlet多个路径名,参数写value={”路径名1“,”路径名2“,……}( 或urlPattern={”路径名1“,”路径名2“,……} )
- 实例化:即调用定义的Servlet类的构造器
- 初始化:调用init方法进行初始化
- 接受请求,处理请求:调用service方法
- 销毁:调用destory方法
生命周期 | 对应方法 | 执行时机 |
---|---|---|
构造对象 | 构造器 | 第一次请求或者容器启动 |
初始化 | init() | 构造完毕后 |
处理服务 | service(HttpServletRequest req,HttpServletResponse resp) | 每次请求 |
销毁 | destory() | 容器关闭 |
load-on-startup默认为-1,如果是-1,即默认tomcat启动时不会实例化该servlet
如果是正整数则表示容器在启动时就要实例化Servlet,数字表示的是实例化的顺序
load-on-up的赋值可以在注解@WebServlet()中赋值,若要赋值为6,参数列表为(value=“路径名”,loadOnStartup = 6
也可以在web.xml文件中赋值,例:
servletLifeCycle
com.atguigu.servlet.ServletLifeCycle
1
servletLifeCycle
/servletLiftCycle
总结:
- 通过生命周期测试我们发现Servlet对象在容器中是单例的
- 容器是可以处理并发的用户请求的,每个请求在容器中都会开启一个线程
- 多个线程可能会使用相同的Servlet对象,所以在Servlet中,我们不要轻易定义一些容易经常发生修改的成员变量
- load-on-startup中定义的正整数表示实例化顺序,如果数字重复了,容器会自行解决实例化顺序问题,但是应该避免重复
- Tomcat容器中,已经定义了一些随系统启动实例化的servlet,我们自定义的servlet的load-on-startup尽量不要占用数字1-5
当客户端请求静态资源时,没有匹配到某个servlet,于是就与defaultServlet进行匹配,defaultServlet就去找对应的静态资源响应给客户端。总的来说,defaultServlet是用来请求静态资源的。
- 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
getInitParameterNames()
- 返回所有初始化参数名的方法
- 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的方法
也不用记这么多,我也是复制粘贴过来的。只要记住GenericServlet 抽象类侧重实现除了service方法之外的其他抽象方法
- 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";1
- 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*** 方法都在故意响应错误信息
总之,HttpServlet抽象类侧重service方法的实现,并根据请求方式对应具体的处理。
由于HttpServlet抽象类中,service方法调用了do方法,会响应对应请求方式的错误信息,如果在自定义Servlet类不重写service方法,就会响应错误信息。(也可以选择重写do方法)
Servlet是为Servlet提供初始配置参数的一种对象,每个Servlet都有自己独立唯一的ServletConfig对象。容器会为每个Servlet实例化一个ServletConfig对象,并通过Servlet生命周期的init方法传入给Servlet作为属性。
方法名 | 作用 |
---|---|
getServletName() | 获取 |
getServletContext() | 获取ServletContext对象 |
getInitParameter() | 获取配置Servlet时设置的『初始化参数』,根据名字获取值 |
getInitParameterNames() | 获取所有初始化参数名组成的Enumeration对象 |
通过xml文件配置:
ServletA
com.atguigu.servlet.ServletA
param1
value1
param2
value2
ServletB
com.atguigu.servlet.ServletB
param3
value3
param4
value4
ServletA
/servletA
ServletB
/servletB
通过注解的方式配置:
@WebServlet(
urlPatterns = "/servlet",
initParams = {@WebInitParam(name = "key1",value = "value1"),@WebInitParam(name = "key1",value = "value1"),……}
)
使用xml配置ServletContext的参数信息:
paramA
valueA
paramB
valueB
getServletContext():获取ServletContext对象,调用者可以是servletConfig,也可以是ServletRequest的对象,也可以没有调用者
getRealPath("资源在web目录中的路径"):获取资源的真实路径,调用者为ServletContext的对象(即磁盘路径)
getContextPath():获取项目的上下文路径(即访问路径,在浏览器地址框输入的那个)
域对象是一些用于存储数据和传递数据的对象,传递数据不同的范围,我们称之为不同的域,不同的域对象代表不同的域,共享数据的范围也不同
ServletContext代表应用,所以ServletContext域也叫作应用域,是webapp中最大的域,可以在本应用内实现数据的共享和传递
webapp中的三大域对象,分别是应用域,会话域,请求域
API | 功能解释 |
---|---|
void setAttribute(String key,Object value); | 向域中存储/修改数据 |
Object getAttribute(String key); | 获得域中的数据 |
void removeAttribute(String key); | 移除域中的数据 |
相关API:(打字好累,复制粘贴偷个懒)
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请求头 |
API | 功能解释 |
---|---|
String getParameter(String parameterName); | 根据请求参数名获取请求单个参数值 |
String[] getParameterValues(String parameterName); | 根据请求参数名获取请求多个参数值数组 |
Enumeration |
获取所有请求参数名 |
Map |
获取所有请求参数的键值对集合 |
BufferedReader getReader() throws IOException; | 获取读取请求体的字符输入流 |
ServletInputStream getInputStream() throws IOException; | 获取读取请求体的字节输入流 |
int getContentLength(); | 获得请求体长度的字节数 |
API | 功能解释 |
---|---|
String getServletPath(); | 获取请求的Servlet的映射路径 |
ServletContext getServletContext(); | 获取ServletContext对象 |
Cookie[] getCookies(); | 获取请求中的所有cookie |
HttpSession getSession(); | 获取Session对象 |
void setCharacterEncoding(String encoding) ; | 设置请求体字符集 |
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 | 功能解释 |
---|---|
void sendError(int code, String message) throws IOException; | 向客户端响应错误信息的方法,需要指定响应码和响应信息 |
void addCookie(Cookie cookie); | 向响应体中增加cookie |
void setCharacterEncoding(String encoding); | 设置响应体字符集 |
文件拓展名 | 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 |
getRequestDispatcher("servletB"):获取请求转发器,调用者为HttpServletRequest的对象,参数为要转发的Servlet的对象的名字
forward(request,response):做出转发动作,调用者为转发器对象,参数为HttpServletRequest对象与HttpServletResponse对象
// 获取请求转发器
RequestDispatcher requestDispatcher = request.getRequestDispatcher("servletB");
// 做出转发动作
requestDispatcher.forward(request,response);
- 请求转发是通过HttpServletRequest对象实现的
- 请求转发是服务器内部行为,对客户端是屏蔽的
- 在此期间,客户端只产生了一次请求,服务器只产生了一对request和reponse对象
- 客户端的地址是不变的
- 请求的参数是可以继续传递的
- 请求转发的目标资源可以是Servlet动态资源,也可以是静态资源,也可以是WEB-INF下的受保护的资源(该方式也是WEB-INF下的资源的唯一访问方式),不可以是外部资源(比如其他网页地址)
sendRedirect("servlet1"):设置响应状态码为302,同时设置location为参数内的路径,调用者为HttpServletResponse对象
response.sendRedirect("servlet2");
- 响应重定向是通过HttpServletResponse对象实现
- 响应重定向是在服务器下的客户端的行为
- 客户端的地址会转到location的路径,客户端产生了多次请求(至少两次)
- 请求产生多次,后端就有多个request对象,此时请求中的参数不能继续自动传递
- 目标资源可以是视图资源,不能是WEB-INF下的资源,目标资源可以是外部资源