目录
2.Servlet访问动态资源(访问java代码逻辑)的原理简介
7.2 servletContext 和 servletConfig 异同点
1.绝对路径,以 / 开头 在页面上 / 代表从项目的部署目录开始找 2.页面的绝对路径要有项目名,除非我们的项目没有设置项目名
1.相对路径,凡事不以 / 开头 的就是相对路径,在页面上从web目录往下找
1Servlet介绍
Servlet是Server Applet的简称,称为服务端小程序,是JavaEE平台下的技术标准,基于Java语言编写的服务端程序。Web容器或应用服务器实现了Servlet标准所以Servlet需运行在Web容器或应用服务器中。Servlet主要功能在于能在服务器中执行并生成数据。
简言之,servlet是一个连接前后端,获取后端动态数据,展示在前端页面的技术。
1.1Servlet技术特点
Servlet使用单进程多线程方式运行。
1.2Servlet在应用程序中的位置
1.3静态资源和动态资源区分
静态资源: 每次访问都不需要运算,直接就可以返回的资源, 如HTML CSS JS 多媒体文件等等,每次访问获得的资源都是一样的
动态资源:每次访问都需要运算代码生成的资源,如Servlet JSP ,每次访问获得的结果可能都是不一样的
Servlet作为一种动态资源技术,是我们后续学习框架的基础
1.4Servlet在程序中到底处于一个什么地位?
Servlet是可以接受Http请求并作出响应的一种技术,是JAVA语言编写的一种动态资源
Servlet是前后端衔接的一种技术,Servlet在MVC模式中运行时,位于Controller层(控制层),用于和浏览器和java业务代码完成数据交互,控制交互逻辑
1.5 以来的maven仓
<dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>10.1.7</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>9.0.34</version> </dependency> <dependency> <groupId>jakarta.servlet</groupId> <artifactId>jakarta.servlet-api</artifactId> <version>5.0.0</version> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-core</artifactId> <version>9.0.63</version> </dependency>
2.Servlet访问动态资源(访问java代码逻辑)的原理简介
首先,如果是访问静态资源,完全不需要servlet,因为它是用来访问动态资源的技术。当然它肯定也兼容访问静态资源。
其次,明确一点,访问动态资源,说白了就是页面数据的展示,需要java代码逻辑运算,那就是说,需要前端页面和java代码交互。咋交互呢?是通过http协议框架交互的。
而servlet 就是提供一个httpServletRequest来接收http请求,通过配置将请求映射到对应的java数据处理逻辑的代码中(当然处理结果需要基于http协议给出响应),然后通过httpServletResponse来接收http请求的响应,再继续通过配置将请求响应映射到对应的前端页面。本质上是拦截了一下http请求和响应,所以servlet可以做拦截器。
<!--向Tomcat声明一个 Servlet-->
<servlet>
<servlet-name>myServlet</servlet-name><!--别名 外号-->
<servlet-class>com.mashibing.servlet.MyServlet</servlet-class><!-- 对应的Servlet类 -->
</servlet>
<!--给Servlet匹配一个请求的映射路径-->
<servlet-mapping>
<servlet-name>myServlet</servlet-name>
<url-pattern>/myServlet.do</url-pattern>
</servlet-mapping>
3.servlet的乱码问题解决
4.Servlet的继承结构
4.1Servlet接口
1.init()
Tomcat创建Servlet对象后立即调用该方法完成其他初始化工作
2.service()
接受前端请求,生产动态数据,返回给前端
3.destroy()
在销毁Servlet对象之前默认调用该方法,释放资源。
4.getServletConfig()
ServletConfig是容器向servlet传递参数的载体。
5.getServletInfo()
获取servlet相关信息
5.Servlet的生命周期
package org.cuitao; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class Servlet_1 extends HttpServlet { public Servlet_1() {// 构造一个Servlet对象的方法 System.out.println("org.cuitao.Servlet_1 Constructor invoked"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } @Override public void init() throws ServletException {// 初始化 System.out.println("org.cuitao.Servlet_1 init invoked"); try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } @Override protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { // 执行服务 System.out.println("org.cuitao.Servlet_1 service invoked"); } @Override public void destroy() {// 销毁 System.out.println("org.cuitao.Servlet_1 destory invoked"); } }
6.ServletContext
6.1概述
ServletContext官方叫Servlet上下文。Tomcat服务器会为每一个Web应用创建一个ServletContext对象。这个对象在自己的应用中全局唯一,而且自己的Web应用中的所有Servlet都共享这个对象。所以叫全局应用程序共享对象
6.2如何获取servletContext
6.3作用
主要是获取servlet配置信息(比如web.xml中的信息)和作为 web应用的全局变量来用
6.2.1获取配置信息
6.2.2作为web应用的全局变量使用
7.ServletConfig
7.1概述
ServletConfig对象对应web.xml文件中的<servlet>节点。当Tomcat初始化一个Servlet时,会将该Servlet的配置信息,封装到一个ServletConfig对象中。我们可以通过该对象读取<servlet>节点中的配置信息。
7.2 servletContext 和 servletConfig 异同点
7.3如何获取servletConfig
7.4作用
获取对应<Servlet>标签中的参数
<servlet>
<servlet-name>servletConfig</servlet-name>
<servlet-class>org.cuitao.ServletConfigDemo</servlet-class>
<init-param>
<param-name>lianxiang</param-name>
<param-value>LIAN-XIANG</param-value>
</init-param>
<init-param>
<param-name>jingdongfang</param-name>
<param-value>JING-DONG-FANG</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>servletConfig</servlet-name>
<url-pattern>/servletConfig.aaa</url-pattern>
</servlet-mapping>
package org.cuitao;
import javax.servlet.ServletConfig;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
public class ServletConfigDemo extends HttpServlet {
@Override
public void service(HttpServletRequest request, HttpServletResponse response) {
//只能通过继承的方式获取
ServletConfig servletConfig = this.getServletConfig();
System.out.println("servletConfig.getServletName() =\n" +
" " + servletConfig.getServletName());
System.out.println("servletConfig.getInitParameter(\"lianxiang\") = \n" +
"" + servletConfig.getInitParameter("lianxiang"));
Enumeration<String> initParameterNames = servletConfig.getInitParameterNames();
while (initParameterNames.hasMoreElements()){
System.out.println("initParameterNames.nextElement() = \n"
+ initParameterNames.nextElement());
}
}
}
8.URL的匹配规则
8.1 5种匹配方式
1.精确匹配
精确匹配是指<url-pattern>中配置的值必须与url完全精确匹配。
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>/demo.do</url-pattern>
</servlet-mapping>
http://localhost:8888/demo/demo.do 匹配
http://localhost:8888/demo/suibian/demo.do 不匹配
2.扩展名匹配(后缀名匹配)
在<url-pattern>允许使用通配符 “*” 作为匹配规则,“*” 表示匹配任意字符。在扩展名匹配中只要扩展名相同都会被匹配和路径无关。注意,在使用扩展名匹配时在<url-pattern>中不能使用“/”,否则容器启动就会抛出异常。
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
http://localhost:8888/demo/abc.do 匹配
http://localhost:8888/demo/suibian/haha.do 匹配
http://localhost:8888/demo/abc 不匹配
3.路径匹配
根据请求路径进行匹配,在请求中只要包含该路径都匹配。“*”表示任意路径以及子路径。
<servlet-mapping>
<servlet-name>demoServlet</servlet-name>
<url-pattern>/suibian/*</url-pattern>
</servlet-mapping>
http://localhost:8888/demo/suibian/haha.do 匹配
http://localhost:8888/demo/suibian/hehe/haha.do 匹配
http://localhost:8888/demo/hehe/heihei.do 不匹配
4.任意匹配
匹配“/”。匹配所有但不包含JSP页面
<url-pattern>/</url-pattern>
http://localhost:8888/demo/suibian.do匹配
http://localhost:8888/demo/addUser.html匹配
http://localhost:8888/demo/css/view.css匹配
http://localhost:8888/demo/addUser.jsp不匹配
http://localhost:8888/demo/user/addUser.jsp不匹配
5.匹配所有
<url-pattern>/*</url-pattern>
http://localhost:8888/demo/suibian.do匹配
http://localhost:8888/demo/addUser.html匹配
http://localhost:8888/demo/suibian/suibian.do匹配
8.2 匹配优先级
优先顺序
当一个url与多个Servlet的匹配规则可以匹配时,则按照 “ 精确路径 > 最长路径 >扩展名”这样的优先级匹配到对应的Servlet。
案例分析
Servlet1映射到 /abc/*
Servlet2映射到 /*
Servlet3映射到 /abc
Servlet4映射到 *.do
当请求URL为“/abc/a.html”,“/abc/*”和“/*”都匹配,Servlet引擎将调用Servlet1。
当请求URL为“/abc”时,“/abc/*”和“/abc”都匹配,Servlet引擎将调用Servlet3。
当请求URL为“/abc/a.do”时,“/abc/*”和“*.do”都匹配,Servlet引擎将调用Servlet1。
当请求URL为“/a.do”时,“/*”和“*.do”都匹配,Servlet引擎将调用Servlet2。
当请求URL为“/xxx/yyy/a.do”时,“/*”和“*.do”都匹配,Servlet引擎将调用Servlet2。
8.3 映射方式
在web.xml文件中支持将多个URL映射到一个Servlet中,但是相同的URL不能同时映射到两个Servlet中。
方式一,相当于是特殊 情况下的简化写法
9.基于注解式开发Servlet
package org.cuitao;
import javax.servlet.ServletConfig;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(name = "name",
urlPatterns = "/annotate/*",
loadOnStartup = 1,
initParams = {@WebInitParam(name = "flag1", value = "flag1value"), @WebInitParam(name = "flag2", value = "flag2value")},
asyncSupported = true,
description = "description",
displayName = "displayName")
public class Servlet1 extends HttpServlet {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
System.out.println("request = " + "111111111111");
ServletConfig servletConfig = this.getServletConfig();
System.out.println("servletConfig.getServletName() = " + servletConfig.getServletName());
System.out.println("servletConfig.getInitParameter(\"flag1\") = " + servletConfig.getInitParameter("flag1"));
System.out.println("servletConfig.getInitParameterNames() = " + servletConfig.getInitParameterNames());
}
}
10请求转发
10.1请求转发的两种方式
forward方式
1获取请求参数
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Auther: cuitao
* @Date: 2023/6/27 - 06 - 27 - 11:03
* @Description: PACKAGE_NAME
*/
@WebServlet(urlPatterns = "/servlet1.do")
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
System.out.println("servlet1 service invoked");
String money = req.getParameter("money");
System.out.println("money:"+money);}}
2.转发
3.响应数据来源分析
首先响应数据都是存在response中的,表现为resp.getWriter().println(“要响应的数据”),
其次,由forward的请求流图克制,请求完全托管给servlet2,servlet1根本不对请求做任何的处理。
事实上,forward底层为了实现这一逻辑,servlet1一旦有转发处理操作出现就会把 servlet1的response中的数据清空,并且再转发后,存储的数据,底层也会清空,也就是再也存不进去。所有的响应都交给servlet2去处理。servlet1不能再干预。
include方式
清空
1.include请求转发和forward请求转发的区别
区别1:转发方式不同
forward转发后啥都就不管了,由接收转发的对象去处理响应并返回给请求源
include转发后,还需要接收servlet2返回的响应,然后自己(可以继续处理)再把结果返回给源。也因此,include 底层没有把转发前后的response给清空,还保留着。
区别2:写法不同
RequestDispatcher requestDispatcher = req.getRequestDispatcher("servlet2.do");
requestDispatcher.include(req, resp);
RequestDispatcher requestDispatcher = req.getRequestDispatcher("servlet2.do");
requestDispatcher.forward(req, resp);
2.include案例
可以看到全给响应出来了
10.2请求转发的注意项
1请求转发是一种服务器的行为,因此浏览器的地址栏不会发生变化
2请求转发可以进行站内页面的跳转
3.请求转发可以转发至WEB-INF里【虽然WEB-INF中的数据受保护,但是可以通过请求转发的方式获取】
4.请求转发只能转发给当前项目的内部不能转发至外部资源
11 重定向
11.1概述
生活案例:
张三向李四借钱1000元,李四说”我也没有,要不你去王五哪里看看?”,然后张三根据李四的指示,去找王五借钱
响应重定向是通过HttpServletResponse对象sendRedirect(“路径”)的方式实现是,是服务器通知浏览器,让浏览器去自主请求其他资源的一种方式
重定向的运作流程
1用户在浏览器端输入特定URL,请求访问服务器端的某个Servlet。
2服务器端的Servlet返回一个状态码为302的响应结果,该响应结果的含义为:让浏览器端再请求访问另一个Web资源,在响应结果中提供了另一个Web资源的URL。另一个Web资源有可能在同一个Web服务器上,也有可能不再同一个Web服务器上。
3当浏览器端接收到这种响应结果后,再立即重新组织参数,自动请求访问另一个Web资源。
4浏览器端接收到另一个Web资源的响应结果。
11.2 重定项的案例
package org.example;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
/**
* @Author: Ma HaiYang
* @Description: MircoMessage:Mark_7001
*/
@WebServlet(urlPatterns = "/servlet1.do")
public class Servlet1 extends HttpServlet {
@Override
protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
resp.setCharacterEncoding("UTF-8");
resp.setContentType("text/html;charset=UTF-8");
// resp.sendRedirect("https://www.baidu.com/");
resp.sendRedirect("aaa.html");
}
}
11.3重定向和请求转发的异同
1重定向是服务器给浏览器重新指定请求方向 是一种浏览器行为,因此 地址栏会发生变化,而转发时地址栏不会变
2重定向时,请求对象和响应对象都会再次产生,请求中的参数是不会携带,转发时是一套参数,携带着转发
3.重定向可以定向到外部资源
4.重定向不能访问 WEB-INF中的资源 (已经过测试)
12.路径问题
12.1 web页面路径问题
12.1.1绝对路径写法
1.绝对路径,以 / 开头 在页面上 / 代表从项目的部署目录开始找
2.页面的绝对路径要有项目名,除非我们的项目没有设置项目名
12.2相对路径写法
1.相对路径,凡事不以 / 开头 的就是相对路径,在页面上从web目录往下找
12.2请求转发路径问题
12.2.1绝对路径写法
以web为基准,按绝对路径的写法往下写
12.2.2相对路径写法
以web为基准,按相对路径的写法往下写
12.3响应重定向路径问题
12.3.1 绝对对路径写法
以web为基准,项目名+绝对路径
12.3.2 相对对路径写法
以web为基站,按照相对路径的写法(不以/开头)往下写