目录
ServletContext类 (全局的初始化参数 | 全局域对象 | 资源真实路径)
一、Servlet的概念
Web资源就是运行在服务器上的资源,它一共分为两类::
静态资源:html css js 图片...
动态资源 :通过代码控制展示的动态数据。
什么是Servlet?
1. Servlet 是sun公司提供的一套定义动态资源的规范 (接口)。
2. Servlet 是JavaWeb三大组件之一。(Servlet程序 Filter过滤器 Listener监听器)
3. Servlet 是运行在服务器上的一个Java小程序,用来接收客服端送过来的请求,并响应数据给客户端。 (服务员)
准备工作:导入jar包,模块添加依赖
编写 Hello Servlet
1. 编写一个类去实现Servlet接口,重写方法
2. 实现service方法,处理请求,并响应数据 (不要用中文)
3. 到web.xml中配置servlet程序的访问地址
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>HelloServlet</h1>
<a href="helloServlet">点我</a>
</body>
</html>
public class HelloServlet 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("HelloServlet!");
//调用业务层方法(暂略)
//反馈信息到客户端 (此时中文会乱码!!)
servletResponse.getWriter().println("Success!");
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
}
}
<?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_4_0.xsd"
version="4.0">
<!--配置HelloServlet的映射路径 -->
<servlet>
<!--给Servlet取名,建议使用类名-->
<servlet-name>HelloServlet</servlet-name>
<!--配置的Servlet的全类名,Tomcat内部的Servlet容器通过反射创建Servlet对象-->
<servlet-class>com.atguigu.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>HelloServlet</servlet-name>
<!--拦截路径-->
<url-pattern>/helloServlet</url-pattern>
</servlet-mapping>
</web-app>
- 常见错误1:url-pattern 中配置的路径没有以斜杠打头。
- 常见错误2:servlet-name 配置的值不存在。(打错字)
Web 概念梳理
原生Tomcat
安装在电脑上的实实在在的Tomcat软件
IDEA中的Tomcat实例
通过idea的配置在idea上集成的Tomcat实例,其实还是使用的原生的Tomcat软件
IDEA中的Web工程
程序员使用IDEA编写的动态Web工程,该工程只是用于程序员编码,实际上部署运行在Tomcat服务器中的并不是这个工程。
根据Web工程生成的war包
根据程序员创建的动态Web工程,IDEA会将其打包成一个war包,而真正部署运行在Tomcat服务器中的其实是war包。
访问资源的地址
访问静态资源:/Web应用名称/静态资源本身的路径(就是静态资源在web文件夹中的路径)
访问动态资源:/Web应用名称/映射路径
Web应用名称(项目名)
注意Web应用名不是你工程或者Module的名字,而是你在部署时候的ApplicationContext的内容
工程目录 vs 部署目录
部署目录:一般在out文件夹内
二、Servlet 的生命周期
Servlet在容器中是单例的、线程不安全的。(尽量不要修改成员变量、通过成员变量判断)
① Servlet对象的创建:构造器
-
默认情况下,Tomcat内的Servlet容器第一次收到HTTP请求时创建对应Servlet对象。
-
容器之所以能做到这一点是由于我们在注册Servlet时提供了全类名,容器使用反射技术创建了Servlet的对象。
② Servlet对象初始化:init()
-
Servlet容器创建Servlet对象之后,会调用init(ServletConfig config)方法。
-
init()方法只在创建对象时执行一次,以后再接到请求时,就不执行了
-
可以通过<load-on-startup>X</load-on-startup> 设置初始化时机,X值越小启动越早。
③ 处理请求:service()
-
service(ServletRequest req, ServletResponse res)方法处理HTTP请求。在每次接到请求后都会执行。Servlet的作用,主要在此方法中体现。(由Toncat容器调用)
④ Servlet对象销毁:destroy()
-
服务器重启、服务器停止执行或Web应用卸载时会调用public void destroy()方法,销毁Servlet对象。
-
此方法用于销毁之前执行一些诸如释放缓存、关闭连接、保存内存数据持久化等操作。
/**
* 注解的方式访问Servl(暂时了解)
* @Author by:Plisetsky
*/
@WebServlet("/anno")
public class AnnoServlet implements Servlet {
//Servlet对象由Tomcat内部的Servlet容器通过反射创建
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//init()只会执行一次,可以处对处理请求做准备。
}
@Override
public ServletConfig getServletConfig() {
return null;
}
@Override
public void service(ServletRequest servletRequest, ServletResponse servletResponse) throws ServletException, IOException {
//处理请求的逻辑写在此处,每一次请求都会执行
}
@Override
public String getServletInfo() {
return null;
}
@Override
public void destroy() {
//关闭、重启服务器,会导致Servlet销毁,可以进行关闭资源操作
}
}
ServletConfig的介绍
在web.xml中对Servlet配置的初始化参数,可以在Servlet的init()方法中获取初始化参数的值。
方法名 | 作用 |
---|---|
getServletName() | 获取<servlet-name>HelloServlet</servlet-name>定义的Servlet名称 |
getServletContext() | 获取ServletContext对象 |
getInitParameter() | 获取配置Servlet时设置的『初始化参数』,根据名字获取值 |
getInitParameterNames() | 获取所有初始化参数名组成的Enumeration对象 |
代码:
web.xml 内设置参数: <init-param>
<servlet>
<servlet-name>Servlet</servlet-name>
<servlet-class>com.atguigu.setvlet.Servlet1</servlet-class>
<!--配置初始化参数-->
<init-param>
<param-name>uname</param-name>
<param-value>zs</param-value>
</init-param>
<init-param>
<param-name>pwd</param-name>
<param-value>123456</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Servlet</servlet-name>
<url-pattern>/test1</url-pattern>
</servlet-mapping>
servlet init()内获取参数
public class Servlet1 implements Servlet {
@Override
public void init(ServletConfig servletConfig) throws ServletException {
//获取初始化参数
//getInitParameter: 根据name获取value
String unameValue = servletConfig.getInitParameter("uname");
String pwdValue = servletConfig.getInitParameter("pwd");
System.out.println(unameValue + "-->" + pwdValue);//zs-->123456
//getInitParameterNames: 获取所有初始化参数的名字
Enumeration<String> names = servletConfig.getInitParameterNames();
while (names.hasMoreElements()){
String name = names.nextElement();
//根据name获取value
String value = servletConfig.getInitParameter(name);
System.out.println(name+ "-->" + value);//uname-->zs pwd-->123456
}
}
三、Servlet体系结构 (HttpServlet)
创建Servlet时,继承 HttpServlet 需要处理什么业务,重写什么方法。
doGet()
doPost()
使用IDEA创建Servlet
之后添加 <servlet-mapping> 即可,如果没有该选项参考:IDEA——万能青年操作指南_焰火青年·的博客-CSDN博客
public class Servlet3Http extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("do Get 执行了...");
resp.getWriter().println("get Success");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("do Post 执行了...");
resp.getWriter().println("Post Success");
}
}
ServletContext类 (全局的初始化参数 | 全局域对象 | 资源真实路径)
1.ServletContext是一个接口,它表示Servlet上下文对象
2.一个web工程,只有一个ServletContext对象实例
3.ServletContext对象是一个域对象。
4.ServletContext是在web工程部署启动的时候创建。在web工程停止的时候销毁。
-
一、ServletContext获取全局的初始化参数
web.xml
<!--配置全局初始化参数-->
<context-param>
<param-name>username</param-name>
<param-value>123456</param-value>
</context-param>
//获取全局初始化参数,通过servletContext对象
String username = servletContext.getInitParameter("username");
-
二、ServletContext作为全局的域对象
域对象,是可以像Map一样存取数据的对象。
域对象就是在一定的作用域范围内进行数据共享的对象,ServletContext 作为全局域对象可以在整个项目的所有动态资源(包含所有Servlet)中进行数据共享。
存数据 取数据 删数据
Map put() get() remove()
域对象 setAttribute() getAttribute() removeAttribute()
public class Servlet4Context extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("一、获取servletContext的三种方式");
//1.获取servletContext上下文(全局)对象
ServletContext s1 = getServletContext();
System.out.println("s1 =" + s1);
//2.通过请求对象来获取
ServletContext s2 = req.getServletContext();
System.out.println("s2 = " + s2);
//3.通过ServletConfig 获取
ServletContext s3 = getServletConfig().getServletContext();
System.out.println("s3 = " + s3);
System.out.println("二、全局初始化参数");
//获取全局初始化参数 可以被全局共享 所有Servlet共享,一个程序只有一个
String value = s3.getInitParameter("username");
System.out.println("username----> "+value);
System.out.println("三、全局域");
//向全局域中添加值
s1.setAttribute("hero","安其拉");
//获取全局域中的值
Object hero = s2.getAttribute("hero");
System.out.println("hero = " + hero);
}
}
-
三、获取资源的真实路径
工程目录:
部署目录:
public class Servlet5Attribute extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
//获取全局上下文对象
ServletContext s1 = req.getServletContext();
//获取资源在部署目录的路径 (只有部署到服务器中的文件才可以被访问)
String realPath = s1.getRealPath("/img/wH6gilRG.png");
System.out.println("realPath = " + realPath);
//E:\代码\World\out\artifacts\day07Servlet_war_exploded\img\wH6gilRG.png
}
}
四、Servlet的三种映射路径的配置
一个Servlet可以配置多个映射路径,但是多个Servlet不能配置相同的映射路径
映射路径的分类:完全路径匹配、目录匹配、扩展名匹配
web.xml
<!--完全路径匹配 -->
<servlet-mapping>
<servlet-name>ServletPath1</servlet-name>
<url-pattern>/path1</url-pattern>
</servlet-mapping>
<!--路径模糊匹配(目录匹配) /xxx/* 能够匹配所有`/xxx/任意字符串`的请求路径-->
<servlet-mapping>
<servlet-name>ServletPath2</servlet-name>
<url-pattern>/path1/*</url-pattern>
</servlet-mapping>
<!--后缀名匹配(扩展名匹配) *.xxx 能够匹配所有以`.相同扩展名`结尾的请求路径-->
<servlet-mapping>
<servlet-name>ServletPath3</servlet-name>
<url-pattern>*.path</url-pattern>
</servlet-mapping>
Servlet实现类
public class ServletPath1 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("完全路径匹配");
response.getWriter().println("success!");
}
}
public class ServletPath2 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("路径模糊匹配(目录匹配)");
response.getWriter().println("success!");
}
}
public class ServletPath3 extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("后缀名匹配(扩展名匹配)");
response.getWriter().println("success!");
}
}
index.html
<body>
<h1>路径匹配规则</h1>
<a href="path1">完全路径匹配</a>
<a href="path1/12345">路径模糊匹配(目录匹配)</a>
<a href="12345.path">后缀名匹配(扩展名匹配)</a>
</body>
url(统一资源定位符) 与 uri(统一资源标识符)
url:既可以访问本项目资源 也可以访问其他项目资源
uri:标记【当前项目】下的资源 (使用url访问本项目资源,地址太长了,省略一点)
url:统一资源定位符
协议 主机名 端口号 应用名/项目名 资源名
http://localhost:8080/day06Servlet/success.html
既可以访问本项目资源 也可以访问其他项目资源<a href="http://localhost:8080/day06Servle/success.html">Success</a> <a href="http://localhost:8080/day06Servlet/s"> SecondServlet</a> <a href="http://www.baidu.com">百度一下</a>
uri:统一资源标识符
标记【当前项目】下的资源
/应用名/资源名
<a href="/day06Servlet/success.html">Success</a> <br>
<a href="/day12Servlet/s"> SecondServlet</a>
Web中的相对路径和绝对路径
- 相对路径:相对自身资源而言
. 表示当前目录
../ 表示上一级目录
资源名 表示当前目录下/资源名
-
绝对路径:永远以"/"开头。(建议使用)
-
/ 如果被浏览器解析,得到的地址是: http://ip:port/ (服务器根目录)
-
使用时需要加上 / 应用名(项目名)/ 资源名
http://ip:port/工程路径/资源路径
动态获取上下文路径(部署的项目名)
上下文路径(context path)=/Web应用名称
在使用资源的uri路径中使用绝对路径,项目名一旦修改,将无法定位资源(404)。
request.getContextPath()
public class ServletPath4ContextPath extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
System.out.println("动态获取上下文路径(项目名)");
//响应一个 a标签到客户端,一旦项目名修改会报错(404)
// http://localhost:8080/day07ServletPath/success.html
// response.getWriter().println("<a href="/day07ServletPath/success.html">成功界面</a>");
//获取 /应用名 /day07ServletPath
String contextPath = request.getContextPath();
System.out.println("contextPath = " + contextPath);
response.getWriter().println("<a href='"+contextPath+"/success.html'>成功界面</a> ");
}
<body>
<h1>路径匹配规则</h1>
<a href="contextPath">动态获取上下文路径(项目名)</a> <br>
<a href="/day07ServletPath/success.html">Success</a>
</body>