1 JSP
1.1 JSP概述
1.1.1 jsp介绍
由SUN公司提供的动态web资源的开发技术, 看起来非常像html, 但是可以在JSP页面中写java代码, 所以JSP是一种动态web资源开发技术.
1.1.2 JSP技术的由来
JSP的出现是为了解决Servlet在响应时不适合向外输出页面的问题
Servlet本质上是一段java代码, 非常适合处理逻辑, 但是不合适向外输出页面。
HTML适合用来开发页面, 展示数据, 但是HTML开发出来的页面本质上就是一个文档, 无法展示动态的数据。
JSP非常适合编写HTML代码, 适合作为响应页面向外输出, 同时JSP里可以写java代码, 也可以展示动态的数据。
所以JSP可以解决既要处理逻辑又要向外输出页面的难题。
JSP在第一次访问时, 会被翻译成一个Servlet, 对JSP访问后看到的页面 其实就是翻译后的Servlet在向外输出!!
1.2 JSP语法
1.2.1 模版元素
直接写在jsp页面中的html内容称之为jsp页面中的模版元素
模版元素在翻译过来的Servlet中被out.write()原样输出到浏览器中
out.write("\tday13....index.jsp........\r\n");
1.2.2 JSP表达式
<%= 脚本表达式 %> 常量 变量 表达式(3+4)
在翻译过来的Servlet中, 计算表达式的值原样输出
out.print( 100+123 );
1.2.3 JSP脚本片段
<% 若干java语句 %> Scriptlet
在翻译过来的servlet中, 脚本片段被复制粘贴到对应位置执行
翻译前:
<% for(int i=0; i<5; i++){ %>
Hello JSP~~~~~<br/>
<% } %>
翻译后:
for(int i=0; i<5; i++){
out.write("\r\n");
out.write("\t\tHello JSP~~~~~<br/>\r\n");
out.write("\t");
}
多个脚本片段之间的变量可以互相访问
在某一个脚本片段中的java代码可以是不完整的, 但是要求在翻译过来的servlet中整体的代码必须是完整符合java语法的
任何文本,HTML标记,JSP元素必须在脚本片段之外
1.2.4 JSP声明:(不常用)
格式: <%! java代码 %>
写在jsp声明中的内容, 在翻译过来的servlet中会和servlet方法平级成为类的成员
( 注意: 写在JSP脚本片段中的内容, 在翻译过来的servlet中是方法的局部变量! )
1.2.5 JSP注释:
格式: <%-- JSP注释 --%>
<%-- out.write("aaa"); --%> 被JSP注释注释的内容, 在翻译的过程中被抛弃, 不会被翻译
<% //out.write("bbb"); %> 被java注释注释的内容, 在翻译的过程中被当作脚本片段翻译到servlet中, 但是由于被注释了, 所以也不会执行
<!-- <% out.write("ccc"); %> --> 被HTML注释注释的内容, 在翻译过程中直接当作模版元素原样输出到浏览器, 但是浏览器认为是注释, 所以不予显示
!!!在jsp中最好使用jsp注释, html注释慎用!!
1.2.6 JSP指令:
<%@ 指令名称 若干属性声明... %>
-- 不会直接产生输出, 用来指挥JSP解析引擎如何来翻译当前JSP页面中其他部分的内容
1.page指令
-- 用来声明当前JSP页面的基本属性的, page指令可以写在JSP页面的任意位置, 但是为了可读性考虑, 一般情况下最好放在JSP页面的最前面
格式: <%@ page ... %>
page指令属性介绍
~~(1) [ language="java" ]
当前JSP使用的开发语言
~~(2) [ extends="package.class" ]
当前JSP翻译成servlet后要继承的类,注意此值必须是一个servlet的子类,一般情况下不要改
!!(3) [ import="{ package.class | package.*}, ..." ]
导入需要使用到的包
java.lang.*;
javax.servlet.*;
javax.servlet.JSP.*;
javax.servlet.http.*;
可以在一个page指令的import属性中导入多个包 也可以通过多个page指令来分别导包
示例:
<%@ page language="java" import="java.util.*,java.sql.*" pageEncoding="utf-8" isErrorPage="true"%>
<%@ page import="java.io.*" %>
!(4) [ session="true | false" ]
用来指定当前页面是否使用session,如果设置为true,则翻译过来的servlet中将会有对session对象的引用,于是可以直接在JSP中使用session隐式对象。但是这将导致一旦访问JSP就会调用request.getSession()方法,可能导致不必要的空间浪费。如果确定JSP中不需要session可以设为false
(5) [ errorPage="relative_url" ]
如果页面出错,将要跳转到的页面,除了在JSP中使用此属性指定错误页面外也可以在web.xml中配置整个web应用的错误页面,如果两个都设置则JSP中的此属性起作用
配置示例:
<error-page>
<exception-type>java.lang.Throwable</exception-type>
<location>/error/500.jsp</location>
</error-page> -->
<error-page>
<error-code>404</error-code>
<location>/error/404.jsp</location>
</error-page>
(6) [ isErrorPage="true | false" ]
如果设置此属性为false, 翻译过来的servlet中将不会含有Exception隐式对象,其中封装的就是上一个页面中抛出的异常信息
!!(7) [ pageEncoding="characterSet | ISO-8859-1" ]
服务器翻译JSP时使用的编码集.
如果想防止JSP乱码,应该保证文件的保存编码和JSP翻译成servlet用的编码以及输出到浏览器后浏览器打开的编码一致.此属性一旦设置好,翻译引擎会间接帮我们设置content-type属性.
(8) [ buffer="none | 8kb | sizekb" ] out隐式对象所使用的缓冲区的大小
(9) [ autoFlush="true | false" ] out隐式对象是否自动刷新缓冲区,默认为true,不需要更改
2.include指令
<%@ include file="" %> -- 可以实现页面包含的效果
(1)include指令实现的包含叫做静态包含:
多个JSP文件翻译成一个servlet, 最终由这一个servlet向外输出数据, 这是源文件级别的包含
(2)其他方式的包含叫做动态包含:
被包含的页面各自翻译成servlet, 包含的过程其实就是各个servlet分别执行后在输出流上的合并
总结: 静态包含在效率上更高一些, 尽量使用静态包含.
3.taglib指令
导入tld标签库文件
JSTL标签库
1.3 JSP的九大隐式对象
JSP翻译引擎在将JSP翻译成servlet的过程中, 在servlet里预先定义了九个对象, 因此我们可以在JSP页面中直接使用这九个对象
page(this)
Request request
Response response
Config selvetconfig
Application servletcontext
Session session
Exception exception
Out response.getwriter()
pageContext
1.4 ,九大内置对象到底是哪九大呢?
[plain] view plain copy
1. 内置对象名 类型
2. request HttpServletRequest
3. response HttpServletResponse
4. config ServletConfig
5. application ServletContext
6. session HttpSession
7. exception Throwable
8. page Object(this)
9. out JspWriter
10. pageContext PageContext
1.5 三,解析几个内置对象
1.5.1 1)out对象对象,对象类型是JspWriter类,相当于带缓存的PrintWriter(不带缓存)
PrintWriter:write("内容") 直接向浏览器输出内容
JspWriter:writer("内容") 向jsp缓冲区写出内容
JspWriter当满足以下条件时之一时,缓冲区的内容写出:
a,缓冲区满了
b,刷新缓冲区
c,关闭缓冲区
d,jsp页面执行完毕
1.5.2 2)pageContext对象
pageContext的对象类型是PageContext,叫jsp的上下文对象.
pageContext作用:可以获取其他八个内置对象
[plain] view plain copy
1. //示例:
2. pageContext.getOut();
3. pageContext.getServletConfig()
使用场景:在自定义标签时会频繁使用到PageContext对象;或者是定义一个方法需要用到多个对象时,传一个pageContext对象就能解决问题.
1.6 四,JSP中四大域对象
1.6.1 分类:
[plain] view plain copy
1. ServletContext context域
2. HttpServletRequet request域
3. HttpSession session域 --前三种在学习Servlet时就能接触到
4. PageContext page域 --jsp学习的
域对象的作用:保存数据,获取数据,共享数据.
1.6.2 保存数据:
[plain] view plain copy
1. pageContext.setAttribute("内容");//默认保存到page域
2. pageContext.setAttribute("内容",域范围常量);//保存到指定域中
3. //四个域常量
4. PageContext.PAGE_SCOPE
5. PageContext.REQUEST_SCOPE
6. PageContext..SESSION_SCOPE
7. PageContext.APPLICATION_SCOPE
1.6.3 获取数据:
[plain] view plain copy
1. pageContext.getAttribute("内容");
2. <p>pageContext.getAttribute("name",<span style="font-family:宋体;">域范围常量</span><span style="font-family:Calibri;">);</span></p>//自动在四个域中搜索数据
3. pageContext.findAttribute("内容");//在四个域中自动搜索数据,顺序:page域->request域->session域->application域(context域)
1.6.4 域作用范围:
[plain] view plain copy
1. page域: 只能在当前jsp页面使用 (当前页面)
2. request域: 只能在同一个请求中使用 (转发)
3. session域: 只能在同一个会话(session对象)中使用 (私有的)
4. context域: 只能在同一个web应用中使用 (全局的)
1.6.5 out隐式对象
相当于response.getWriter();
区别在于out对象自带缓冲区, 如果out和response.getWriter()混用可能会造成输出顺序上混乱
page指令中buffer和autoflush就是用来设置out缓冲区的
总结起来一句话, 如果想要在JSP页面中输出内容, 直接使用out, 尽量别使用response.getWriter();
1.6.6 pageContext隐式对象
代表当前JSP页面的运行环境的对象, 通过该对象可以访问页面中的共享数据
PageContext对象功能:
(1) 作为入口对象获取其他八大隐式对象
getPage()方法 返回page隐式对象
getRequest()方法 返回request隐式对象
getResponse()方法 返回response隐式对象
getServletConfig()方法 返回config隐式对象
getServletContext()方法 返回application隐式对象
getSession()方法 返回session隐式对象
getException()方法 返回exception隐式对象
getOut()方法 返回out隐式对象
(2) 本身也是一个域对象, 也可以作为入口对象来操作其他三大作用域中的数据
a)本身是个域对象,并提供了方法操作域中的属性
setAttribute(String name, Object obj);
getAttribute(String name);
removeAttribute(String name);
getAttributeNames();
生命周期: 访问JSP页面开始时创建, 访问JSP页面结束时销毁
作用范围: 当前JSP页面
主要功能: 在当前JSP页面中共享数据
四大域对象的作用范围大小排序:ServletContext > Session > request > pageContext
b)作为入口对象, 可以操作其他三大作用域
setAttribute(String name, Object value,int scope)
getAttribute(String name,int scope)
removeAttribute(String name,int scope)
其中pageContext中代表域的常量:
PageContext.APPLICATION_SCOPE
PageContext.SESSION_SCOPE
PageContext.REQUEST_SCOPE
PageContext.PAGE_SCOPE
pageContext对象还额外提供了findAttribute(String name)方法,该方法会按照由小到大的顺序在四大作用域中搜寻指定名称的属性, 如果找到就返回, 如果都找不到就返回一个null
(3) 提供了便捷方法实现请求转发和包含
下面是通过request对象实现请求转发或包含:
request.getRequestDispatcher("/7.jsp").forward(request, response);
request.getRequestDispatcher("/7.jsp").include(request, response);
或通过page指令实现包含:
<%@include file="xxx.jsp" %>
pageContext对象实现请求转发或包含:
转发: pageContext.forward("/index.jsp");
包含: pageContext.include("/index.jsp");
1.7 JSP标签技术
在JSP页面中写入大量的java代码会导致JSP页面中html代码和java代码混杂在一起, 会造成页面非常的混乱, 难于维护
于是在JSP的2.0版本中, sun提出了JSP标签技术, 推荐使用标签来代替JSP页面中java代码, 并且推荐, JSP2.0以后不要在JSP页面中出现任何一行java代码。
1.7.1 JSP标签 -- sun开发的JSP页面的标签技术, 包含了不少标签, 但是不太好用, 我们只要求掌握三个
<jsp:forward> 用来替代request.getRequestDispatcher().forward()
<jsp:include> 用来替代request.getRequestDispatcher().include()
<jsp:param> 配合前两个标签使用,可以在包含或转发时,带一些参数过去
1.7.2 EL表达式
EL表达式, 可以非常方便替代JSP页面中的JSP表达式(<%= %>)
基本结构: ${ 表达式 }
EL只能获取不能设置!!!
EL只能获取不能遍历!!!
EL表达式提供了如下功能:
Ø 获取数据
1.1.1. 获取变量:在四大作用域中搜寻属性
${propName}在四个域中搜寻proName属性,输出该值到输出流中
搜寻域的顺序为由小到大。
如果四大域中都搜寻不到,则什么都不输出。
1.1.2. 获取变量:获取指定域中的属性
${pageScope/requestScope/sessionScope/applicationScope.proName}
获取指定域中的属性
Ø
获取常量: 支持 数字/字符串/布尔值, 整个el表达式的值就是当前常量的值
获取变量: el表达式可以获取变量的值, 在获取时它的底层会调用pageContext的findAttribute()方法按照由小到大的顺序在四大作用中搜寻指定名称的值, 如果找到就直接返回该值, 如果找不到就什么也不输出
获取数组中的数据: 可以通过 数组变量名[数字] 来获取域中数组中的内容
获取集合中的数据: 可以通过 集合变量名[数字] 来获取域中集合中的内容
获取map中的数据: 可以通过 map变量名[键] 或者是 map变量名.键 获取map中的数据
1.1.3. 获取变量:获取javabean属性
${bean.propName}获取javaBean的属性,可以认为是调用了javaBean的getXXX方法,
最重要的一个应用场景:
在写路径的时候最好不要把web应用名称写死,java中应该用request.getContextPath去获取,jsp中就用el获取:
${pageContext.request.contextPth}
1.1.4. 获取数据细节
获取javaBean中的属性: 在获取javaBean中的属性值时, 点什么就相当于get什么(比如: p.username <==> p.getUsername())
## 之前获取web应用的名称是通过 <%= request.getContextPath() %>
但是这种写法不推荐, 推荐使用el表达式来获取: ${ pageContext.request.contextPath }
1.1.5. 获取数据细节
1.1. 进行简单运算
1.1.1. 算数运算
${3+2}
${“3”+2}
${“3”+2}
${1+”a”}
所有参与元算的元素都会被转成数字,如果不能转就报错,空元素参与运算当作没参与。
1.1.2. 关系运算:
如图-2所示:
图-2
${3 > 2}
${3 gt 2}
1.1.3. 逻辑运算:
如图-3所示:
图-3
${3>2 && 4>5}
1.1.4. Empty运算符
empty/not empty判断对象是否为null,判断集合是否为空,数组长度是否为0,判断字符串是否为空串,判断域中是否没有任何属性。
1.1.5. 三元表达式
${name == null ? "张三" : name;}
(1)和[]区别:使用点的地方都可以用中括号,如果属性名是数字或包含特殊符号(.-)就必须使用中括号。例子:${map["first.name"]}
(2)EL只能获取不能设置
(3)EL只能获取不能遍历
Ø 执行运算
算术运算
在El表达式中, 加号只是一个运算符, 不能作为连接符使用.
在进行算术运算时, 对于非数字会试图先转换成数字再参与运算, 如果转换不成功就会抛异常!!
关系运算
> gt
< lt
>= ge
<= le
!= ne
== eq
逻辑运算
&& and
|| or
! not
三元表达式
表达式 ? "xx" : "xx"
empty运算:
判断对象是否为null,
判断字符串是否为空字符串,
判断数组是否为空数组,
判断集合中是否没有任何元素,
判断域对象中是否没有任何属性
(3) 获取常用开发对象
1.1.6. EL的内置对象
El中预先定义了11个内置对象,不需要提前存入域中个,可以直接在el使用。
如图-4、图-5所示:
图-4
(4)
el中内置了11个常用对象, 可以不用预先存入域中就可以使用
代表当前JSP页面环境的pageContext对象
!!!pageContext - 有了它就意味着el中就有了其他八大隐式对象
代表四大作用域的隐式对象, 用来明确指定从哪个域中查找数据
!!!pageScope -- pageContext
!!!requestScope -- request
!!!sessionScope -- session
!!!applicationScope -- ServletContext
注意: 上面这四个对象只能代表四大作用域对象身上的那个域!!
请求参数组成的map
!!!param - Map<String, String>
paramValues - Map<String, String[]>
请求头组成的map
header -- Map<String, String>
headerValues - Map<String, String[]>
key为请求头的名字
所有cookie信息组成的map
!!!cookie -- Map<String, Cookie>
key为Cookie的名字, 值为Cookie对象
例如:
Cookie cookie1 = new Cookie("c1", "111")
Cookie cookie2 = new Cookie("c2", "222")
Cookie cookie3 = new Cookie("c3", "222")
Response.addCookie(cookie1);
c2:cookie2
c3:cookie3
${ cookie.c1.value } 可以获取 "111"
所有web应用初始化信息组成的map
initParam -- Map<String, String>
key初始化参数的名字, value为参数对应的值
1.7.3 JSTL标签库
1.1.7. JSTL标签库子库
核心标签库 (core) --- c
国际化标签 fmt
数据库标签 sql --Servlet JSP
XML标签 xml
JSTL函数(EL函数) fn
1.2. JSTL核心标签库
1.2.1. <c:out>
如图-6所示:
图-6
输出固定值 <c:out value="Hello c out~"/> 输出变量 <c:out value="${m}"/> 转义html,默认为转义,可以设置escapeXml属性为false,禁止转义 <c:out value="<a href='#'>link</a>" escapeXml="false"/> 允许输出默认值,如果给定值不存在,输出默认值 <c:out value="${city}" default="北京"/>
1.2.2. <c:set>
如图-7所示:
图-7
标签用于把某一个对象存在指定的域范围内,或者设置Web域中的java.util.Map类型的属性对象或JavaBean类型的属性对象的 属性。
在指定域中增加、修改属性 <c:set var="name" value="value" scope="page"/> 设置一个保存在四个范围的java对象的属性值,cset不能设置对象进域,但是可以更改域中对象的属性 <c:set targe="${person}" property="name" value="lisi"/>
1.2.3. <c:remove>
标签用于删除各种Web域中的属性
<c:remove var="varName" [scope="{page|request|session|application}"] />
1.2.4. <c:catch>
标签用于捕获嵌套在标签体中的内容抛出的异常,其语法格式如下:
<c:catch var="e"> <% String s = null; s.charAt(1); %> </c:catch>
1.2.5. <c:if>
如图-8所示:
图-8
此标签可以构造简单的“if-then”结构的条件表达式 。
1.2.6. <c:choose>
标签用于指定多个条件选择的组合边界,它必须与<c:when>和<c:otherwise>标签一起使用。使用<c:choose>,<c:when>和<c:otherwise>三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构。
<c:choose> <c:when test="${weekday==1}"> 星期一 </c:when> <c:when test="${weekday==1}"> 星期二 </c:when> <c:when test="${weekday==1}"> 星期三 </c:when> <c:otherwise> 输入无效 </c:otherwise> </c:choose>
1.2.7. <c:forEach>
标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。
如图-9所示:
图-9
varStatus属性,如图-10所示:
图-10
实验:遍历10到100的偶数,如果数字所在的位置是3的倍数,显示成红色
1.2.8. <c:forTokens>
用来浏览一字符串中所有的成员,其成员是由定义符号所分隔的
1.2.9. <c:param>
在JSP页面进行URL的相关操作时,经常要在URL地址后面附加一些参数。<c:param>标签可以嵌套在<c:import>、<c:url>或<c:redirect>标签内,为这些标签所使用的URL地址附加参数。
1.2.10. <c:import>
标签,实现include操作,如图-11所示:
图-11
1.2.11. <c:url>
如图-12所示:
图-12
标签用于在JSP页面中构造一个URL地址,其主要目的是实现URL重写。URL重写就是将会话标识号以参数形式附加在URL地址后面
1.2.12. <c:redirect>
此标签用于实现请求重定向。如图-13所示:
Ø JSTL:通用的JSP标签库 提供了实现java代码中最常见功能的操作标签(taglib指令)
Ø 为javaweb开发人员提供的一套标准通用的标签库, 可以和el配合起来替JSP页面中的大部分的java代码
Ø javaee4.0及其之前的版本中, 在使用前需要导入jstl开发包, 在javaee5.0及其以后版本中内置了jstl开发包, 所以不需要我们手动导入就可以直接使用了!!
Ø JSTL标签库中包含的标签:
~~<c:out> 标签用于输出一段文本内容到pageContext对象当前保存的“out”对象中。
!!!<c:set> 标签用于把某一个对象存在指定的域范围内,或者设置Web域中的java.util.Map类型的属性对象或JavaBean类型的属性对象的属性。
<c:remove> 标签用于删除各种Web域中的属性
<c:catch> 标签用于捕获嵌套在标签体中的内容抛出的异常,其语法格式如下:<c:catch [var="varName"]>nested actions</c:catch>
!!!<c:if test=""> 标签可以构造简单的“if-then”结构的条件表达式
!!!<c:choose> 标签用于指定多个条件选择的组合边界,它必须与<c:when>和<c:otherwise>标签一起使用。使用<c:choose>,<c:when>和<c:otherwise>三个标签,可以构造类似 “if-else if-else” 的复杂条件判断结构。
!!!<c:forEach> 标签用于对一个集合对象中的元素进行循环迭代操作,或者按指定的次数重复迭代执行标签体中的内容。
<c:forTokens> 用来浏览一字符串中所有的成员,其成员是由定义符号所分隔的
<c:import> 标签,实现include操作
<c:redirect>标签用于实现请求重定向
<c:url>标签用于在JSP页面中构造一个URL地址,其主要目的是实现URL重写。URL重写就是将会话标识号以参数形式附加在URL地址后面
<c:param>标签 在JSP页面进行URL的相关操作时,经常要在URL地址后面附加一些参数。<c:param>标签可以嵌套在<c:import>、<c:url>或<c:redirect>标签内,为这些标签所使用的URL地址附加参数。
1.7.4 案例: 改造EasyMall项目, 将其中的java代码用EL+JSTL进行替换。
1.编辑_head.jsp
(1)用JSTL+EL替换_head.jsp中的路径
将路径中的 <%= request.getContextPath() %> 替换为:
${ pageContext.request.contextPath }
(2)获取用户登陆状态, 用JSTL+EL替换原有的java代码
注意: 在用JSTL标签库之前先引入库:
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!-- 如果用户没有登陆, 就提示用户登陆或注册 -->
<c:if test="${ (empty sessionScope) || empty sessionScope.user }">
<a href="<%=request.getContextPath() %>/login.jsp">登录</a> |
<a href="<%=request.getContextPath() %>/regist.jsp">注册</a>
</c:if>
<!-- 如果用户已经登陆, 提示欢迎xxx回来 -->
<c:if test="${ !((empty sessionScope) || empty sessionScope.user)}">
欢迎 <%= request.getSession().getAttribute("user") %> 回来 |
<a href="<%=request.getContextPath() %>/LogoutServlet">退出</a>
</c:if>
2.编辑index.jsp和_foot.jsp
将路径中的 <%= request.getContextPath() %> 替换为:
${ pageContext.request.contextPath }
3.编辑regist.jsp
(1)将路径中的 <%= request.getContextPath() %> 替换为:
${ pageContext.request.contextPath }
(2)注册失败时, 获取错误提示消息
将页面中获取注册失败后的
<%= request.getAttribute("msg") == null ? "" : request.getAttribute("msg") %>
错误提示代码替换为:
${ msg }
(3)注册失败时, 输入框数据进行回显
将
<input type="text" name="username" value="<%= request.getParameter("username")==null? "" : request.getParameter("username") %>"/>
替换为:
<input type="text" name="username" value="${ param.username }" />
其他输入项略...
4.编辑login.jsp
(1) 将路径中的 <%= request.getContextPath() %> 替换为:
${ pageContext.request.contextPath }
(2) 登陆失败时, 获取错误提示消息
将
<%= request.getAttribute("msg") == null ? "" : request.getAttribute("msg") %>
替换为:
${ msg }
(3) 获取Cookie中保存的用户名
//获取Cookie中的用户名
<td>
<input type="text" name="username" value="${ cookie.remname.value }"/>
</td>
//利用js代码对用户名进行url解码
window.onload = function(){
var oInp = document.getElementsByName("username")[0];
//利用js代码对用户名进行url解码
var username = decodeURI(oInp.value);
oInp.value = username;
}
//勾选记住用户名输入框
<input type="checkbox" name="remname" value="true"
${ empty cookie.remname ? "" : "checked='checked'" }
/>记住用户名
四大作用域的比较
ServletContext: 代表整个WEB应用的对象, 在整个WEB应用范围内都可以访问到.
生命周期:
在服务器加载WEB应用之后立即创建, WEB应用被移出容器时销毁
作用范围:
整个WEB应用
主要功能: 在整个WEB应用范围内共享数据
Session:
生命周期:
第一次调用request.getSession()方法时创建, 销毁包括超时(如果30分钟不使用session)、自杀(调用invalidate方法)、意外身亡(当服务器意外关闭时)!
作用范围:
一次会话范围内
主要功能:
在整个会话范围内实现数据的共享
request: 代表HTTP请求的对象
生命周期:
一次请求开始时创建, 一次请求结束后销毁
作用范围:
整个请求链
主要功能:
在一次请求中共享数据(注册失败后转发回注册页面提示错误消息)
pageContext: 代表JSP运行环境的对象
生命周期:
在开始访问JSP时创建, 访问JSP结束时销毁!
作用范围:
在整个JSP范围内
主要功能:
在整个JSP范围内共享数据
1.8 问题
如果再jsp中使用了jstl标签库, 出现如下错误:
原因在于, 在将EasyMall项目发布到www.easymall.com主机时, 并没有将jstl相关的包发布过去, 所以才导致上面的错误
解决方案: 自己手动将jstl的包拷贝到EasyMall项目中的lib目录下, 再次发布项目, 重新启动服务器即可!!
1.2.13.
1.2.14. 改造index.jsp
1.9 耦合和解耦
1.9.1 耦合
所谓的耦合指的是在软件开发中,在层与层之间产生了某种紧密的关系,这种关系可能会导致,在我们修改或者是替换某一层时会影响其他的层,像这种情况我们就称之为层与层之间产生了耦合。
由于耦合(层与层之间的紧密关系)可能会导致我们在修改某一层时影响到其他的层,而这严重违反了我们对软件进行分层的最初设想 -- 软件各层之间应该相互独立、互不干扰,在修改或者是替换某一层时,应该做到不影响其他层。
1.9.2 解耦
去除耦合的过程,称为解耦。
首先应该在开发程序时保证不要胡乱传递只属于某一层特有的对象或跨层调用只属于某一层特有的方法,从而避免产生不必要的耦合。但是无论如何小心,层与层之间最终还是会有关系,对于这种无法避免的耦合,我们应该想办法管理起来。
解耦: 接口+配置文件+工厂