浅谈一款古老技术 动态页面jsp

0. 前言:

Jsp作为一个后端渲染技术,已经不符合现在前后端严格分离的主流设计思路。“Jsp是严重过时的技术,行将进入坟墓。”

那么jsp被什么替代了?
要么前后端分离,后端只需要返回JSON给前端,页面完全不需要后端管。
要么就是用常见的模板引擎『freemarker』『Thymeleaf』『Velocity』,用法其实跟『JSP』差不太多,只是它们的性能会更好。

但是jsp目前还没在业界彻底消失,尤其是一些老项目的维护。
最近写了一个老项目,用到了jsp,因此总结一下基本思想和用法。无需深入学习,了解即可。

1. jsp的使用

JSP最初的设计目的是为了简化Servlet输出HTML代码

现在一般的使用模式是:
在Servlet中处理好数据,存到服务器创建的域对象中,JSP通过内置的域对象获取数据,再结合封装的html代码对页面进行动态更新。
(参考Servlet的三大域对象和JSP的四大域对象)

试想:服务器接收到请求后解析出访问的servlet程序,然后servlet程序处理完请求之后,需要把整个html页面进行逐行输出(write),工作量巨大,页面冗余。

而有了jsp页面之后,我们只需在Servlet中请求转发或重定向到指定的jsp页面即可,不用在servlet中逐行输出html代码。因为我们可以把需要输出的html页面放在jsp中,把需要更新的部分,使用域对象中共享的数据进行更新。

但是,这种模式不可避免的存在前后端耦合的问题,因为我们在jsp(源自前端工程师设计的静态html页面)和servlet中操作了共同的域对象,被淘汰是必然的。

注:对于服务器而言,Servlet和JSP都是动态资源。Tomcat访问任何的资源都是在访问Servlet!JSP本身就是一种Servlet。

2. jsp的本质及编译过程

JSP是一种基于文本的程序,其特点就是HTML和Java代码共同存在!
记住一点:JSP本身就是一种Servlet,JSP就是封装了Servlet的java程序

编译过程
JSP在第一次被访问的时候会被(该类是HttpServlet的一个子类)
浏览器第一次请求jsp文件时,Tomcat服务器会将jsp页面编译为HttpJspPage类,该类是httpServlet的子类,并存储为java源文件。因此,JSP就是Servlet。
然后,将该文件编译成class文件,编译完毕后再运行class文件来响应浏览器的请求。

3. jsp语法

3.1 头部的page指令
<%@ page contentType=“text/html;charset=UTF-8” language=“java” %>
i. language 属性 表示 jsp 翻译后是什么语言文件。暂时只支持 java。
ii. contentType 属性 表示 jsp 返回的数据类型是什么。也是源码中 response.setContentType()
v. autoFlush 属性 设置当 out 输出流缓冲区满了之后,是否自动刷新冲级区。默认值是 true。 vi. buffer 属性 设置 out 缓冲区的大小。默认是 8kb
vii. errorPage 属性 设置当 jsp 页面运行时出错,自动跳转去的错误页面路径。

3.2 常用脚本
表达式脚本
表达式脚本的格式是:<%=表达式%>

<%=request.getParameter("username")%>

表达式脚本的作用是:在 jsp 页面上输出数据。
表达式脚本的特点:
1、所有的表达式脚本都会被翻译到_jspService() 方法中
2、表达式脚本都会被翻译成为 out.print()输出到页面上
3、表达式脚本中的表达式不能以分号结束。

代码脚本
代码脚本的格式是: <% java 语句 %>
代码脚本的作用是:可以在 jsp 页面中,编写我们自己需要的功能(使用 java 语句),仍是为了输出数据。
代码脚本的特点是:
1、代码脚本翻译之后都在_jspService 方法中
2、代码脚本还可以和表达式脚本一起组合使用,在 jsp 页面上输出数据

注:表达式脚本可用EL表达式替换;代码脚本可用JSTL标签库替换。(参看下文)

3.3 注释
i. html 注释 < !-- 这是 html 注释 -->
ii. java 注释 <% // 单行 java 注释 /* 多行 java 注释 */ %>
iii. jsp 注释 <%-- jsp 注释 --%> jsp 注释可以注掉页面中所有代码。

4. jsp九大内置对象与四大域对象

jsp 中的内置对象
是指 Tomcat 在翻译 jsp 页面成为 Servlet 源代码后,内部提供的九大对象,叫内置对象。

jsp中的四大域对象
四个域对象及其作用域分别是:
pageContext (PageContextImpl 类) 当前 jsp 页面范围内有效
request (HttpServletRequest 类) 一次请求内有效
session (HttpSession 类) 一个会话范围内有效(打开浏览器访问服务器,直到关闭浏览器
application (ServletContext 类) 整个 web 工程范围内都有效

域对象作用可以像 Map 一样存取数据

使用顺序
虽然四个域对象都可以存取数据,但在使用上它们是有优先顺序的,按照范围从小到大的顺序使用。晚创建、早销毁,节省资源
pageContext ====>>> request ====>>> session ====>>> application

5. 服务器创建的三大域对象(Servlet三大域对象)

详看:Servlet三大域对象,Jsp四大域对象
总结的很好,注意对象的创建、销毁、作用范围,以及服务器三大域对象的区别。
尤其是web资源需要共享一个请求的数据时,只能使用请求转发,不能使用重定向。

注:session是在服务器端建立的,浏览器访问服务器会有一个jsessionid,再以cookie的形式返回给浏览器。浏览器端通过 jsessionid定位服务器端的session。
session的创建和销毁由服务器端控制。
**当浏览器关闭后,session还存在在服务器端,只不过你新开的浏览器去访问服务器会创建另一个session。**这个时候的jsessionid已经不一样了,也就不能访问上一次的哪个session里面的 内容了。
还要考虑到session的生命周期,tomcat服务器默认的存活时间为30 minutes。

6. jsp的常用标签

6.1 静态包含

格式:<%@ include file=""%> ,file 属性指定你要包含的 jsp 页面的路径。
地址中第一个斜杠 / 表示为 http://ip:port/工程路径/ 映射到代码的 web 目录

静态包含的特点:
1、静态包含不会翻译被包含的 jsp 页面。
2、静态包含其实是把被包含的 jsp 页面的代码拷贝到包含的位置执行输出。

作用:抽取页面的共同内容,简化页面。

6.2 请求转发

格式:<jsp:forward page=""></jsp:forward> , page 属性设置请求转发的路径
功能是请求转发。

7. EL 表达式

EL 表达式的格式${表达式}
注:EL 表达式在输出 null 值的时候,输出的是空串。jsp 表达式脚本输出 null 值的时候,输出的是 null 字符串。

EL表达式的作用:代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。

EL表达式获取属性值的方法:EL表达式输出JavaBean属性时调用对应的get方法

7.1 EL表达式的常用运算:
语法:${ 运算表达式 }

empty 运算

empty 运算可以判断一个数据是否为空,如果为空,则输出 true,不为空输出 false。${ empty emptyStr }

三元运算

表达式 1?表达式 2:表达式 3 ; 如果表达式 1 的值为真,返回表达式 2 的值,如果表达式 1 的值为假,返回表达式 3 的值。

.点运算,可以输出 Bean 对象中某个属性的值

[]中括号运算,可以输出有序集合中某个元素的值

7.2 EL表达式的常用隐含对象:

EL 表达式中 11 个隐含对象,是 EL 表达式中自己定义的,可以直接使用。

1 pageContext PageContextImpl(类) 它可以获取 jsp 中的九大内置对象
可以通过获取九大内置对象得到1. 协议 2. 服务器 ip 3. 服务器端口 4. 工程路径 5. 请求方法 6. 客户端 ip 7. 会话的 id 编号等
例:获取工程路径:${ pageContext.request.contextPath }<br>
注:

<%-- 
request.getScheme() 获取请求的协议 
request.getServerName() 获取请求的服务器 ip 或域名 
request.getServerPort() 获取请求的服务器端口号 
getContextPath() 获取当前工程路径 
request.getMethod() 获取请求的方式(GET 或 POST) 
request.getRemoteHost() 获取客户端的 ip 地址 
session.getId() 获取会话的唯一标识 
--%>

2 pageScope Map<String,Object> 它可以获取 pageContext 域中的数据
3 requestScope Map<String,Object> 它可以获取 Request 域中的数据
4 sessionScope Map<String,Object> 它可以获取 Session 域中的数据
5 applicationScope Map<String,Object> 它可以获取 ServletContext 域中的数据
例如:${ applicationScope.key }

6 param Map<String,String> 它可以获取请求参数的值
7 paramValues Map<String,String[]> 它也可以获取请求参数的值,当请求参数有多个值的时候使用。

8 header Map<String,String> 它可以获取请求头的信息
9 headerValues Map<String,String[]> 它可以获取请求头的信息,当请求头的某个参数有多个值的时候使用。

10 cookie Map<String,Cookie> 它可以获取当前请求的 Cookie 信息

8. JSTL 标签库

常用的是核心标签库的几个标签。

<c:if /> if 标签用来做 if 判断,test 属性表示判断的条件(使用 EL 表达式输出)。

<c:if test="${ 12 == 12 }">
	 <h1>12 等于 12</h1> 
</c:if>

<c:choose> <c:when> <c:otherwise> 标签 作用:多路判断。跟 if - else if - else非常接近。
choose 标签开始选择判断
when 标签表示每一种判断情况 test 属性表示当前这种判断情况的值
otherwise 标签表示剩下的情况
注:when 标签的父标签一定要是 choose 标签,不能是otherwise标签。

<c:choose> 
<%-- 这是 html 注释 --%> 
	<c:when test="${ requestScope.height > 190 }"> <h2>小巨人</h2> </c:when> 
	<c:when test="${ requestScope.height > 180 }"> <h2>很高</h2> </c:when> 
	<c:when test="${ requestScope.height > 170 }"> <h2>还可以</h2> </c:when>
	<c:otherwise> 
		<c:choose> 
			<c:when test="${requestScope.height > 160}"> <h3>大于 160</h3> </c:when> 
			<c:when test="${requestScope.height > 150}"> <h3>大于 150</h3> </c:when> 
			<c:when test="${requestScope.height > 140}"> <h3>大于 140</h3> </c:when> 
			<c:otherwise> 其他小于 140 </c:otherwise> 
		</c:choose> 
	</c:otherwise> 
</c:choose>

<c:forEach /> 作用:用于遍历输出。
items属性 表示遍历的数据源(遍历的集合);
var 属性表示当前循环的变量(也是当前正在遍历到的数据) ;
begin 属性设置开始的索引 end 属性设置结束的索引 step 属性表示遍历的步长值 。

<c:forEach items="${ requestScope.arr }" var="item">
	${ item } <br> 
</c:forEach>
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值