- 什么是 Servlet?先让工夫回到 25 年前,我国刚刚接入互联网不到两年工夫。那时候的电脑长这个样子:
过后的网页技术还不是很发达,大家关上浏览器只能浏览一些动态的页面,例如图片、文本信息等。
随着工夫的倒退,动态页面曾经不能满足于大部分用户的需要了。用户关上浏览器不能只浏览个图片和文字吧?用户还想提交个表单、点个按钮、还想和浏览器做交互怎么办?为了解决用户和浏览器动静交互的问题,到了 1997 年,SUN 公司(创造了 JDK) 推出了 Servlet 技术。Servlet 是一个基于 Java 技术开发的 web 组件,它运行在服务器端,由 Servlet 容器治理。次要用于解决用户的申请并生成动静的信息。
Servlet 其实就是依照 Servlet 标准编写的一个 Java 类。咱们晓得一个类要想独立运行必须要有 main 办法,然而 Servlet 这个类没有 main 办法。那怎么运行?答案是放到 servlet 容器里运行。你能够把 servlet 看成是一个个的 app , 而手机就相当于一个 servlet 容器。app 不能独自运行,必须放在手机上运行。
servlet 因为没有 main 办法,也不能独立运行,必须放在 servlet 容器外面运行。
- Tomcat 的装置和应用 2.1 Tomcat 简介后面咱们讲到 servlet 必须放到 servlet 容器外面运行,而 Tomcat 就是一个能够运行 servlet 的容器。为什么举荐应用 Tomcat?因为它收费、开源、好用。Tomcat 响应用户申请的过程如下:用户通过浏览器向 Tomcat(web 服务器)发送一个 HTTP 申请。Tomcat 接管到申请后,将申请信息发送给 Servlet 容器,并交给 servlet 容器一个申请对象和一个响应对象。Servlet 容器加载 Servlet,先创立一个 Servlet 实例。而后通知这个 servlet 实例说:嘿!小伙,我这里有一个用户的申请对象和响应对象,你来解决一下。Servlet 实例从申请对象拿到客户端的申请信息,而后进行相应的解决。Servlet 实例将处理结果交给响应对象,通过响应对象发送到客户端。
注:申请对象:HttpServletRequest 响应对象:HttpServletResponse2.2 Tomcat 的装置与配置注:装置 Tomcat 之前须要先装置配置 JDK。下载解压链接:https://pan.baidu.com/s/1Ey-g…
提取码:1234
复制代码启动 tomcat 进入 bin 目录下,双击 startup.sh
关上浏览器,输出:http://localhost:8080/
复制代码当呈现如下画面,阐明你装置胜利了!!! -
Servlet 标准 servlet 标准定义了动静资源文件 (其实就是 servlet) 的开发步骤。servlet 标准定义了 Tomcat 服务器调用 servlet 的规定。servlet 标准定义了 Tomcat 服务器治理 servlet 实例的规定。为什么要定义这些标准?因为无规矩不成方圆。因为 Tomcat 同样也恪守了人家 Servlet 的标准,不然你写完程序交给 Tomcat 运行的时候,Tomcat 一看你没有恪守 Servlet 的标准,人家懒得管你。4. 开发 Servlet4.1 新建一个 javaweb 我的项目这里咱们应用 idea 创立一个 javaweb 我的项目。
我的项目目录:
4.2 idea 配置 Tomcat1. 顶部菜单栏抉择 Run,抉择 Edit Configuration。
2. 点击“+”号,抉择 Tomcat Server,抉择 Local。
3.Application server 抉择 Tomcat 本地装置目录。Http port 默认 8080 即可。
4. 抉择 Deployment,点击左边的 + 号,抉择 Artifact。
5. 抉择 web 我的项目,Application context 能够自定义,它相当于咱们我的项目的默认拜访门路。
6. 编写 index.jsp
7. 运行 Tomcat
浏览器网址输出:http://localhost:8080/myProject/
复制代码4.3 开发 Servlet1. 引入 jar 包在 WEB-INF 目录下新建 lib 目录,将 Tomcat bin 目录下的 servlert-api.jar 放到 lib 我的项目下。
2. 将 jar 包作为库增加到我的项目中。注:因为 jar 包就是编译后的 java 代码,所以这里就相当于在我的项目中增加了 Tomcat 指定标准下的 java 代码。抉择 lib 目录,右键抉择 Add as a Library。
3. 新建 Servlet 类 Servlet 标准:新建的 Servlet 类要想被 Tomcat 治理,必须继承 Tomcat jar 包下的 HttpServlet 类。创立一个 Java 类继承 HttpServlet 父类,使之成为一个 Servlet 接口实现类,并重写父类 doGet 和 doPost 办法。public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 这里用来解决用户的 get 申请 System.out.println("接管到用户的 get 申请");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码 4. 配置 web.xml 为什么要配置 web.xml ? 你依据 servlet 标准创立了一个 servlet 类,然而大哥 Tomcat 不晓得啊!所以你须要通知大哥一声。web.xml 相当于 Tomcat 的门卫,你须要在门卫处做一下注销,将 Servlet 接口实现类信息注册到 Tomcat 服务器。你须要注销 servlet 类的名字、类所在我的项目的门路以及申请门路。<?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">
<!– 将 Servlet 接口实现类交给 Tomcat 治理 –>
<servlet><servlet-name>userServlet</servlet-name> <!--Servlet 接口实现类名称 --> <servlet-class>com.xxl.controller.UserServlet</servlet-class><!-- 申明 servlet 接口实现类类门路 -->
</servlet>
<servlet-mapping><servlet-name>userServlet</servlet-name> <url-pattern>/user</url-pattern> <!-- 设置 Servlet 类的申请门路,必须以 / 结尾 -->
</servlet-mapping>
</web-app>
复制代码 servlet-name:servlet 类的名字。servlet-class:servlet 类所在我的项目的门路。url-pattern:用户申请该 servlet 的门路。5. 测试运行我的项目,浏览器输出:http://localhost:8080/myProje…
复制代码查看控制台打印:注:浏览器间接输出网址,按回车键是 GET 申请,和 html 中的超链接一样,例如:点击拜访 UserServlet
复制代码 6. 注解式开发工夫从敲代码的键盘声中划过,貌似所有惊涛骇浪,可是有一天却出事了。那是一个黑云压城城欲摧的下午,Tomcat 的门卫 web.xml 正在门卫室一边嗑瓜子一遍看报纸,门外忽然传来了一阵阵短促的马蹄声。原来这一天下午忽然来了一万个 servlet 找 web.xml 做注销。web.xml 一看这阵势蚌埠住了!,连忙禀告 Tomcat 大官人。Tomcat 一想:” 这一万个 servlet 得注销到猴年马月啊?算了,不让他们做注销了,让他们本人身上带个标记吧,这个标记我认得就行。” 所以在 servlet3.0 版本之后,咱们不须要在 web.xml 外面给每个 servlet 做配置了,只须要加一个注解就行。注解格局:@WebServlet(name = “servlet 的名字 ”,value = “ 拜访门路 ”)
或者:
@WebServlet(“/ 拜访门路 ”) // 默认以类名作为名字
复制代码例如:@WebServlet(name = “userServlet”,value = “/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 这里用来解决用户的 get 申请 System.out.println("哈哈哈哈哈哈我头上有注解");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码或者:@WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 这里用来解决用户的 get 申请 System.out.println("哈哈哈哈哈哈我头上有注解");
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码这时的 web.xml 就是空洞无物:即使 web.xml 什么也不配置,因为咱们加了注解,所以 Tomcat 也能辨认到,咱们再来申请一下 servlet,发现也能申请胜利。运行我的项目,浏览器输出:http://localhost:8080/myProje…
复制代码注:名字和申请门路要放弃唯一性,不然 Tomcat 获取用户的申请之后不晓得给哪一个 Servlet。5. Http 协定 5.1 简介为什么要学习 Http 协定?因为只有晓得了 Http 协定,你能力弄清楚信息在网络上传递的过程,你能力晓得 servlet 是干什么的。Htttp 协定次要利用在客户端 - 服务端架构上。浏览器作为 Http 客户端通过 URL 向 Web 服务器发送申请,其中 Http 罕用的申请的形式次要有 GET 申请和 POST 申请。Web 服务器解决用户的申请后,向客户端发送响应信息。信息在网络上都是以二进制模式进行传递的,传递的信息被封装成一个个的 Http 协定包。Http 协定包包含申请包和响应包。5.2 Http 申请 HTTP 申请的音讯格局次要蕴含:申请行、申请头、申请空行、申请数据。例如 GET 申请的音讯体:GET /login.html HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
复制代码申请行次要包含:申请形式、申请的 URL、申请的 Http 版本协定,例如:GET /login.html HTTP/1.1
复制代码申请头格局:申请头名称: 申请头值,例如:Host: localhost
复制代码上面是一个残缺的申请头:Host: localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Referer: http://localhost/login.html
Connection: keep-alive
Upgrade-Insecure-Requests: 1
复制代码申请空行就是一个空行,意思就是通知服务器从下一行开始就没有申请头了。GET 申请是没有申请体的,只有 POST 申请有申请体,申请体是以键值对的形式传输的,POST 的申请体就是键值对。5.3 Http 响应 HTTP 响应的音讯格局次要蕴含:状态行、响应头、空行、相应数据。例如上面就是一个残缺的响应体:HTTP/1.1 200 OK
Date: Wed, 22 Dec 2021 09:07:21 GMT
Content-Type: text/html; charset=UTF-8
<html>
<head></head>
<body>
一颗雷布斯
</body>
</html>
复制代码状态行:HTTP 协定版本号、状态码、状态音讯。第一行为状态行,(HTTP/1.1)示意 HTTP 版本为 1.1 版本,状态码为 200,状态音讯是 ok。第二行和第三行为响应头,用来阐明客户端要应用的一些附加信息。第四行是空行。最初的 html 代码就是响应的注释。5.4 GET 和 POST 区别 GET 把申请参数蕴含在 URL 中,POST 通过申请体传递参数。GET 不平安,因为参数间接裸露在 URL 上,所以不能用来传递敏感信息。GET 申请在 URL 中传递的参数是有长度限度的,而 POST 没有限度。6. 欢送页面咱们平时拜访一个网站,都是输出一个简略的网址,例如:https://www.baidu.com
复制代码而不是:https://image.baidu.com/searc…
复制代码因为这种太长的门路咱们基本记不住。所以当用户拜访一个网站时,咱们个别会设置一个默认的页面,例如百度默认首页:
那如何在咱们的我的项目中设置默认的欢送页面?也是在 web.xml 中配置。设置规定:<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
复制代码而后咱们须要在 web 或者 webapp 目录下创立欢送页面。欢送页面默认显示程序是从上到下,如果不配置也是从这几个文件中找。比方咱们刚创立这个我的项目时没有配置欢送页面,然而程序运行之后默认显示的就是 index.jsp 的内容。当然了咱们也能够设置自定义的欢送页面,例如:
login.html:<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset="UTF-8">
<title>login.html</title>
</head>
<body>
<h1> 家人们!家人们!欢送来到登录页面!</h1>
</body>
</html>
复制代码运行程序:
-
HttpServletRequest7.1 HttpServletRequest 是啥?咱们通过浏览器向 Http 服务器发送了一个 Http 申请协定包,Http 服务器会主动为这个 Http 申请协定包生成一个申请对象和一个响应对象。而 HttpServletRequest 就代表客户端的申请,HTTP 申请中的所有信息都封装在这个对象中,咱们能够应用这个对象干如下事件:读取 Http 申请协定包中的申请信息向 Http 服务器申请资源文件 7.2 获取申请行信息 @WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 获取申请行中【url】信息 String url = request.getRequestURL().toString(); // 2. 获取申请行中【method】信息 String method = request.getMethod(); // 3. 获取申请行中【URI】信息,URI: "/ 网站名 / 资源文件名" String uri = request.getRequestURI(); System.out.println("申请 URL:" + url); System.out.println("申请 method:" + method); System.out.println("申请 URI:" + uri);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码运行我的项目,浏览器输出:http://localhost:8080/myProje…
复制代码控制台打印后果:7.3 获取申请头的参数信息咱们应用如下办法获取申请头的参数信息:String parameter = request.getParameter(“ 参数名 ”);
复制代码 7.3.1 获取 GET 申请头的参数信息首先咱们在浏览器申请门路追加申请参数,多个参数用 & 分隔,例如:http://localhost:8080/myProje… 一颗雷布斯 &age=23
复制代码批改代码:@WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获取申请头的 name 参数 String name = request.getParameter("name"); // 获取申请头的 age 参数 String age = request.getParameter("age"); System.out.println("name:"+name); System.out.println("age:"+age);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码运行程序,查看控制台打印信息:7.3.2 获取 POST 申请头的参数信息咱们先批改一下默认欢送页面 login.html 的代码,减少一个 form 表单信息:<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>login.html</title>
<style>div { width: 300px; height: 300px; margin: 0 auto; }
</style>
</head>
<body>
<div>
<form action=”/myProject/user” method=”post”><lable> 姓名:</lable> <input type="text" name="name"></br> <lable> 明码:</lable> <input type="password" name="password"></br> <input type="submit" value="登录">
</form>
</div>
</body>
</html>
复制代码批改 servlet 代码:@WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 这里用来解决用户的 get 申请 System.out.println("接管到用户的 get 申请");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 获取 post 申请的 name 参数 String name = request.getParameter("name"); // 获取 post 申请的 password 参数 String password = request.getParameter("password"); System.out.println("name:"+name); System.out.println("password:"+password);
}
}
复制代码浏览器页面输出信息,明码是 123456,点击登录按钮:
查看控制台打印信息:
7.3.3 解决 POST 申请获取参数乱码问题下面的例子中咱们发现英文和数字能够失常输入,然而中文却乱码了,这是为什么?当浏览器以 GET 形式发送申请,申请参数保留在申请头中,Http 服务器获取申请协定包之后先对其解码。Tomcat 负责对其解码。因为 Tomcat 默认应用 utf- 8 字符集,这个字符集能够解释所有国家的文字,所以即使是中文也不会乱码。当浏览器以 POST 形式发送申请,申请参数保留在申请体中,Http 服务器获取申请协定包之后先对其解码。申请对象 request 负责对申请体的内容进行解码。因为 request 默认应用 ISO-8859-1 字符集,这个字符集是东欧语字符集,所以遇到中文会乱码。所以在 Post 申请形式下要想解决乱码问题,应该先让申请对象应用 utf-8 字符集对申请体内容进行一次从新解码。request.setCharacterEncoding(“utf-8”);
复制代码咱们从新批改一下 servlet 的代码:@WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 这里用来解决用户的 get 申请
System.out.println("接管到用户的 get 申请");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// Tomcat 告诉申请对象,应用 utf-8 字符集对申请体内容重写解码
request.setCharacterEncoding("utf-8");
// 获取 post 申请的 name 参数
String name = request.getParameter("name");
// 获取 post 申请的 password 参数
String password = request.getParameter("password");
System.out.println("name:"+name);
System.out.println("password:"+password);
}
}
复制代码浏览器页面输出信息,点击登录按钮查看控制台打印信息:
-
HttpServletResponse8.1 HttpServletRequest 是啥?咱们解决完用户的申请之后必定要给用户做出响应,而 HttpServletResponse 就是响应对象,它无能如下事件:将后果以二进制模式写入到响应体设置响应头中 content-type 属性值设置响应头中 location 属性,让浏览器向指定 Http 服务器发送申请。8.2 将响应后果发送到浏览器咱们将响应后果放到 Http 响应包的响应体中,而后在浏览器对响应体的二进制内容进行编译解析,从而显示其内容。语法格局:PrintWriter writer = response.getWriter();
writer.println(响应后果内容);
复制代码咱们批改一下 servlet 的代码:@WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String result1 = "<h1>2022: Where there is a well,there is a way<h2>"; String result2 = "海鸟跟鱼相爱,只是一场意外"; PrintWriter writer = response.getWriter(); writer.println(result1); writer.println(result2);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码运行我的项目,浏览器输出:http://localhost:8080/myProje…
复制代码查看浏览器响应后果:8.3 设置响应头 content-type 从下面的例子中,咱们看到英文和数字能够失常输入,然而中文乱码了,咱们能够设置一下响应头 content-type 的格局,让浏览器能够输入中文。设置 content-type 的语法格局:response.setContentType(“content-type 的格局 ”);
复制代码咱们批改一下 servlet 的代码:@WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {String result1 = "<h1>2022: Where there is a well ,there is a way<h2>"; String result2 = "海鸟跟鱼相爱,只是一场意外"; // 设置响应头 content-type 的格局 response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.println(result1); writer.println(result2);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码运行我的项目,浏览器输出:http://localhost:8080/myProje…
复制代码查看浏览器响应后果:8.4 向指定 Http 服务器发送申请咱们能够在响应头中设置 location 属性,从而让浏览器跳转到指定的网址。语法格局:response.sendRedirect(“ 网址 ”);
复制代码咱们批改一下 servlet 的代码:@WebServlet(“/user”)
public class UserServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 浏览器接管到 http 响应包之后,如果发现响应头中存在 location 属性 // 2. 则主动通过地址栏向 location 指定网站发送申请 // 3. sendRedirect 办法管制浏览器的申请行为 response.sendRedirect("http://www.baidu.com");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 这里用来解决用户的 post 申请 System.out.println("接管到用户的 post 申请");
}
}
复制代码运行我的项目,浏览器输出:http://localhost:8080/myProje…
复制代码查看浏览器响应后果: -
重定向和申请转发 9.1 Servlet 之间相互拜访如果有一天你对 Http 服务器说:我想吃黄焖鸡。后果你的拜访场景是这样的:
起初你彻底破防了:“老子就想吃个黄焖鸡,须要拜访这么屡次?啥破网站啊,再也不必了!”所以为了晋升用户应用体验,servlet 标准定义了多个 servlet 之间相互调用的规定。无论该申请波及到多少个 Servlet,用户只须要向浏览器发动一次申请,Servlet 之间相互合作,用户失去响应后果。
多个 Servlet 之间相互调用的规定有两个:重定向解决方案申请转发解决方案 9.2 重定向原理:用户先通过浏览器拜访 oneServlet,然而 oneServlet 不能解决用户的问题。于是 oneServlet 就将 TwoServlet 的拜访地址写入到响应头 的 location 属性中。浏览器拿到 Http 响应包之后,会依据响应头中的 location 的值再次向 Http 服务器中的 twoServlet 发送申请。twoServlet 再去解决用户的申请。其实重定向就相当于你去找刘备借钱,刘备说我没钱你去找曹操吧。而后你又去找曹操借钱,最初借到了钱。
特色:浏览器至多发送两次申请,只有第一次是用户本人通过浏览器发送的,前面的都是浏览器主动发送的。重定向申请形式是 GET 形式。因为申请地址发生变化,所以浏览器地址栏会发生变化。除了能够拜访 http 服务器外部的资源,还能够拜访内部网站资源。例如百度等。浏览器屡次拜访服务器,减少用户等待时间。实现形式 response.sendRedirect(“ 网址 ”);
复制代码案例新建 OneServlet@WebServlet(“/one”)
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.sendRedirect("/myProject/two");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码新建 TwoServlet@WebServlet(“/two”)
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setContentType("text/html;charset=utf-8"); PrintWriter writer = response.getWriter(); writer.println("我是 twoServlet,我帮你解决问题!");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码运行我的项目,应用浏览器拜访 OneServlet:http://localhost:8080/myProje…
复制代码查看浏览器响应后果:9.3 申请转发 1. 原理用户先通过浏览器拜访 oneServlet,然而 oneServlet 不能解决用户的问题。于是 oneServlet 将 request 对象和 response 对象传递给 TwoServlet,而后 twoServlet 去解决用户的申请。其实申请转发就相当于你去找刘备借钱,刘备一摸兜没钱,然而刘备这人挺仗义,他就带着你去找曹操借钱,最初你从曹操那里借到了钱。
2. 特色在申请转发过程中,浏览器只发送一次申请。在 HTTP 服务器外部做申请转发,只能申请服务器外部资源。在申请转发过程中,浏览器只发送一个 Http 申请协定包。所以参加本次申请的所有 Servlet 共享同一个申请协定包。因为在 Http 服务器外部做申请转发,所以浏览器地址栏不变。3. 实现形式 RequestDispatcher requestDispatcher = request.getRequestDispatcher(“ 下一个 servlet 申请门路 ”);
// 将本次 Http 申请协定包的【申请对象】和【响应对象】交给下一个 servlet
requestDispatcher.forward(request,response);
复制代码 4. 案例只批改 OneServlet@WebServlet(“/one”)
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 因为是 http 服务器外部做申请转发,相当于调用同一个我的项目的资源,所以间接写 servlet 的拜访门路就行 RequestDispatcher requestDispatcher = request.getRequestDispatcher("/two"); // 将本次 Http 申请协定包的【申请对象】和【响应对象】交给下一个 servlet requestDispatcher.forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码运行我的项目,应用浏览器拜访 OneServlet:http://localhost:8080/myProje…
复制代码查看浏览器响应后果:总结:重定向的重是从新、再次的意思,也就是浏览器向服务器发送了两次以上的申请。而申请转发产生在服务器外部,浏览器只申请了一次。10. Servlet 之间数据共享数据共享:第一个 Servlet 解决申请之后,将数据交给第二个 Servlet 来应用。Servlet 标准提供了四种形式来解决数据共享问题。10.1. ServletContext1. 全局作用域 ServletContext 对象是全局作用域对象。全局作用域对象相当于教室外面一个专用的区域,老师把一些公共物品放到这里,所有同学 (Servlet) 都能够应用。2. 应用办法将共享数据增加到全局作用域对象 // 1. 获取全局作用域对象
ServletContext servletContext = request.getServletContext();
// 2. 将共享数据增加到全局作用域对象
servletContext.setAttribute(“key”,value);
复制代码从全局作用域对象获取共享数据 // 1. 获取全局作用域对象
ServletContext servletContext = request.getServletContext();
// 2. 从全局作用域对象获取共享数据
Object value = servletContext.getAttribute(“key”);
复制代码 3. 案例 批改 OneServlet@WebServlet(“/one”)
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 获取全局作用域对象 ServletContext servletContext = request.getServletContext(); // 2. 将共享数据增加到全局作用域对象 servletContext.setAttribute("info","祝往年期末考试的你科科必过!祝往年考研、考公的你肯定上岸!"); // 3. 重定向 response.sendRedirect("/myProject/two");
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码批改 TwoServlet@WebServlet(“/two”)
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 获取全局作用域对象 ServletContext servletContext = request.getServletContext(); // 2. 从全局作用域对象获取共享数据 String info = (String)servletContext.getAttribute("info"); response.setContentType("text/html;charset=utf-8"); // 3. 将共享数据发送到浏览器 response.getWriter().println(info);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码运行我的项目,应用浏览器拜访 OneServlet:http://localhost:8080/myProje…
复制代码查看浏览器响应后果:10.2. Cookie1. 简介 Cookie 是 Servlet 标准中的一个对象。如果两个 Servlet 来自于同一个网站,能够应用 Cookie 对象进行数据共享。2. 原理用户申请 OneServlet,OneServlet 创立一个 Cookie 存储与以后用户相干的数据。OneServlet 执行结束,将 Cookie 写入到响应头交还给以后浏览器。浏览器获取 Http 响应包之后,将 cookie 信息存储在浏览器的缓存中。过了一段时间,用户通过同一个浏览器拜访 TwoServlet。浏览器将缓存中的 Cookie 信息写入到 Http 申请包的申请头中。此时 TwoServlet 就能够通过读取申请头中 的 cookie 信息,获取 OneServlet 提供的共享数据。其实 Cookie 的原理就像你 (浏览器) 第一次去健身房 (Http 服务器),健身房的工作人员给你办了张会员卡(Cookie)。你下次再去这家健身房,外面的工作人员拿到会员卡之后就晓得你是谁了。3. 应用形式创立 cookie,保留共享数据 // 1. 创立一个 cookie 对象,保留共享数据
Cookie cookie = new Cookie(“key”,”value”);
// 2. 将 cookie 信息写入到响应头,交给浏览器
response.addCookie(cookie);
复制代码获取共享数据 // 1. 调用申请对象从申请头失去浏览器返回的 Cookie 信息
Cookie cookies[] = request.getCookies();
// 2. 遍历数据获取 cookie 的 key 与 value
for(Cookie cookie:cookies) {
// 3. 获取 key 的值
String key = cookie.getName();
// 4. 获取 value 的值
String value = cookie.getValue();
}
复制代码 4. 案例 批改 OneServlet@WebServlet(“/one”)
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 创立一个 cookie 对象,保留共享数据 Cookie cookie = new Cookie("name","jay"); // 2. 将 cookie 信息写入到响应头,交给浏览器 response.addCookie(cookie);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码批改 TwoServlet@WebServlet(“/two”)
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 调用申请对象从申请头失去浏览器返回的 Cookie 信息 Cookie cookies[] = request.getCookies(); // 2. 遍历数据获取 cookie 的 key 与 value for(Cookie cookie:cookies) { // 3. 获取 key 的值 String key = cookie.getName(); // 4. 获取 value 的值 String value = cookie.getValue(); System.out.println("key:"+key+"value:"+value); }
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码运行我的项目,先拜访 OneServlet:http://localhost:8080/myProje…
复制代码再拜访 TwoServlet:http://localhost:8080/myProje…
复制代码查看控制台打印后果:留神:cookie 相当于一个 map。一个 cookie 中只能寄存一个键值对。键值对的 key 与 value 只能是 String 类型。键值对中 key 不能是中文。5.cookie 的销毁机会默认状况下,Cookie 对象保留在浏览器的缓存中。所以只有敞开浏览器,Cookie 对象就会被销毁。为了缩短 Cookie 的存活工夫,咱们能够将 Cookie 信息存储在本地计算机的硬盘上,并设置 Cookie 的存活工夫。在存活工夫范畴内,敞开浏览器或者服务器,都不会导致 Cookie 被销毁。当存活工夫时到了,Cookie 主动被删除。设置 Cookie 在硬盘存活工夫:Cookie cookie = new Cookie(“name”,”jay”);
//cookie 在硬盘上存活 2 分钟
cookie.setMaxAge(120);
复制代码 10.3. Session1. 简介 Session 是 Servlet 标准中的一个对象。如果两个 Servlet 来自于同一个网站,能够应用 Session 对象进行数据共享。咱们习惯将 Session 叫做会话对象。2. 原理用户申请 OneServlet,OneServlet 创立一个 Session 对象存储与以后用户相干的数据。OneServlet 执行结束,将 Session 保留到 Http 服务器的内存中。而后用户通过同一个浏览器拜访 TwoServlet。TwoServlet 就能够通过 Http 服务器内存中的 Session,获取 OneServlet 提供的共享数据。其实 Session 能够看做服务器端的保险柜。3. 应用形式创立 Session,保留共享数据 // 1. 创立 session 对象
HttpSession session = request.getSession();
// 2. 将数据保留到服务器内存中(保险柜)
session.setAttribute(“key”, 共享数据);
复制代码获取共享数据 // 1. 获取 session
HttpSession session = request.getSession();
// 2. 从 session 中获取共享数据
Object 共享数据 = session.getAttribute(“key”);
复制代码 4. 案例批改 OneServlet@WebServlet(“/one”)
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 创立 session 对象 HttpSession session = request.getSession(); // 2. 将数据保留到服务器内存中(保险柜)session.setAttribute("key",123);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码批改 TwoServlet@WebServlet(“/two”)
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 1. 获取 session HttpSession session = request.getSession(); // 2. 从 session 中获取共享数据 Object info = session.getAttribute("key"); System.out.println("从 session 中获取信息:"+info);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码运行我的项目,先拜访 OneServlet:http://localhost:8080/myProje…
复制代码再拜访 TwoServlet:http://localhost:8080/myProje…
复制代码查看控制台打印后果:留神:HttpSession 对象能够存储任意类型的共享数据。HttpSession 相当于一个 map 汇合,所以能够存储任意数量共享数据。10.4. HttpServletRequest1. 简介在同一个网站中,两个 Servlet 之间通过申请转发形式进行调用,因为他们共享同一个申请协定包,所以 servlet 之间共享同一个申请对象。因而能够利用这个申请对象在两个 Servlet 之间实现数据共享。这个申请对象叫做申请作用域对象。2. 应用形式应用申请对象保留共享数据 // 数据类型能够是任意类型
req.setAttribute(“key”, 数据);
复制代码应用申请对象获取共享数据 // 从申请对象获取共享数据
Object 数据 = req.getAttribute(“key”);
复制代码 3. 案例批改 OneServlet@WebServlet(“/one”)
public class OneServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 应用申请对象保留共享数据 request.setAttribute("info","我一路向北,来到有你的节令。"); // 申请转发 request.getRequestDispatcher("/two").forward(request,response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码批改 TwoServlet@WebServlet(“/two”)
public class TwoServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// 从申请对象中获取共享数据
Object info = request.getAttribute(“info”);
response.setContentType(“text/html;charset=utf-8”);
response.getWriter().println(info);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {}
}
复制代码运行我的项目,应用浏览器拜访 OneServlet:http://localhost:8080/myProje…
复制代码查看浏览器响应后果: -
Filter 过滤器 1. 简介 Filter 是 Servlet 标准下的一个接口,次要用来通知 Tomcat 在调用某一个资源文件之前,对用户的申请进行拦挡。比方用户还没有登录网站就想查看本人购物车的信息,这时候就须要对用户的申请进行拦挡。
2. 应用形式新建 filter 类,实现 Filter 接口中的 doFilter 办法。在 web.xml 中配置 filter 类 <!– 配置过滤器 –>
<filter>
<filter-name>userFilter</filter-name>
<filter-class>com.xxl.filter.UserFilter</filter-class>
</filter>
<!– 通知 Tomcat 在用户调用何种资源文件时须要被以后过滤器拦挡 –>
<filter-mapping>
<filter-name>userFilter</filter-name>
<url-pattern> 拦挡门路 </url-pattern>
</filter-mapping>
复制代码 3. 案例新建 UserFilterpublic class UserFilter implements Filter {@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {}
}
复制代码在我的项目中放一个美女照片:在 web.xml 中配置 UserFilter,拦挡该照片。<?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">
<!– 配置过滤器 –>
<filter><filter-name>userFilter</filter-name> <filter-class>com.xxl.filter.UserFilter</filter-class>
</filter>
<!– 通知 Tomcat 在用户调用何种资源文件时须要被以后过滤器拦挡 –>
<filter-mapping><filter-name>userFilter</filter-name> <url-pattern>/girl.jpg</url-pattern>
</filter-mapping>
</web-app>
复制代码欠缺 UserFilter 代码,判断 age 参数是否大于 18 岁。public class UserFilter implements Filter {@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 1. 通过【拦挡申请对象】获取申请参数信息 String age = servletRequest.getParameter("age"); // 2. 如果年龄非法 if (Integer.parseInt(age) > 18) { // 3. 将拦挡申请对象和响应对象交还给 Tomcat,由 Tomcat 持续调用资源文件,放行 filterChain.doFilter(servletRequest,servletResponse); }else{servletResponse.setContentType("text/html;charset=utf-8"); servletResponse.getWriter().println("看啥美女!写你的作业去!"); }
}
}
复制代码运行后果:4. 注解式开发不须要在 web.xml 中配置,间接在 filter 类上加注解:@WebFilter(filterName = “filter 名字 ”,urlPatterns = “ 拦挡门路 ”)
复制代码批改 UserFilter 代码:@WebFilter(filterName = “userFilter”,urlPatterns = “/girl.jpg”)
public class UserFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {// 1. 通过【拦挡申请对象】获取申请参数信息 String age = servletRequest.getParameter("age"); // 2. 如果年龄非法 if (Integer.parseInt(age) > 18) { // 3. 将拦挡申请对象和响应对象交还给 Tomcat,由 Tomcat 持续调用资源文件,放行 filterChain.doFilter(servletRequest,servletResponse); }else{servletResponse.setContentType("text/html;charset=utf-8"); servletResponse.getWriter().println("看啥美女!写你的作业去!"); }
}
}
复制代码运行成果一样。