java servlet作用域_JavaWeb基础(七)-Servlet交互和作用域对象

本文详细探讨了Servlet的交互方式,包括请求转发和URL重定向,以及请求包含的概念。请求转发在同一个请求对象间共享数据,不改变浏览器地址,而URL重定向则发起新的请求,改变浏览器地址且不共享请求数据。此外,还介绍了Servlet的三大作用域对象——request、session和ServletContext,以及它们的作用和使用场景。JSP作为动态网页技术,旨在分离业务逻辑和页面渲染。
摘要由CSDN通过智能技术生成

1.Servlet交互和作用域对象

在JavaWeb基础(六)中我分享了三个主要内容Servet3.0注解的使用、Cookie技术实现请求数据共享、Session技术实现请求数据共享.在这篇博客中,我主要分享以下两方面的内容。Servlet交互

作用域对象

1.1 Servlet交互

在J2EE规范中, Servlet的交互方式主要有三种。Servlet之所以需要交互是因为我们不可能将所有业务逻辑都揉和在一个Servlet中.所以一个Sevlet一般对应一个功能。多个Servlet之间就涉及到如何进行数据的传递和跳转, 这我们又称为Servlet的交互。简而言之,Servlet的交互讲的是Servlet之间的数据传递和跳转。

1.1.1 Servlet交互方式

Servlet交互方式,主要分为以下两种, 请求转发, URL重定向,请求包含

请求转发获取分发器,并调用forward开始转发.

req.getRequestDispatcher(path).forward(req, resp);

FirstServlet@WebServlet("/request_forward/FirstServlet")public class FirstServlet extends HttpServlet{    @Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

PrintWriter pw = resp.getWriter();

System.out.println("FirstServlet before");

pw.println("FirstServlet before");

req.getRequestDispatcher("/request_forward/SecondServlet").forward(req, resp);

System.out.println("FirstServlet Request =" + req);

System.out.println("FirstServlet after");

pw.println("FirstServlet after");

}

}

SecondServlet@WebServlet("/request_forward/SecondServlet")public class SecondServlet extends HttpServlet {

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

PrintWriter pw = resp.getWriter();

System.out.println("SecondServlet before");

pw.println("SecondServlet before");

System.out.println("SecondServlet Request =" + req);

System.out.println("SecondServlet after");

pw.println("SecondServlet after");

}

}

浏览器输出AAffA0nNPuCLAAAAAElFTkSuQmCC

控制台输出AAffA0nNPuCLAAAAAElFTkSuQmCC

特点研究

我们根据浏览器的输出和控制器台输出,结合代码来研究请求转发的特点.

我们从浏览器地址栏、请求转发整个过程Servlet的执行先后顺序、请求报文变化、参数是否可以传递、请求转发能够访问的资源来研究。1.浏览器地址栏

如上图, 浏览器地址栏没有发生变化.我们可以得出结论请求转发不会改变浏览器地址栏.

2.请求转发整个过程Servlet的执行先后顺序

如上图控制台的输出, FirstServlet before-SecondServlet before-SecondServlet after-FirstServlet after.我们可以发现最后响应给浏览器并不是直接通过SecondServlet而是先回到了转发位置,然后继续执行FirstSevrlet后的代码。但是决定最后内容的是SecondServlet。我们可以得出以下结论一.决定最终返回数据的是SecondServlet, 但是并不是直接从SecondServlet响应给浏览器,而是还需要通过FirstServlet. 二.前后的请求对象不是同一个

3.请求报文的变化AAffA0nNPuCLAAAAAElFTkSuQmCC4.参数是否可以传递

更改FirstServlet的代码,请求转发前给path增加name参数,并且存放一个age数据到reqeust域中.req.setAttribute("age", 13);

req.getRequestDispatcher("/request_forward/SecondServlet?name=will").forward(req, resp);

SecondServlet最后先新增如下代码pw.println("name = "+req.getAttribute("name")+",age = "+req.getAttribute("age"));

浏览器输出AAffA0nNPuCLAAAAAElFTkSuQmCC

结论:通过请求转发上填写参数无法共享,但是request对象的数据可以共享

5.请求转发能够访问的资源

尝试通过请求转发访问百度req.getRequestDispatcher("www.baidu.com").forward(req, resp);

浏览器输出AAffA0nNPuCLAAAAAElFTkSuQmCC

可以得出以下结论:请求转发无法跨域访问

尝试通过请求转发访问WEB-INF目录下的资源req.getRequestDispatcher("/baidu.html").forward(req, resp);

浏览器输出AAffA0nNPuCLAAAAAElFTkSuQmCC

可以得出以下结论:请求转发可以访问WEB-INF下的资源文件总结1.请求转发不会改变浏览器地址栏(由第一点得出)

2.请求转发内容由第二个Servlet决定,但是最后必须经过第一个Servlet(由第二点得出)

3.请求转发的请求次数只有一次(由第三点得出)

4.请求转发只能共享request中的数据.请求转发只能填写资源路径,填写参数无效.(由第四点得出)

5.请求转发只能不能跨域访问(由第五点得出)

6.请求转发能够访问WEB-INF下的资源(有第五点得出)

URL重定向

URL重定向主要通过response对象的sendRedirect方法实现.其会响应浏览器当前请求, 并让浏览器再发一次请求到新的资源路径。所以称之为重定向.

FirstServlet@WebServlet("/url_redirect/FirstServlet")public class FirstServlet extends HttpServlet{    @Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

PrintWriter pw = resp.getWriter();

System.out.println("FirstServlet before");

pw.println("FirstServlet before");

req.setAttribute("age", 13);//      req.getRequestDispatcher("/baidu.html").forward(req, resp);

resp.sendRedirect("/request_forward/SecondServlet");

System.out.println("FirstServlet Request =" + req);

System.out.println("FirstServlet after");

pw.println("FirstServlet after");

}

}

SecondServlet@WebServlet("/url_redirect/SecondServlet")public class SecondServlet extends HttpServlet {

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

PrintWriter pw = resp.getWriter();

System.out.println("SecondServlet before");

pw.println("SecondServlet before");

System.out.println("SecondServlet Request =" + req);

System.out.println("SecondServlet after");

System.out.println("name = "+req.getAttribute("name")+",age = "+req.getAttribute("age"));

pw.println("name = "+req.getAttribute("name")+",age = "+req.getAttribute("age"));

pw.println("SecondServlet after");

}

}

浏览器输出AAffA0nNPuCLAAAAAElFTkSuQmCC

控制台输出AAffA0nNPuCLAAAAAElFTkSuQmCC

特点研究浏览器地址栏

如上图浏览器输出的地址栏发生了变化.可以得出结论: URL重定向会改变浏览器地址栏为请求地址。

请求转发整个过程Servlet的执行先后顺序

SecondServlet before-Second after.所以URL重定向后响应给浏览器的内容由SecondServlet决定, 并且是直接由SecondServlet响应给浏览器,因为这是一次新的请求。

请求报文变化AAffA0nNPuCLAAAAAElFTkSuQmCC

如上图,请求报文的请求行地址就发生了改变, 说明这是第二次请求.

所以URL重定向的请求是两次参数是否可以传递

见上面的浏览器输出图,URL重定向参数不可传递

请求转发能够访问的资源

跨域访问resp.sendRedirect("https://www.baidu.com");

浏览器输出.没法录制动图,自己尝试下AAffA0nNPuCLAAAAAElFTkSuQmCC

结论: URL重定向可以跨域访问

访问WEB-INFresp.sendRedirect("/WEB-INF/views/login.html");AAffA0nNPuCLAAAAAElFTkSuQmCC

结论: URL重定向不能访问WEB-INF目录下的资源总结1.URL重定向会改变浏览器地址栏(由第一点得出)

2.URL重定向内容由第二个Servlet决定, 并且由第二个Servlet直接响应给浏览器(由第二点得出)

3.URL重定向的请求次数有二次(由第三点得出)

4.URL重定向不能共享request中的数据.(由第四点得出)

5.URL重定向能跨域访问(由第五点得出)

6.URL重定向不能够访问WEB-INF下的资源(有第五点得出)

可见URL重定向和请求转发的6个特点都是相反的.

请求包含

请求包含主要用在JSP中, 用在Servlet中没有多大意义。因为我们的每个Servlet一般有不同职责, 并不能够包含再一起。而JSP页面可以进行复用,这时候就可以用包含.

语法:request.getRequestDispatcher(path).include(req, resp);

如何选择请求转发和URL重定向

请求转发和URL重定向都是用于Web组件(Servlet和JSP)的跳转。如果需要在跳转后共享数据, 或者访问WEB-INF下的资源,那么必须用请求转发

如果需要在跳转后不需要共享数据,或者需要跨域访问资源,那么必须用URL重定向。

其他情况任选

1.2 作用域对象

Servlet三大作用域对象和其操作

Servlet的三大作用域对象其中两个, 我们已经在之前讲过, 分别是request、session.之所以说他们是作用域是因为保存在他们中的数据是有作用域范围, request是在同一个请求对象间, session是在一次会话间, 又因为它们都是Servlet下的规范,所以称为Servlet作用于对象。说了那么多, 最后一个Servlet作用域对象是ServletContext对象.

ServletContext

ServletContext是一个接口, 表示Web应用对象。在JSP中将其称为application.获取ServletContext

获取Servlet可以通过request,也可以通过sessioin、还可以通过在Servlet子类中调用父类的getServletContext()方法.如下图所示AAffA0nNPuCLAAAAAElFTkSuQmCCServletContext常用APIString path = getServletContext().getRealPath("/login.html");

控制台输出AAffA0nNPuCLAAAAAElFTkSuQmCCAAffA0nNPuCLAAAAAElFTkSuQmCCgetContextPath() 获取当前响应的上下文路径.即中path的值.

控制台输出 因为当前Context的path我配置成空字符串,所以输出空getRealPath(path) 获取资源的绝对路径

代码演示Servlet三大作用域@WebServlet("/scope/servlet")public class ScopeServlet extends HttpServlet {

@Override

protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

final String NUM_IN_REQUEST = "NUM_IN_REQUEST";        final String NUM_IN_SESSION = "NUM_IN_SESSION";        final String NUM_IN_APPLICATION = "NUM_IN_APPLICATION";

Integer numInRequest = (Integer) req.getAttribute(NUM_IN_REQUEST);        if (null == numInRequest) {

req.setAttribute(NUM_IN_REQUEST, 1);

}else {

req.setAttribute(NUM_IN_REQUEST, numInRequest+1);

}

HttpSession session = req.getSession();

Integer numInSession = (Integer) session.getAttribute(NUM_IN_SESSION);        if (null == numInSession) {

session.setAttribute(NUM_IN_SESSION, 1);

}else {

session.setAttribute(NUM_IN_SESSION, numInSession+1);

}

ServletContext app = req.getServletContext();

Integer numInApplication = (Integer) app.getAttribute(NUM_IN_APPLICATION);        if (null == numInApplication) {

app.setAttribute(NUM_IN_APPLICATION, 1);

}else {

app.setAttribute(NUM_IN_APPLICATION, numInApplication+1);

}

PrintWriter pw=resp.getWriter();

pw.println("request num = " + req.getAttribute(NUM_IN_REQUEST));

pw.println("session num = " + session.getAttribute(NUM_IN_SESSION));

pw.println("application num = " + app.getAttribute(NUM_IN_APPLICATION));

}

}

第一次访问AAffA0nNPuCLAAAAAElFTkSuQmCC

第二次刷新AAffA0nNPuCLAAAAAElFTkSuQmCC

打开另外一个窗口,地址相同AAffA0nNPuCLAAAAAElFTkSuQmCC

Servlet三大作用域总结作用域对象作用域类型作用域范围表示requestHttpServletRequest当前请求对象每次请求都是一个请求对象

sessionHttpSession一次会话的多个请求之间每次会话都是表示一个session对象

applicationServletContext作用于整个Web应用, 可以实现多次会话之间的数据共享表示一个web应用

1.3 JSP

JSP又称为动态网页, 其专门为页面渲染而生。就要聊聊最初的Servlet

最初的Servlet最早Servlet诞生的时候就是为了完成动态网页的开发, 是需要负责页面的渲染, 也就是使用pw =response对象.getWriter(), 然后使用PrintWriter一行行输出。

问题:HTML代码与业务代码耦合。

后来发现这样做不合理, 因为Servlet里要负责的事太多, 既要负责业务逻辑编写, 又要负责输出HTML页面代码, 导致了业务逻辑代码和HTML代码耦合在一起, 难以维护。

责任分离

出于以上的问题, 就将Servlet里负责HTML页面代码的责任进行了分离。让Servlet专注于业务逻辑。JSP技术就顺理成章的诞生了, JSP技术就是专门为了编写HTML代码。

JSP基本语法JSP语法的标志.其中符号用@、=、!、--代替, 分别有不同的含义.和@结合表示指令, 和=结合表示输出, 和!结合表示定义类成员, 和--结合表示注释(--需要成对)

JSP本质上是一种Servlet,所以其也拥有成员,拥有service方法.以下四种语法分别代表四种含义。

注释。

语法:

输出。用字符输出流输出

语法: 等价于 out.write("sweetcs")

脚本代码段。(定义service方法中的代码)

语法:

代码1;

代码2;

%>

定义类成员。

语法:

代码演示

pageEncoding="UTF-8"%>

html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

Insert title here

public ArrayList names = new ArrayList();

%>

names.add("AAA");

names.add("BBB");

names.add("CCC");

%>

JSP原理剖析

看完上述语法和代码你也许还不是懂。没事, 要理解这是怎么回事, 我们得结合底层来理解。定位对应的Servlet

打开项目部署的路径。找到统一级目录下的work目录.以我mac下的为例, 是在tomcat安装目录work/Catalina/localhost/_/org/apache/jsp/views/jsp下.

作者:sixleaves

链接:https://www.jianshu.com/p/7a0715ddf895

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值