Servlet
概述
Servlet(Server Applet),全称Java Servlet,未有中文译文。是用 Java 编写的服务器端程序。其主要功能在于交互式地浏览和修改数据,生成动态 Web 内容。狭义的 Servlet 是指 Java 语言实现的一个接口,广义的 Servlet 是指任何实现了这个 Servlet 接口的类,一般情况下,人们将Servlet 理解为后者
Servlet运行于支持Java的应用服务器中。从实现上讲,Servlet 可以响应任何类型的请求,但绝大多数情况下 Servlet 只用来扩展基于HTTP协议的Web服务器。
简单理解:
Servlet 是 Java Web 服务端的一个小程序,主要用户数据的交互,Web 数据展示和数据传递,这里的 Servlet 是一个动态资源。
Servlet 程序可以应对所有类型的请求和响应,Servlet 主要还是用于HTTP 协议的WEB服务器程序实现。
工作模式【重点】
- 浏览器端发送请求至服务器
- 服务器启动并调用Servlet,Servlet根据客户端请求生成响应内容并将其传给服务器
- 服务器将响应返回客户端
tomcat 和 servlet 的关系【了解】
Tomcat 是 Web 应用服务器,是一个 Servlet/JSP 容器。Tomcat 作为 Servlet 容器,负责处理客户请求,把请求传送给 Servlet,并将 Servlet 的响应传送回给客户。而Servlet是一种运行在支持 Java 语言的服务器上的组件。Servlet 最常见的用途是扩展 Java Web 服务器功能,提供非常安全的,可移植的,易于使用的 CGI 替代品。
1、Tomcat将http请求文本接收并解析,然后封装成HttpServletRequest类型的request对象,所有的HTTP头数据读可以通过request对象调用对应的方法查询到。
2、Tomcat同时会要响应的信息封装为HttpServletResponse类型的response对象,通过设置response属性就可以控制要输出到浏览器的内容,然后将response交给tomcat,tomcat就会将其变成响应文本的格式发送给浏览器
Java Servlet API 是 Servlet容器 (tomcat) 和 servlet 之间的接口,它定义了 serlvet 的各种方法,还定义了 Servlet 容器传送给 Servlet 的对象类,其中最重要的就是 ServletRequest 和 ServletResponse。所以说我们在编写servlet 时,需要实现 Servlet 接口,按照其规范进行操作。
初识
步骤
1、创建类并继承自HttpServlet
2、重写doGet和doPost方法(两个方法实际是一个)
3、声明@WebServlet并加上默认属性(访问路径)
案例代码
/**
* @description 第一个Servlet程序
*
* @WebServlet 注解的意思是声明程序的入口,注解中的属性为请求的路径
* 【注意】属性前必须要加 / !!!
*/
@WebServlet("/HelloServlet")
public class HelloServlet extends HttpServlet {
/**
* 处理Post请求
*
* @param req HttpServletRequest对象:浏览器请求数据内容对象
* @param resp HttpServletResponse对象:浏览器响应数据内容对象
* @throws ServletException Servlet异常
* @throws IOException IO异常
*/
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doPost被执行");
resp.getWriter().append("Hello Servlet");
}
/**
* 处理Get请求
*
* @param req HttpServletRequest对象:浏览器请求数据内容对象
* @param resp HttpServletResponse对象:浏览器响应数据内容对象
* @throws ServletException Servlet异常
* @throws IOException IO异常
*/
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("doGet被执行");
// 实际调用的仍然是doget方法
doPost(req, resp);
}
}
html页面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试Servlet</title>
</head>
<body>
<form action="HelloServlet" method="get">
<input type="submit" value="get请求">
</form>
<form action="HelloServlet" method="post">
<input type="submit" value="post请求">
</form>
</body>
</html>
【注意】
- Servlet代码中的@WebServlet注解中的属性值前必须要加 /
- HTML页面中跳转页面不要加 /
servlet 核心接口和类
// 两个相关核心包
javax.servlet
javax.servlet.http
// 顶级父类接口,定义了生命周期方法以及获取配置的方法
public interface Servlet;
// 初始化当前Servlet程序,这里需要的参数是ServletConfig,ServletConfig是当前Servlet的配置,该配置可以从注解方式或者从当前项目中的web.xml加载获取
public void init(ServletConfig config) throws ServletException;
// 获取ServletConfig对象,当前对象中保存有Servlet配置内容
public ServletConfig getServletConfig();
// 【核心方法】Servlet提供服务的方法,浏览器访问当前Servlet程序,service方法是起作用,真实调用的还是doget和doPost
// ServletRequest对应的是请求对象
// ServletResponse 对应的是响应对象
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException;
// 获取当时Servlet程序信息对应字符串,几乎不用,数据都保存在数据库中
public String getServletInfo();
// 销毁当前Servlet程序,可以由Tomcat服务器执行,也可也通过servlet程序自己调用
public void destroy();
// 对 Servlet 的扩展,完成了一些不太关心的方法,对我们来说只需重写 service 方法即可
public abstract class GenericServlet;
// 根据初始化参数名字获取对应的值,而且参数值为String
public String getInitParameter(String name);
// 获取ServletContext对象,一个Servlet Application有且只有一个ServletContext对应,这是Servlet上下文对象,对应整个Servlet项目,此方法同时实现了Servlet接口中的 init 初始化方法
public ServletContext getServletContext();
// 符合HTTP协议的Servlet,继承自GenericServlet,最常用,需要重写 doGet 和 doPost 方法
public abstract class HttpServlet;
// 符合HTTP GET请求的处理方式
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
// 符合HTTP POST请求的处理方式
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
// 用于 Servlet 之间的通信
public interface ServletContext;
// 扩展ServletRequest接口,为HTTP servlet提供请求信息。servlet容器创建一个HttpServletRequest对象,并将其作为参数传递给servlet的服务方法(doGet、doPost)。
public interface HttpServletRequest;
// 扩展ServletResponse接口以在发送响应时提供特定于http的功能。servlet容器创建一个HttpServletResponse对象,并将其作为参数传递给servlet的服务方法(doGet、doPost等)。
public interface HttpServletResponse;
// 提供一种技术来识别跨多个页面请求或访问Web站点的用户,并存储有关该用户的信息,用于会话技术
public interface HttpSession;
// 创建一个cookie, servlet发送给Web浏览器的少量信息,由浏览器保存,然后发送回服务器。cookie的值可以唯一地标识客户端,因此cookie通常用于会话管理。
public class Cookie;
【重点】HttpServlet 中的 doGet 和 doPost 方法
三种创建 Servlet 的方式
【注意】不管是哪种方式都一定要加上@WebServlet注解!!!
实现 servlet 接口【鸡肋】
/**
* 实现Servlet接口
* 代码中存在太多和业务逻辑无关的代码,增加了程序员的压力!!!
* 不要这么写!!!
*/
@WebServlet("/ServletImpl")
public class ServletImpl implements Servlet {
/**
* 构造方法
*/
public ServletImpl() {
System.out.println("constructor method be called");
}
/**
* 初始化方法
*
* @param servletConfig 需要使用ServletConfig类对象,也就是Servlet配置来完成初始化操作
* @throws ServletException Servlet异常
*/
@Override
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init method be called");
}
/**
* 获取Servlet配置对象
*
* @return 获取ServletConfig对象
*/
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 提供服务核心方法,其实就是doGet和doPost
*
* @param servletRequest ServletRequest对象
* @param servletResponse ServletResponse对象
* @throws ServletException Servlet异常
* @throws IOException IO异常
*/
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service method be called");
// 设置字符集为UTF-8
servletResponse.setContentType("text/html; charset=utf-8");
// 写入内容
servletResponse.getWriter().append("<font color=red size=30px style=text-align: center>service方法被执行~</font>");
}
/**
* 获取Servlet信息
* @return Servlet信息
*/
@Override
public String getServletInfo() {
return null;
}
/**
* 销毁的方法
*/
@Override
public void destroy() {
System.out.println("destroy method be called");
}
}
太过繁琐,需要关注的东西太多,pass
继承 GenericServlet 类【鸡肋】
/**
* 继承自GenericServlet创建Servlet
*/
@WebServlet("/ExtendsGeneric")
public class ExtendsGeneric extends GenericServlet {
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
servletResponse.setContentType("text/html; charset=utf-8");
servletResponse.getWriter().append("<div style='color: aquamarine'>北纬线的思念被季风吹远</div>");
}
}
相比于实现 Servlet,友好太多,但是还不够友好,因为没有对应Http协议请求的处理方法
继承 HttpServlet 类【重点】
/**
* 继承自HttpServlet创建Servlet
*/
@WebServlet("/ExtendsHttpServlet")
public class ExtendsHttpServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().append("<font color='green' size=7>晚餐可以吃午餐肉吗?</font>");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
【注意】一定要重写 doGet 和 doPost 方法
使用继承 HttpServlet 类的优点
HttpServlet 在实现 Servlet 接口的时候,已经实现了 servlet 中所有方法,因此继承自 HttpSrvlet 的类,不需要再去重写相应的生命周期等方法,并且支持 HTTP 协议
Servlet 生命周期
- Servlet 构造方法被执行
- 然后使用 init 方法进行初始化。
- 浏览器端对 service 方法的任何调用都将被处理
- Servlet 退出,使用 destroy 方法进行销毁,然后垃圾收集并完成。
案例代码
/**
* Servlet生命周期
*/
@WebServlet("/ServletLife")
public class ServletLife implements Servlet {
/**
* 构造方法
*/
public ServletLife() {
System.out.println("ServletLife Constructor called");
}
/**
* 初始化方法
*
* @param config 需要使用ServletConfig类对象,也就是Servlet配置来完成初始化操作
* @throws ServletException Servlet异常
*/
@Override
public void init(ServletConfig config) throws ServletException {
System.out.println("init method called");
}
/**
* 获取ServletConfig对象
*
* @return 获取ServletConfig对象
*/
@Override
public ServletConfig getServletConfig() {
return null;
}
/**
* 提供服务核心方法
*
* @param req ServletRequest对象
* @param res ServletResponse对象
* @throws ServletException Servlet异常
* @throws IOException IO异常
*/
@Override
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException {
System.out.println("service method called");
}
/**
* 获取Servlet信息
* @return Servlet字符串信息
*/
@Override
public String getServletInfo() {
return null;
}
/**
* 销毁Servlet
*/
@Override
public void destroy() {
System.out.println("destroy method called");
}
}
两种配置方式【重点】
通过 @WebServlet 注解
@WebServlet注解用于标注在一个继承了HttpServlet类之上,属于类级别的注解
【注意】Servlet3.0之后允许使用注解方式配置!!!
常用格式
@WebServlet("/TestServlet")
public class useAnnotation extends HttpServlet {
doGet();
doPost();
}
常用属性描述
属性 | 类型 | 是否必须 | 描述 |
---|---|---|---|
asyncSupported | boolean | 否 | 指定Servlet是否支持异步操作 |
displayName | String | 否 | 指定Servlet显示名称 |
initParams | WebInitParam[] | 否 | 配置初始化参数 |
loadOnStartup | int | 否 | 标记容器是否在应用启动时就加载这个Servlet,默认 -1,选择加载 1 |
name | String | 否 | 指定Servlet名称 |
urlPatterns | String[] | 是/否 | 允许当前Servlet有多个匹配方式,和value互斥 |
value【重点】 | String[] | 否/是 | url资源匹配方式,和urlPatterns互斥 |
案例代码
/**
* 通过注解配置Servlet
*/
@WebServlet(urlPatterns = {"/urlPatterns", "/aa"}, // 多个匹配路径,与value属性互斥,只能存在一个
name = "AnnotationServlet", // 自定义Servlet名,没啥用
displayName = "AnnotationServlet", // 显示名,没啥用
loadOnStartup = 1, // 加载时自动启动
initParams = {@WebInitParam(name = "username", value = "易烊千玺"), @WebInitParam(name = "password", value = "欧阳娜娜")}) // 初始化参数
public class UseOnAnnotation extends HttpServlet {
public UseOnAnnotation() {
System.out.println("constructor be called");
}
@Override
public void init() throws ServletException {
System.out.println("init method be called");
super.init();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().append("test annotation");
// 获取初始化参数
String username = getServletConfig().getInitParameter("username");
String password = getServletConfig().getInitParameter("password");
resp.getWriter().append(username).append(":").append(password);
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
}
通过 web.xml 文件
核心内容
<!--Servlet核心配置,必须告知Servlet程序对应的名字和Servlet程序对应的class(Java类)-->
<servlet>
<!-- ServletName -->
<servlet-name>UseWebXML</servlet-name>
<!-- Servlet对应的class,必须是完整的包名.类名 -->
<servlet-class>com.fc.d_configServlet.UseWebXML</servlet-class>
</servlet>
<!-- Servlet映射关系 -->
<servlet-mapping>
<!--声明映射到哪一个Servlet,必须与Servlet-name中相同-->
<servlet-name>UseWebXML</servlet-name>
<!--URL-->
<url-pattern>/UseWebXML</url-pattern>
</servlet-mapping>
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_3_1.xsd"
version="3.1">
<!--Servlet核心配置,必须告知Servlet程序对应的名字和Servlet程序对应的class(Java类)-->
<servlet>
<!-- ServletName -->
<servlet-name>UseWebXML</servlet-name>
<!-- Servlet对应的class,必须是完整的包名.类名 -->
<servlet-class>com.fc.d_configServlet.UseWebXML</servlet-class>
<!-- 当前Servlet程序初始化操作,需要放在servlet-class之后 -->
<init-param>
<param-name>彭于晏</param-name>
<param-value>真帅</param-value>
</init-param>
<init-param>
<param-name>欧阳娜娜</param-name>
<param-value>真美</param-value>
</init-param>
<!-- Tomcat启动时当前Servlet -->
<load-on-startup>1</load-on-startup>
</servlet>
<!-- Servlet映射关系 -->
<servlet-mapping>
<!--声明映射到哪一个Servlet,必须与Servlet-name中相同-->
<servlet-name>UseWebXML</servlet-name>
<!--URL-->
<url-pattern>/UseWebXML</url-pattern>
</servlet-mapping>
<!-- Servlet映射关系2 -->
<servlet-mapping>
<!--声明映射到哪一个Servlet,必须与Servlet-name中相同-->
<servlet-name>UseWebXML</servlet-name>
<!--第二个URL-->
<url-pattern>/UseWebXML2</url-pattern>
</servlet-mapping>
</web-app>
案例代码
/**
* 使用Web.xml方式
*/
public class UseWebXML extends HttpServlet {
public UseWebXML() {
System.out.println("constructor be called");
}
@Override
public void init() throws ServletException {
System.out.println("init method be called");
super.init();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setContentType("text/html; charset=utf-8");
resp.getWriter().append("猫(>^ω^<)喵");
String parameter1 = getServletConfig().getInitParameter("彭于晏");
String parameter2 = getServletConfig().getInitParameter("欧阳娜娜");
System.out.println(parameter1 + ":" + parameter2);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
两种方式比较
@WebServlet注解 配置简单,直观,高效 url-pattern 冲突问题,并且是在Tomcat启动时发现,需要注意细节 web.xml配置文件 繁琐,麻烦,步骤繁多 url-pattern 一旦写错或者冲突,web.xml文件会提示错误!!!