jsp/servlet学习笔记(核心编程)mvc部分

MVC

第十五章 servlet和jsp的集成 模型-视图-控制器
servlet擅长处理数据 jsp擅长构建HML表示请求结果

初始请求由servlet处理。servlet调用商业逻辑和数据处理代码,并创建Bean表示相应的结果(模型),然后servlet确定哪个JSP页面适用于表达这些特定结果,并将请求转发到相应的页面(JSP页面即视图)。由servle就是控制器

使用RequestDirpatcher实现MVC
(1)使用Bean表示数据
(2)使用servlet处理请求
(3)使用Bean
(4)将bean存储到请求、会话或者servlet上下文
servlet调用请求会话或者servlet上下文对象的setAttribute方法,存储表示请求结果的bean引用
(5)将请求分发到jsp页面
servlet确定使用哪个jsp页面,并使用RequsetDispacher的forword方法将控制转移到那个页面
(6)从Bean中提取数据
jsp页面使用jsp:useBean以及第四步相对应的scope,访问Bean。之后jsp使用jsp:getProperty输出bean的属性。jsp页面并不创建或修改Bean,只是提取和显示servlet创建的数据

1.定义bean表示对象
一般都是由servlet或其他jaba程序创建bean,所以对象只需要遵循正常的推荐准则:保持实例变量私有,且遵顼set/get访问器方法。
jsp页面页面只需要访问bean,不需要创建或者修改他们。因此一种惯常的做法就是定义值对象:仅用来表示结果,只有很少甚至根本没有任何其他功能

2.编写servlet处理请求
编写servlet读取请求信息。采用mvc方案时,servlet并不创建任何输出,输出完全由jsp页面来完成。因此不会调用response.setContentType,response.getWrite和out.println

3.填写bean
填写bean 读取表单参数后,依据它们确定请求结果。

4.结果的存储
servlet主要可以在三个位置存储jsp页面所需要的数据:httpServletRequest,httpSession,ServletContext.这些位置对应jsp:usebean的scope的三种非默认值:request, session,application

(1)存储仅有jsp页面在当前请求中使用的数据
ValueObject value = new ValueObject(...);
request.setAttribute("key",value);

servlet降请求转发给jsp,jsp使用下面的语句检索数据
<jsp:useBean id="key" type="package.ValueObject" scope="request">

(2)存储当前请求及同一用户的后续请求由jsp使用的数据
ValueObject value = new ValueObject(...);
HttpSession session = request.getSession();
sessiont.setAttribute("key",value);

servlet降请求转发给jsp,jsp使用下面的语句检索数据
<jsp:useBean id="key" type="package.ValueObject" scope="session">

(3)存储当前请求及任意客户的后续请求
ValueObject value = new ValueObject(...);
getServletContext().setAttribute("key",value);

servlet降请求转发给jsp,jsp使用下面的语句检索数据
<jsp:useBean id="key" type="package.ValueObject" scope="application">

5.转发请求到jsp页面
使用RequestDirpatcher的forword方法转发请求。需要调用SercletRequest的getRequestDirpatcher方法并提供相对地址;该地址可以指定WEB-INF目录中的地址;WEB-INF文件不允许客户直接访问,但服务器可以将控制权转移过去。
使用forword转移地址,提供HttpServletRequest和HttpServletResponse作为参数。这与HttpServletRequest方法中的sendRedirect方法不同。
forword不会引入额外请求,转移后url地址不会发生变化。使用sendRedirect方法用户看到的时servlet的地址

RequestDispatcher dispatcher =request.getRequestDispatcher("/WEB-INF/SomePage.jsp");
dispatcher.forward(request, response);

(1)转移静态html。如果html包含post请求,可以将.html改成.jsp。静态页面支持get请求但不支持post请求。

(2)重定向替代转发
使用基于会话的数据共享时,有些情况下,使用response.sendRedirect会更合适。
区别:
forword:控制转移完全在服务器中进行。不涉及任何网络数据流。用户不会看到jsp目前的页面。将该页面放在web-inf里防止用户直接访问。
sendRedirect:控制转移通过向客户端发送302状态代码和Location响应报头来完成。转移需要另外的网络往返。用户可以看到页面的地址,并记录下来,独立的访问。所有的数据都可以从会话中提取出来,甚至不涉及servlet的请求。

6.从Bean中提取数据
请求到达jsp页面之后,jsp页面使用jsp:useBean和jsp:getProterty提取数据。

(1)jsp页面不创建对象。servlet,而非jsp页面,应该创建所有数据对象。为了保证jsp页面不会创建对象,应该是用
<jsp:useBean ... type="package.Class"/>
代替:
<jsp:useBean ... class="package.Class"/>
(2)jsp页面不应该修改对象 因此只能使用getProperty而不应该使用setProperty
所指定的scope应该与servlet使用的存储位置相匹配。

mvc汇总:
1.基于请求
ValueObject v = new ValueObject();
request.setAttribute("key",v);
RequestDispatcher dispatcher = request.getRequestDispatcher("/web-inf/some.jsp");
dispatcher.forward(request,response);

<jsp:useBean id="key" type="package.ValueObject" scope="request">
<jsp:getProperty name="key" Property="someProperty">

2.基于会话
ValueObject v = new ValueObject();
HttpSession session = request.getSession();
session.setAttribute("key",v);
RequestDispatcher dispatcher = request.getRequestDispatcher("/web-inf/some.jsp");
dispatcher.forward(request,response);

<jsp:useBean id="key" type="package.ValueObject" scope="session">
<jsp:getProperty name="key" Property="someProperty">

3.基于应用数据共享
基于应用数据共享,servlet将bean存储在ServletContext中,Web应用中任何servlet都可以访问它,为了保证jsp页面提取出来数据与servlet插入的数据完全相同,应该采用下属的方式对代码进行同步。
synchronized(this) {
ValueObject v = new ValueObject();
HttpSession session = request.getSession();
session.setAttribute("key",v);
RequestDispatcher dispatcher = request.getRequestDispatcher("/web-inf/some.jsp");
dispatcher.forward(request,response);
}

<jsp:useBean id="key" type="package.ValueObject" scope="application">
<jsp:getProperty name="key" Property="someProperty">

目的页面相对于URL的解释
sendRedirect相当于断开之前的请求重新链接
forword在服务器中跳转,保留之前请求的数据

jsp:useBean id值一定时唯一的

从jsp页面转发请求
可以使用<jsp:forword page="url">,还可以使用jsp:param元素添加额外请求参数

输出页面组合
RequestDispatcher的forword方法依靠目的jsp页面全部输出。使用RequestDispatcher的include方法,可以将页面组合在一起进行显示。RequestDispatcher的include方法就是jsp:include动作在调用后台代码。

String table1,table2,table3;
if(somaCondition) {
table1 = "url1";
table2 = "url2";
table3 = "url3";
}else if(...) {...}

RequestDispatcher dispatcher = dispatcher.getRequestDispatcher(table1);
dispatcher.include(request,response);

dispatcher = dispatcher.getRequestDispatcher(table2);
dispatcher.include(request,response);

dispatcher dispatcher.getRequestDispatcher(table3);
dispatcher.include(request,response);

第十六章 简化对jsva代码的访问:jsp2.0表达式语句
为了计算和输出存储在标准位置的java对象的值,jsp2.0引入了简捷的语法。表达式语言(EL)是jsp2.0最重要的两项特征。另一个是自定义标签

传统mvc的不便之处在于,最后一步jsp页面输出时使用jsp:useBean和jsp:setProperty,使用这些元素比较冗余笨拙,且jsp:setProperty只能对简单的属性进行访问。如果子属性时另一个Bean时,就只能用到复杂的java语法。
使用jsp2.0表达式就能尽量的简化,它允许使用更简单更易读的项。
$(expression)
来替代或难以维护的jsvs脚本以及jsp:useBean和jsp:setProperty
早期的jsp版本不支持jsp2.0的语法,可以在web.xml禁用,也可以在单个页面设置isELEnable="false"
综述:
(1)精确访问存储对象
输出"作用域变量"(用setAttribute存储在PageContext,HttpSession,HttpServletRequesr,ServletContext中的对象)saleTiem,使用${saleItem}
如果用到 $,'," 使用转义字符转义\$,\',\"

要输出作用域变量的值,只需要在表达式语言元素中使用它的名字 ${name}
等价于
<%=pageContext.findAttribute("name")%>
或者
<jsp:useBean id="name" type="somePackage.class" scope="...">
<%=name%>
一般来说,在mvc中,servlet存储的对象几乎总是使用唯一的值。如果又重复的属性名,表达式语言以pageContext,HttpServletRequesr,httpSession,ServletContext的顺序进行搜索属性并输出第一个被搜索到的属性名的值。

(2)Bean属性简略记法(用到了反射)
${company.companyName}等价于
company.getcompanyName
同时可以嵌套
${company.getcompanyName.firstName}

使用[]有同样的效果
${company["companyName"]}
使用[]可以把括号[]里面的值作变量处理

(3)对集合的简单访问
访问数组lisp或map的元素,使用
${variable[indexOrKey]}
对于map来说,如果内部键名符合java的明明规则,则 ${variable.indexOrKey} 同样有效

(4)使用预定义隐式对象对请求,cookie以及其他请求数据进行访问
1.pageContext
引用当前页面的pageContext。拥有request,session,out和servletContext的属性(既getRequest,getResponse,getSession,getOut,getServletContext方法)
例如:
${pageContext.session.id}

2.param以及paramValues
允许访问请求的参数值(param)或者请求参数值的数组
${param.name}
如果没有返回空字符串

3.header以及headerValues
访问报头。记住,某些变量名不能使用点号记法
${header.Accept} ${header["Accept"]}
${header["Accept-Encoding"]} //不能用.

4.cookie
cookie返回的是Cookie对象,需要调用getValue方法访问value属性
${cookie.userCookie.value}
${header["userCookie"].value}

5.initParam
允许访问上下文初始化参数(context,initialization)
${initParam.defaultColor}

6.pageScope,requestScope,sessionScope,applicationScope
限制访问属性名的作用域变量
${requestScope.name} 表示只能访问在HttpServletRequest中的name

(5)一组为数不多的但有效的简单计算
在EL表达式内部可以用算数,关系,逻辑或者空值检查
1. + - * /和div %和mod
2.==和eq !=和ne
3.<lt >和gt <=和le >=和ge 类型转换的执行==和!=,如果参数是字符串,则进行字面比较
4.&& and or !和not
5.空运算符 empty 空返回true

(6)条件输出 ${test? option1:option2}

(7)自动类型转换

(8)空值代替错误消息
大多数情况下,没有相应的值或NullPointerExceptions异常都会导致空字符串而不会抛出异常

posted on 2017-04-28 17:24  zhd_七  阅读(262)  评论(0编辑  收藏  举报