文章目录
Servlet
1. 介绍
Servlet运行在服务器端的小程序,具有独立于平台和协议的特性,主要功能在于交互式地浏览和生成数据,生成动态Web内容。
- Servlet就是一个接口,定义了java类被浏览器访问到(Tomcat识别)的规则。
- 将来我们自定义一个类,实现Servlet接口,复写方法。
**运行在服务器端的程序:**即运行在Tomcat这类web容器的程序。
Servlet: 是指所有实现了 Servlet 接口的类,是编写的程序。
**作用:**Servlet 主要用于处理客户端传来的 HTTP 请求,并返回一个响应,它能够处理的请求有 doGet() 和 doPost() 等。
**来源:**Servlet 由 Servlet 容器提供,Servlet 容器是指提供了 Servlet 功能的服务器(如 Tomcat)。Servlet 容器会将 Servlet 动态加载到服务器上,然后通过 HTTP 请求和 HTTP 应与客户端进行交互。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m4xSIM7K-1652970457898)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\image-20211218200119946.png)]
综合以上:
- Servlet是我们编写的程序,这个程序是运行在服务器上的。
- Servlet容器就是我们的服务器。Tomcat就是一种容器。
Servlet 的请求首先会被 HTTP 服务器(如 Apache)接收,HTTP 服务器只负责静态 HTML 页面的解析,而 Servlet 的请求会转交给 Servlet 容器,Servlet 容器会根据 web.xml 文件中的映射关系,调用相应的 Servlet,Servlet 再将处理的结果返回给 Servlet 容器,并通过 HTTP 服务器将响应传输给客户端。
最主流的三个Web服务器(HTTP服务器)是Apache、 Nginx 、IIS。
Servlet 技术具有如下特点。
-
方便
Servlet 提供了大量的实用工具例程,如处理很难完成的 HTML 表单数据、读取和设置 HTTP 头,以及处理 Cookie 和跟踪会话等。
-
跨平台
Servlet 使用 Java 类编写,可以在不同的操作系统平台和不同的应用服务器平台运行。
-
灵活性和可扩展性强
采用 Servlet 开发的 Web 应用程序,由于 Java 类的继承性及构造函数等特点,使得应用灵活,可随意扩展。
2. 快速入门
使用Servlet
-
创建JavaEE项目(参考上一章节Tomcat服务器中的创建步骤)
-
创建一个Servlet类,实现Servlet接口
-
实现类中的抽象方法
public class ServletDemo1 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
}
@Override
public ServletConfig getServletConfig() {
return null;
}
//提供服务的方法
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("hello servlet");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
- 配置Servlet
在xml中添加实现接口类的路径以及定义url地址
配置之后,我们通过浏览器访问对应的路径时,即可跳转到我们相应的接口中
<?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-name>demo1</servlet-name>
<servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class>
</servlet>
<!-- 配置访问的url路经-->
<servlet-mapping>
<servlet-name>demo1</servlet-name>
<url-pattern>/demo1</url-pattern>
</servlet-mapping>
</web-app>
-
运行结果:
-
Jsp页面
-
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>$Title$</title> </head>s <body> <h1>Hello servlet</h1> <a href="/servlet/demo1">please enter</a> </body> </html>
-
浏览器访问:
控制台打印:
设置请求路径
-
重启服务器,再次请求
3. 执行原理
-
当服务器接受到客户端浏览器的请求后,会解析请求URL路径,获取访问的Servlet的资源路径
-
查找web. xml文件,是否有对应的标签体内容。
-
如果有,则在找到对应的全类名
-
tomcat会将字节码文件加载进内存,并且创建其对象
-
调用其方法
通过反射机制,创建类的实例对象,之后调用对象的service方法。
Servlet方法(生命周期)解析
三种状态
-
被创建时:执行init(),只执行一次。加载资源
-
servlet什么时候被创建
-
默认情况下,第一次访问时被创建
-
可以指定Servlet的创建时机(在xml中配置)
<servlet> <servlet-name>demo1</servlet-name> <servlet-class>cn.itcast.web.servlet.ServletDemo1</servlet-class> <!--指定servlet的创建时机--> <!-- 1.第一次访问时创建-->访问的是所在页面 <!-- <load-on-startup>的值为负数--> <!-- 2.在服务器启动时创建-->Tomcat服务器启动时 <!-- <load-on-startup>的值为0或正整数--> <load-on-startup>5</load-on-startup> </servlet>
-
初始化参数init
@WebServlet(urlPatterns = "/demo3",initParams = { @WebInitParam(name = "username",value = "tom"), @WebInitParam(name = "password",value = "123456") }) public class ServletDemo3 extends HttpServlet { public void doGet(HttpServletRequest request, HttpServletResponse response){ System.out.println(this.getInitParameter("username")); System.out.println(this.getInitParameter("password")); } }
-
-
-
提供服务时:执行 service(),执行多次
-
每次访问Servlet时执行(刷新页面)
-
被销毁:执行destory(),只执行一次。释放资源
- Servlet被销毁时执行。服务器关闭时,Servlet被销毁
- 只有服务器被正常关闭时,而不是只关闭页面
- 是在Servlet在Servlet执行之前执行(死前遗言)
public class ServletDemo1 implements Servlet {
@Override
/*
1.初始化方法
在Servlet创建时执行,只执行一次
*/
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init............");
}
@Override
/***
*2. 获得severlet的一些配置信息
*/
public ServletConfig getServletConfig() {
return null;
}
//提供服务的方法
@Override
/*
3. 提供服务方法
每一次Servlet被访问时执行。执行多次
*/
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service...............");
}
/*
4.获得servlet的一些信息,版本,作者等。
* */
@Override
public String getServletInfo() {
return null;
}
@Override
/*
5. 销毁方法
在服务器正常关闭时执行,执行一次。
*/
public void destroy() {
System.out.println("destory......");
}
}
架构图
下图显示了一个典型的 Servlet 生命周期方案。
- 第一个到达服务器的 HTTP 请求被委派到 Servlet 容器。
- Servlet 容器在调用 service() 方法之前加载 Servlet。
- 然后 Servlet 容器处理由多个线程产生的多个请求,每个线程执行一个单一的 Servlet 实例的 service() 方法。
注解配置Servlet
@WebServlet注解(Servlet注解) (biancheng.net)
从快速入门中我们看到,当我们想访问servlet时,需要在xml中对servlet路径进行配置,但是配置很麻烦,如果有多个servlet,那么就很繁琐。
Servlet3.0之后,引入了注释配置,就不需要在xml中配置了。
创建项目时,也不需要勾选create.web.xml了
语法
@WebServlet(urlPatterns = "/demo1")或者
@WebServlet("/demo1")
使用
@WebServlet(urlPatterns = "/demo1")
public class ServletDemo1 implements Servlet {
@Override
/*
1.初始化方法
在Servlet创建时执行,只执行一次
*/
public void init(ServletConfig servletConfig) throws ServletException {
System.out.println("init............");
}
@Override
/***
*2. 获得severlet的一些配置信息
*/
public ServletConfig getServletConfig() {
return null;
}
//提供服务的方法
@Override
/*
3. 提供服务方法
每一次Servlet被访问时执行。执行多次
*/
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("service...............");
}
/*
4.获得servlet的一些信息,版本,作者等。
* */
@Override
public String getServletInfo() {
return null;
}
@Override
/*
5. 销毁方法
在服务器正常关闭时执行,执行一次。
*/
public void destroy() {
System.out.println("destory......");
}
}
urlPatterns()配置
通过看注解的原码得知,urlPatterns()是一个数组,可以配置多个路径。
路径配置
-
配置多个路径之后,我们就可以在多个路径访问Servlet
-
- @WebServlet({“/demo4”,“/ddemo4”,“/dddemo4”})
-
路径配置规则
-
-
“/XXXX” 单层路径
-
“/XXXX/XXXX” 多层路径 ,目录结构
-
“/XXXX/*” *表示任意,即/XXXX/随意
-
“/*” 表示什么样的路径(除了其他已经配置的路径文件),都能访问到此文件
-
“*.do” 除了其他已经配置的路径文件,任意语录加上.do,即可访问到此文件
-
@WebServlet("*.do")
-
-
-
“/servlet” 虚拟路径开始http://localhost:8800/sevlet
- 虚拟路径,tomcat配置的路径。即/servlet开始
-
“/source/begin” 当前路径开始http://localhost:8800/sevlet/source/begin
- 当前接口路径,即/source/begin开始
以下两个方法时httpservlet
//serlvet 是tomcat配置的路径
String contextPath = req.getContextPath();
System.out.println(contextPath);
// /source/begin 是当前接口配置的路径
String servletPath = req.getServletPath();
System.out.println(servletPath);
@WebServlet注解
属性名 | 类型 | 描述 |
---|---|---|
name | String | 指定Servlet 的 name 属性,等价于 <servlet-name> 。如果没有显式指定,则该 Servlet 的取值即为类的全限定名。 |
value | String[] | 该属性等价于 urlPatterns 属性。两个属性不能同时使用。 |
urlPatterns | String[] | 指定一组 Servlet 的 URL 匹配模式。等价于<url-pattern> 标签。 |
loadOnStartup | int | 指定 Servlet 的加载顺序,等价于 <load-on-startup> 标签。 |
initParams | WebInitParam[] | 指定一组 Servlet 初始化参数,等价于<init-param> 标签。 |
asyncSupported | boolean | 声明 Servlet 是否支持异步操作模式,等价于<async-supported> 标签。 |
description | String | 该 Servlet 的描述信息,等价于 <description> 标签。 |
displayName | String | 该 Servlet 的显示名,通常配合工具使用,等价于 <display-name> 标签。 |
4. Servlet体系结构
GenericServlet:
将Servlet接口中其他的方法做了默认空实现,只将service( )方法作为抽象方法
将来定义Servlet类时,可以继承GenericServlet,实现service( )方法即可
public class ServletDemo extends GenericServlet {
/*
通过继承GenericServlet就可以单独实现service方法
但是不推荐使用这个
*/
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
System.out.println("GenericServlet.....");
}
}
HttpServlet:
对http协议的一种封装,简化操作
-
定义类继承HttpServlet
-
重写doGet/doPost及其它几种Http请求方法
当用户请求数据时,需要判断用户是以何种方式请求。判断这个请求方式是一个麻烦的过程。
HttpServlet中封装了对请求方式的判断,我们使用时只需要重写doGet()和doPost()以及其它我们需要的方法即可。
HttpServlet的service方法
通过请求方法的不同去执行对应的方法。
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
String method = req.getMethod();
long lastModified;
if (method.equals("GET")) {
lastModified = this.getLastModified(req);
if (lastModified == -1L) {
this.doGet(req, resp);
} else {
long ifModifiedSince = req.getDateHeader("If-Modified-Since");
if (ifModifiedSince < lastModified) {
this.maybeSetLastModified(resp, lastModified);
this.doGet(req, resp);
} else {
resp.setStatus(304);
}
}
} else if (method.equals("HEAD")) {
lastModified = this.getLastModified(req);
this.maybeSetLastModified(resp, lastModified);
this.doHead(req, resp);
} else if (method.equals("POST")) {
this.doPost(req, resp);
} else if (method.equals("PUT")) {
this.doPut(req, resp);
} else if (method.equals("DELETE")) {
this.doDelete(req, resp);
} else if (method.equals("OPTIONS")) {
this.doOptions(req, resp);
} else if (method.equals("TRACE")) {
this.doTrace(req, resp);
} else {
String errMsg = lStrings.getString("http.method_not_implemented");
Object[] errArgs = new Object[]{method};
errMsg = MessageFormat.format(errMsg, errArgs);
resp.sendError(501, errMsg);
}
}
重写doGet()方法
例如:浏览器直接访问
@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("get请求");
System.out.println(req.getParameter("username"));
System.out.println(req.getParameter("password"));
}
}
重写doPost()方法
例如:通过表单向后台发送数据。
@WebServlet("/demo2")
public class ServletDemo2 extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("post请求");
System.out.println(req.getParameter("username"));
System.out.println(req.getParameter("password"));
}
}
在webapp包下创建index.jsp。启动tomcat服务器,会默认访问该路径下的index文件。
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>$Title$</title>
</head>
<body>
<h1>Hello servlet</h1>
<a href="/servlet/demo1">please enter</a>
<div>
<a href="/servlet/blog/add">添加blog</a>
<br>
<a href="http://localhost:8899/servlet/blog/delete">删除blog</a>
<br>
<a href="/servlet/blog/update">修改blog</a>
<br>
<a href="/servlet/blog/query">查询blog</a>
</div>
<div>
<h1>post请求</h1>
<form action="/servlet/demo2" method="post">
<input name="username">
<input name="password">
<input type="submit" value="提交">
</form>
<h1>get请求</h1>
<form action="/servlet/demo2" method="get">
<input name="username">
<input name="password">
<input type="submit" value="提交">
</form>
</div>
</body>
</html>
创建servlet接口
运行:
控制台打印: