首页 > 其他分享 >第05章 Servlet和JSP应用

第05章 Servlet和JSP应用

时间:2024-04-05 20:31:54浏览次数:16  
标签:05 URL data JSP jsp Servlet 页面

Servlet与JSP很相似,但也有一些区别,我们重新说明一下:

1. Servlet是一个Java类文件,JSP是一个混编Java的HTML的文件。
2. Servlet使用方法来处理请求,JSP则使用内置对象来处理请求。
3. Servlet需要编译才能运行,而JSP由JSP Container管理,不需要编译。
4. Servlet通过配置url访问,JSP通过路径url访问,两者在Web工程中存放位置也不同。
5. Servlet的生命周期伴随Web容器的启动和关闭,JSP的生命周期伴随请求的开始和结束。
6. Servlet更倾向于做业务数据逻辑处理,JSP则倾向于做页面输出,Servlet可输出JSP文件。

在上面的区别中,重要的是最后一条,servlet侧重于业务数据逻辑处理,而jsp则倾向于页面输出。两者的最好搭配就是在servlet中对请求数据进行处理,然后将处理完毕的数据 “传递” 给JSP页面,在JSP页面中可以使用HTML展示给最终用户,而 “传递” 过来的数据可以使用 <%= 表达式 %> 或 EL 表达式来读取,并控制HTML的输出。也就是说,一个请求URL的处理分为 Servlet 和 JSP 两个部分一起完成的。

我们的Web工程由一个默认的“index.jsp”文件,这是整个工程的入口。然后就是从一个请求URL跳转到另外一个请求URL。每一个请求URL都可以对应一个页面。这个页面可以是Servlet输出的,也可以本身就是JSP页面。我们对需求功能的开发,最重要的就是将其梳理成一个一个页面组成的流程,这个前后顺序非常的重要。每一个页面对应一个请求URL,在这个页面中应该有流程中下一个页面的请求URL。需求功能的开发,其实就是根据流程,规划每一个页面请求URL。例如登录流程,首先是进入登录页面URL,然后用户在登录页面输入账号和密码,然后跳转验证URL,根据验证的结果可能会跳转到成功页面,或者失败页面。这里需要注意的是,JSP页面的请求URL就是该文件的目录地址,而Servlet的请求URL是我们自定义出来的。一个完整的登录流程应该如下所示,

1. 登录页面可以直接使用jsp页面呈现出来,对应的登录页面URL就是该jsp页面的访问路径URL

2. 用户输入完账户和密码后请求URL来验证,这个URL可以对应Servlet来完成。因为这里涉及到数据处理,使用Servlet来更合适。Servlet处理完毕之后,需要将处理结果输出。

3. Servlet输出结果分为两种情况,也就是两个页面,一个是成功页面,一个是失败页面。也可以使用一个结果页面,只是里面的数据代表了成功或者失败。不管是两个页面,还是一个页面,都需要上面的Servlet调用输出。

那么Servlet如何调用输出Jsp文件?以及Servlet如何向Jsp文件传递数据?Servlet输出JSP有两种方式,一个是转发,另一个就是重定向。两者的区别在于,浏览器url地址栏是否改变:重定向会改变url,而转发不会(仍然是当前请求url)。

这里我们先介绍如何进行转发。我们可以通过request对象提供的getRequestDispatche(String path)方法,该方法返回一个RequestDispatcher对象,调用这个对象的forward方法可以实现请求转发。例如下代码:

request.getRequestDispatcher("/test.jsp").forward(request, response);

request对象不仅仅是请求对象,同时也是一个存储对象,对应JSP页面中的requestScope作用域对象,开发人员可以通过request对象的setAttribute方法存储数据,这些数据会被传递给JSP页面。例如下代码:

String data ="hello";
request.setAttribute("data", data);

然后,我们就可以在“/test.jsp”中使用EL表达式 “${requestScope.data}” 来获取到这个data变量值。

接下来,我们就创建一个新的 “TestDemo” 的工程来演示如何进行转发。如何在Eclipse下创建Java动态工程,我们这里不再介绍,请参考上一个章节的内容。工程创建完毕之后,我们就创建一个TestServlet类,对应的请求映射为“/test”。

接下来,我们修改doGet方法内容:

		String data ="hello";
		request.setAttribute("data", data);
		request.getRequestDispatcher("/test.jsp").forward(request, response);

我们设置这个TestServlet的请求url是“/test”,然后它会转发给“/test.jsp”文件。请注意这个文件的路劲,它是一个绝对路径,并且是在 WebContent 根目录下。因此,我们需要在 WebContent 根目录下创建 “test.jsp”文件。同时,我们向这个 “test.jsp” 的文件传递了一个变量。注意到setAttribute方法有两个参数,第一个参数是key, 第二个参数就是 value,也就是变量 data。那么这个 key 是什么呢?它就是JSP页面中获取该变量的使用的名称。因此我们在JSP中可以使用 “${requestScope.data}” 获取到数据,这里的 “data” 就是那个key。这里需要注意的是,我们使用request放置数据,就需要使用requestScope来获取。为了不造成混乱,我们一般将这个key就定义为变量名称,让两者保持一致。接下来,我们创建“test.jsp”文件。

我们只在<body>标签中添加了一句代码:<h1>${requestScope.data}</h1>
就是使用EL 表达式来读取请求域requestScope中的数据“data”。
最后我们在补全一个工程入口文件“index.jsp”,如下所示

我们就增加了一个超链接,执行了TestServlet类,代码如下

<a href="${pageContext.request.contextPath}/test">test</a>

接下来,我们就可以运行整个工程了。

转发和数据传递都成功了,转发的时候,我们的浏览器地址:“http://localhost:8080/TestDemo/test” 是不变的,也就是说,虽然页面显示的是 “test.jsp” 的内容,但是请求的URL仍然是 TestServlet 的URL。正因为请求URL没有变化,因此TestServlet和JSP同属于这一个 “http://localhost:8080/TestDemo/test” 请求域范围,也就是 requestScope 。这就是我们为什么将数据放入到 requestScope 中,而JSP也能能够访问到的原因了。换句话说,如果请求URL改变了,那么他们就不属于同一个 请求requestScope,JSP页面也就不能从 requestScope 中获取传递过来的数据了。那么该使用什么方式来传递和获取数据呢?解决这个问题,我们先要讲解一个重定向。

response.sendRedirect(request.getContextPath()+"/hello.jsp");

请注意,转发是通过request对象实现的,而重定向是通过response对象实现的。我们调用response对象的sendRedirect方法进行重定向,它的参数就是新的请求URL地址,这个地址可以是JSP文件,也可以是其他Servlet。既然是演示Servlet输出JSP文件,那么咱们肯定是要填写jsp文件了。上面代码中request.getContextPath()是为了兼容那个 项目路径 的问题。接下来,我们就来创建 HelloServlet类,对应的请求映射为“/hello”。

然后我们继续修改doGet方法内容

        String data ="hello";
		request.setAttribute("data", data);
		response.sendRedirect(request.getContextPath()+"/hello.jsp");

我们继续使用“请求域”来传递数据,但是这次是“重定向”到“/hello.jsp”文件中。
接下来创建 “/hello.jsp ”

我们依然在<body>中添加 <h1>${requestScope.data}</h1> 来读取请求域的数据。
接下来,我们在“index.jsp”中补充上 HelloServlet 的请求链接

<a href="${pageContext.request.contextPath}/hello">hello</a>

接下来,我们重新发布并运行项目,然后去浏览器中刷新查看

点击“hello”超链接

上面出现了两个问题,第一是浏览器地址 url 不是“http://localhost:8080/TestDemo/hello” 而是 “http://localhost:8080/TestDemo/hello.jsp”。 第二是传递过来的数据没有显示出来,说明我们无法获取传递过来的数据。其实,这两个问题,我们在上面讨论转发的时候,就已经说明过了。正是因为浏览器URL地址的改变,说明 servlet 与 jsp不在同一个请求范围内了,因此我们就不能使用 requestScope 了。我们需要换一个更大范围的存储域,这里推荐大家使用 sessionScope。如何在Servlet中将数据放入到 sessionScope中呢,如下代码

        String data ="hello";
		//request.setAttribute("data", data);
		request.getSession().setAttribute("data", data);
		response.sendRedirect(request.getContextPath()+"/hello.jsp");

我们通过 request 的 getSession 方法获取会话对象,然后使用 setAttribute 将数据放入到 sessionScope中。数据存储的域对象变了,我们在JSP中也需要修改一下。

<h1>${sessionScope.data}</h1>

这里我不在使用“请求域”,而是使用“会话域”。

现在没有问题了,浏览器地址虽然改变了,但是我们依然能够获取传递过来的数据。关于 session 的内容,我们会在后面的章节详细介绍。

这里我们需要再次提醒大家一个问题,就是转发和重定向的参数,

// 转发
request.getRequestDispatcher("/test.jsp").forward(request, response);

// 重定向
response.sendRedirect(request.getContextPath()+"/hello.jsp");

转发的参数实际上是“test.jsp”的文件的目录地址,"/"代表了WebContent根目录。如果我们将“test.jsp”文件放置到“WEB-INF”目录下的话,就应该修改成:“/WEB-INF/test.jsp” 。有人可以疑问,“WEB-INF”目录是保护目录,是不能被访问的。请注意,我们转发的参数是文件的目录地址,并不是访问URL。这是两个完全不同的概念。如果JSP作为请求URL的话,它是不允许在WEB-INF下访问的。但是,如果JSP作为文件路径的话,它是可以被Java代码访问的。因此,转发的JSP文件放置到“WEB-INF”保护目录是没有任何问题的,事实上,我们也经常这么做。接下来是重定向的参数,它才是访问URL,因此它需要 request.getContextPath() 来兼容项目路径的问题。同时,我们还可以填写 servlet 的访问URL。此时,如果我们将“hello.jsp” 放置到 “WEB-INF” 保护目录的话,那么这个重定向的URL是不能被访问的。最后就是数据传递的问题,我们在servlet中将数据放置到那个域中,就需要在jsp页面中使用对应的作用域来获取。一般情况下,转发就使用“请求域”来传递数据,而重定向的话就使用“会话域”来传递数据。虽然我们也可以放置到“应用”级别的作用域applicationScope(ServletContext),但是这个作用域是共享于所有的客户端浏览器,而我们上面介绍的请求作用域和会话作用域是绑定某一个客户端浏览器的,也就是说,客户端浏览器不同,它对应的请求作用域和会话作用域是不一样的。举例而言,张三使用一个客户端浏览器访问某个页面时候,存储在请求域或会话域的数据不会被李四访问到,因为李四使用另一个客户端浏览器访问的。两者的请求域或会话域的数据是相互隔离的,互不干扰。但是,“应用”级别的作用域applicationScope(ServletContext)是共享于所有客户端浏览器,张三和李四可以访问到相同的共享数据,并且该作用域的数据有效期直到我们的WebServer(例如Tomcat)重启才会失效。

标签:05,URL,data,JSP,jsp,Servlet,页面
From: https://blog.csdn.net/richieandndsc/article/details/137406588

相关文章

  • 2024-04-05 闲话
    KlayThompsondidaverygojobattoday'sNBAregularseasonmatch.Anaudiencecommented"春风若有怜花意,可否许我再少年"onHuPuapp.Ithinkthequoteisveryfittingbecauseit'sspringnowinTianjin.Clustersofflowersarequiteattractiveto......
  • 4.5Codeforces Round 905 (Div. 3)
    C题题意:几个数字,挑选其中几个进行+1.得到的数字的乘积可以整除k注意题目条件:k只能是2,3,4,5这几种情况每个数字只能是1——10(不算大)(好像没啥用,因为可以自增超过10)思路:对于2,3,5要想整除,这些个数里必须要有一个数是可以整除2,3,5的。所以思路很简单,去造,找到一个“变成5的倍数”所需......
  • 3D Object Detection Essay Reading 2024.04.05
    EMIFF论文:https://arxiv.org/abs/2303.10975代码:https://github.com/Bosszhe/EMIFF​ 本文提出了一种新的基于摄像机的三维检测框架,增强型多尺度图像特征融合(EMIFF)。虽然EMIFF的输入是2D图像,但是它的neck层的结构设计应该普适于点云的3D目标检测,同时其中的MFC等模块可以......
  • P9058 [Ynoi2004] rpmtdq 题解
    Description给定一棵有边权的无根树,需要回答一些询问。定义\(\texttt{dist(i,j)}\)代表树上点\(i\)和点\(j\)之间的距离。对于每一组询问,会给出\(l,r\),你需要输出\(\min(\texttt{dist(i,j)})\)其中\(l\leqi<j\leqr\)。\(n\leq2\times10^5\),\(q\leq10^6\),\(1\l......
  • 20240405比赛总结
    寄的很惨T1[JLOI2014]聪明的燕姿https://gxyzoj.com/d/hzoj/p/3672敲个警钟,千万不要用一些奇怪的方法写自己会的题,不然大概率会一分不剩由小学奥数知识,约数和的求法为\(\prod(1+p_i^2+p_i^3+\dots+p_i^{a_i})\)所以,可以先线性预处理出约数和,再直接统计,时间复杂度\(O(nk)\)......
  • P3052 [USACO12MAR] Cows in a Skyscraper G
    原题链接题解模拟,遍历n个物品,一开始一个箱子不给,遍历到某个物品时,先把所有已经给了的箱子放进去试试,再创一个新箱子放进去试试code#include<bits/stdc++.h>usingnamespacestd;intn,w;intcnt,ans;intchongdie=0;intbox[20],c[20];voidmoni(intnow,intcnt)//now......
  • L1-056 猜数字
    一群人坐在一起,每人猜一个100以内的数,谁的数字最接近大家平均数的一半就赢。本题就要求你找出其中的赢家。输入格式:输入在第一行给出一个正整数N(≤104)。随后N行,每行给出一个玩家的名字(由不超过8个英文字母组成的字符串)和其猜的正整数(≤ 100)。输出格式:在一行中顺序输出......
  • 万户ezOFFICE-wf_printnum.jsp存在SQL注入漏洞
    声明:本文仅用于技术交流,请勿用于非法用途由于传播、利用此文所提供的信息而造成的任何直接或者间接的后果及损失,均由使用者本人负责,文章作者不为此承担任何责任。简介万户EZOFFICE是一款办公软件,由中国万户网络科技有限公司开发和提供。该软件提供了一系列办公管理工具,包括......
  • STM32F1系列硬件I2C移植MPU6050DMP库
    目录前言STM32CubeMX配置过程工程移植与使用前言配置好硬件I2C拿过来直接用就行,一点也不用改这段时间在移植正点原子的MPU6050的库函数,网络上的教程大部分都是标准库同时也是软件模拟I2C的形式,这里我把正点原子的函数移植成了HAL库的硬件I2C的,下面会附带工程源码STM3......
  • 基于SSM+Jsp+Mysql的超市管理系统
    开发语言:Java框架:ssm技术:JSPJDK版本:JDK1.8服务器:tomcat7数据库:mysql5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9系统展示管理员登录员工管理商品类型管理商品库存管理商品进货管理上班打卡管理请假信息管理交流信息......