Servlet
1.Servlet简介
Servlet是运行在Web服务器上的应用程序。Servlet本身是一个Java接口,它定义了浏览器访问服务器程序的规则,我们写服务器程序只需要按照需求复写Servlet方法即可。
2.Servlet实现方法
第一种
实现Servlet接口,实现所有的抽象方法,该方式支持最大程度的自定义
第二种
继承GeneriServlet抽象类,必须重写service方法,其他方法可以选择重写,该方式让我们开发Servlet变得简单,但是这种方式和HTTp协议无关
第三种
继承HTTPServlet抽象类,需要重写doGet和doPost方法,该方法表示请求和响应都需要和HTTP协议相关
3.Servlet的生命周期
对象的生命周期:对象从出生到死亡
出生:第一次到servlet时,对象就创建出来,并初始化,只创建一次,将对象放入内存中
活着:每次执行service方法
死亡:服务停止的时候
访问Servlet会先执行init方法,在执行service方法,当服务器关闭的时候,destroy执行了
4.Servlet的线程安全问题
结论:Servlet是线程不安全的
解决:如果是公用的,并且只会在初始化赋值,其他时间都是获取值的时候,没有问题。如果不是公用的,或者每次都有可能赋值,就要考虑线程安全问题。可以将其定义到doGet或者doPost方法内或者使用同步代码块
5.Servlet映射方式
第一种:
具体名称的方式。访问的资源路径必须和映射配置相同
<servlet>
<servlet-name>servletDemo05</servlet-name>
<servlet-class>com.itheima.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo05</servlet-name>
<url-pattern>/servletDemo05</url-pattern>
</servlet-mapping>
第二种:
/开头 + 通配符的方式。只要符合目录结构即可,不需要考虑什么
<servlet>
<servlet-name>servletDemo05</servlet-name>
<servlet-class>com.itheima.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo05</servlet-name>
<url-pattern>/servlet/*</url-pattern>
</servlet-mapping>
第三种:
通配符 + 固定格式结尾的方式。只要符合固定结尾格式即可,不需要考虑前面的路径
<servlet>
<servlet-name>servletDemo05</servlet-name>
<servlet-class>com.itheima.servlet.ServletDemo05</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>servletDemo05</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
优先级:第一种>第二种>第三种
6.Servlet创建时机
第一次访问时创建:
优势:减少对服务器内存的浪费,提高了服务器的效率
弊端:如果有一些要在加载时就做初始化操作,就无法完成
服务器加载时创建:
优势:提前创建好对象,提高了首次执行的效率。可以完成一些应用加载时需要做的初始化操作
弊端:对服务器内存占用较多,影响了服务器启动的效率
修改Servlet创建时机,在<servlet> 标签中,添加<load-on-startup>1</load-on-startup>
正整数代表服务器加载时创建,值越小,优先级越高,负整数或者不写代表第一次访问时创建
<servlet>
<servlet-name>ServletDemo4</servlet-name>
<servlet-class>com.itheima.servlet.ServletDemo4</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>ServletDemo4</servlet-name>
<url-pattern>/ServletDemo4</url-pattern>
</servlet-mapping>
7.Servlet的执行流程
从浏览器发送请求给服务器,到服务器处理Servlet作出响应的流程,如图所示
8.Servlet体系结构
-
HttpServletRequest对象
当浏览器访问服务器时,tomcat会对Http请求的数据进行解析,并封装为HttpServletRequest对象
-
HttpServletReponse对象
当服务器给浏览器返回数据时,需要将数据封装为HttpServletReponse对象,然后用流往浏览器进行输出。
ServletConfig
1.ServletConfig 介绍
1.ServletConfig是Servlet的配置对象,在Servlet的规范中,允许每一个Servlet都提供一些初始化的配置
2.作用:在Servlet初始化时,把一些配置信息传递给Servlet(通过键值对配置)
3.生命周期:和Servlet相同
2.ServletConfig 配置方式
在<servlet>标签中,通过<init-param>标签来配置,有俩个子标签
<param-name>encoding</param-name>:代表初始化参数的key
<param-value>UTF-8</param-value>:代表初始化参数的value
3.ServletConfig 常用方法
public String getInitParameter(String name)
根据参数的名称回去参数的值
public Enumeration<String> getInitParameterNames()
获取所以的参数名称的枚举
public String getServletName()
获取Servlet的名称
public ServletContext getServletContext()
获取ServletContext对象
- 给ServletConfigDemo1配置初始化参数
<servlet>
<servlet-name>servlerConfigDemo1</servlet-name>
<servlet-class>com.itheima.servletconfig.ServletConfigDemo1</servlet-class>
<!--Servlet初始化参数-->
<init-param>
<param-name>encoding</param-name>
<param-value>utf-8</param-value>
</init-param>
<init-param>
<param-name>desc</param-name>
<param-value>这是一个ServletConfigDemo</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servlerConfigDemo1</servlet-name>
<url-pattern>/servlerConfigDemo1</url-pattern>
</servlet-mapping>
- 获取ServletConfigDemo1的初始化参数
public class ServletConfigDemo extends HttpServlet {
private ServletConfig servletConfig;
@Override
public void init() throws ServletException {
//获取ServletConfig
this.servletConfig = getServletConfig();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取所有的配置名称
Enumeration<String> keys = servletConfig.getInitParameterNames();
while (keys.hasMoreElements()) {
String key = keys.nextElement();
//根据配置名称获取值
String value = servletConfig.getInitParameter(key);
//打印键和值
System.out.println(key+"..."+value);
}
//获取ServletConfig(下面有讲是什么意思)
ServletContext servletContext = servletConfig.getServletContext();
System.out.println(servletContext);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
ServletContext
1.获取方式
1通过request对象获取
request.getServletContext();
2. 通过HttpServlet获取
this.getServletContext();
2.ServletContext 配置全局初始化参数
在<web-app>标签中,通过<context-param>标签来配置,有俩个子标签
<param-name>globalEncoding</param-name>:代表全局初始化参数的key
<param-value>UTF-8</param-value>:代表全局初始化参数的value
配置全局参数
<!--配置全局编码-->
<context-param>
<param-name>globalEncoding</param-name>
<param-value>utf-8</param-value>
</context-param>
<!--配置全局描述信息-->
<context-param>
<param-name>globalDesc</param-name>
<param-value>utf-8</param-value>
</context-param>
获取全局参数
//获取ServletContext
ServletContext servletContext = getServletContext();
//获取全局参数globalEncoding的值
String globalEncofing = servletContext.getInitParameter("globalEncoding");
System.out.println(globalEncofing);
//获取全局参数globalDesc的值
String globalDesc = servletContext.getInitParameter("globalDesc");
System.out.println(globalDesc);
3.ServletContext 常用方法
public String getInitParamteter(String name)
根据名称获取全局配置的参数
public String getContextPath()
获取当前应用的访问的虚拟目录
public String getRealPath(String path)
根据虚拟目录获取应用部署的磁盘绝对路径
public void setAttribute(String name,Object value)
向应用域对象存储数据
public Object getAttribute(String name)
通过名称获取应用域对象的数据
public void removeAttribute(String name)
通过名称移除应用域对象中的数据
获取真实路径
//获取ServletContext对象
ServletContext servletContext = req.getServletContext();
//虚拟目录
String contextPath = servletContext.getContextPath();
System.out.println(contextPath);
//获取虚拟目录的绝对路径
String servletContextRealPath = servletContext.getRealPath("/");
System.out.println(servletContextRealPath);
//获取web/a.txt的绝对路径
String webPath = servletContext.getRealPath("/a.txt");
System.out.println(webPath);
//获取web/WEB-INF/a.txt的绝对路径
String webInfPath = servletContext.getRealPath("/WEB-INF/a.txt");
System.out.println(webInfPath);
//获取src/a.txt的绝对路径
String srcPath = servletContext.getRealPath("WEB-INF/classes/a.txt");
System.out.println(srcPath);
Servlet间数据共享
- 在Servlet1中设置数据
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置共享数据
servletContext.setAttribute("username","zhangsan");
servletContext.setAttribute("password","123");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
- 在Servlet2中获取数据
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取username的值
Object username = servletContext.getAttribute("username");
System.out.println(username);
//获取password的值
Object password = servletContext.getAttribute("password");
System.out.println(password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
```# ServletContext
### 1.获取方式
```java
1通过request对象获取
request.getServletContext();
2. 通过HttpServlet获取
this.getServletContext();
2.ServletContext介绍
1.ServletContext是应用上下文对象(应用域对象)。每一个应用只有一个ServletContext对象
2.作用:可以配置和获取全局初始化参数,可以实现Servlet之间的数据共享
3.生命周期:应用一加载则创建,应用被停止则销毁
域对象
域对象指的是对象有作用域,也就是作用范围。域对象可以实现数据共享。不同作用范围的域对象,共享数据的能力也是不一样的
在Servlet规范中,一共有四个域对象,ServletContext就是其中一个,他也是web应用中最大的作用域,也叫application域,他可以实现整个应用之间的数据共享
3.ServletContext 配置全局初始化参数
在<web-app>标签中,通过<context-param>标签来配置,有俩个子标签
<param-name>globalEncoding</param-name>:代表全局初始化参数的key
<param-value>UTF-8</param-value>:代表全局初始化参数的value
配置全局参数
<!--配置全局编码-->
<context-param>
<param-name>globalEncoding</param-name>
<param-value>utf-8</param-value>
</context-param>
<!--配置全局描述信息-->
<context-param>
<param-name>globalDesc</param-name>
<param-value>utf-8</param-value>
</context-param>
获取全局参数
//获取ServletContext
ServletContext servletContext = getServletContext();
//获取全局参数globalEncoding的值
String globalEncofing = servletContext.getInitParameter("globalEncoding");
System.out.println(globalEncofing);
//获取全局参数globalDesc的值
String globalDesc = servletContext.getInitParameter("globalDesc");
System.out.println(globalDesc);
4.ServletContext 常用方法
public String getInitParamteter(String name)
根据名称获取全局配置的参数
public String getContextPath()
获取当前应用的访问的虚拟目录
public String getRealPath(String path)
根据虚拟目录获取应用部署的磁盘绝对路径
public void setAttribute(String name,Object value)
向应用域对象存储数据
public Object getAttribute(String name)
通过名称获取应用域对象的数据
public void removeAttribute(String name)
通过名称移除应用域对象中的数据
获取真实路径
//获取ServletContext对象
ServletContext servletContext = req.getServletContext();
//虚拟目录
String contextPath = servletContext.getContextPath();
System.out.println(contextPath);
//获取虚拟目录的绝对路径
String servletContextRealPath = servletContext.getRealPath("/");
System.out.println(servletContextRealPath);
//获取web/a.txt的绝对路径
String webPath = servletContext.getRealPath("/a.txt");
System.out.println(webPath);
//获取web/WEB-INF/a.txt的绝对路径
String webInfPath = servletContext.getRealPath("/WEB-INF/a.txt");
System.out.println(webInfPath);
//获取src/a.txt的绝对路径
String srcPath = servletContext.getRealPath("WEB-INF/classes/a.txt");
System.out.println(srcPath);
Servlet间数据共享
- 在Servlet1中设置数据
public class Servlet1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//设置共享数据
servletContext.setAttribute("username","zhangsan");
servletContext.setAttribute("password","123");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
- 在Servlet2中获取数据
public class Servlet2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取username的值
Object username = servletContext.getAttribute("username");
System.out.println(username);
//获取password的值
Object password = servletContext.getAttribute("password");
System.out.println(password);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
注解开发Servlet
我们发现,每次写一个Servlet都需要在web.xml文件中写大量的配置,非常麻烦。好消息来了,在Servlet3.0以后的版本提供了Servlet注解配置,大大简化了代码编写。
//@WebServlet注解配置Servlet访问路径
@WebServlet("/servletDemo5")
public class ServletDemo5 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet执行了");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req,resp);
}
}
浏览器直接访问 http://localhost:8080/day02_servlet/servletDemo5就可以了