以前servlet和JSP交互的代码

  • servlet代码示例:

  • JSP代码示例:

若属性不是一个String而是一个Bean呢?

  • 一个简单的JavaBean

  • servlet代码示例:

  • JSP代码示例:



    或者这么写:

JSP中不要出现脚本

  • 使用标准动作的JSP

  • 标准动作jsp:useBean详解



    scope默认是page作用域,那么在上述示例代码中可能出现问题:找不到person对象!

  • 标准动作jsp:getProperty详解

  • jsp:useBean还可以创建一个bean

    以下标准动作标记:



    会变成_jspService()方法中的以下代码:

  • jsp:setProperty可为上述生成的bean赋予属性值

  • 考虑更全面一些:jsp:useBean有条件地创建一个bean——useBean体

    如果找不到bean属性,那么才会创建一个bean:

Bean法则

普通的非企业JavaBean规范定义了一个类怎么才能算是JavaBean。这个规范很复杂,不过,结果JSP和servlet使用bean时,只需要知道以下规则:

  • 必须有一个无参数的公共构造函数
  • 必须按照命名约束来命名公共的获取方法和设置方法
  • 设置方法的参数类型和获取方法的返回类型必须一样
  • 性质名和类型是由获取方法和设置方法推导得出
  • 结合JSP使用时性质类型必须是String。(这一条可以通过scriptlet脚本或者EL表达式打破,见后续文档)

    也就是说,在标准动作useBean的class属性中引用的java对象,必须满足以上的Bean法则。

建立多态的bean引用



如上,使用Person类型,但是要建立一个Employee对象:

  • 为jsp:userBean增加type属性



    type:可以是class类型、抽象类型或者是一个接口。

    class:必须是type的一个子类或具体实现。

  • 若只用type,没有class



    这时要求必须在page作用域中存在person属性,否则会报出java.lang.InstantiationException异常。

    type vs class

    type==引用类型,即要声明的类型,可以是抽象类

    class==对象类型,即要实例化的类,必须是具体类

请求直接到JSP,而不经过servlet

既然jsp动作可以生成bean,那么可以不用通过servlet来new一个对象了,而直接到jsp页面中完成对象生成、赋值。

  • 以前用脚本的丑类做法

    表单如下:



    jsp中如下:



    或者这样:

  • 使用param属性,避免脚本

  • 若是让html和javaBean有一样的属性名字,那么param可以省略,property可以更清爽

    bean标记会自动转换基本类型:

    以上name类型是String,empID类型是int,bean标记会自动转换类型。

如果Bean性质不是Sring或者基本类型,比如有性质本身就是一个bean对象呢?

  • 使用丑类的脚本是可以的

  • EL来了——避免使用脚本

EL表达式

${person.name}

上述代码中,person没有声明就能使用,为什么?

在EL表达式中第一个命名变量可以是一个隐式对象(EL隐式对象不同于JSP也是对象)、也可以是一个属性。后文将详述EL隐式对象。

EL使用点号(.)操作符访问性质和映射值

访问性质:对JavaBean属性而言(bean有性质);

访问映射值:对Map等映射而言(Map有键);

  • 点号左边必须是一个映射或一个bean
  • 点号右边必须是一个映射键或一个bean性质
  • 点号右边必须遵循Java标识符的命名规则

EL使用中括号([])操作符,可访问更多

除了访问性质和映射值,还可以访问数组、List、非Java规范的属性名等

  • 中括号左边的变量有更多选择,如Map、bean,还可以是List或者数组
  • 如中括号里是一个String直接量(即引号引起来的串),这可以是一个Map键、bean性质、List或数组的索引
  • List或数组中的String索引会强制转换为int
  • 如中括号里不是String直接量,就会计算,而且可以嵌套表达式

EL隐式对象

  • EL中的请求参数

    若特定参数名只有一个参数值,那可以用param隐式对象;

    ${param.属性名}

    若给定参数名有多个参数值,就使用paramValues。

    ${paramValues.属性名[n]},n是索引

  • 从请求中获取信息

    EL的header隐式对象保证了所有首部的一个Map,如获取host:

    ${header["host"]}或者${header.host}

    这等同于脚本:

    <%= request.getHeader("host") %>

如果要获取HTTP请求方法呢?——使用pageContext来得到其他一切

使用脚本是这样的:

<%= request.getMethod() %>

但是不能这样使用EL隐式对象:${requestScope.method},这是不对的,requestScope不是request对象本身

而是需要这样:

${pageContext.request.method}

即pageContext有一个request性质,request有一个method性质。

  • 隐式作用域的作用

    既然requestScope不是request对象,获取不到request请中的参数,那么有什么作用?

    考虑这样的情况:

    request.setAttribute("foo.person",p);

    要获取“foo.person”属性,EL表达式就不能做到了,因为”foo.person”是一个完整的属性名.

    ${foo.person.name}根本不行,因为容器认为foo是某个作用域中的属性,但是永远找不到。

    隐式对象requestScope就可以发挥作用:

    ${requestScope["foo.person"].name}

  • 得到cookie更简单

    如要获得userName属性的cookie值,使用隐式对象cookie很方便:

    ${cookie.userName.value}

    相比使用脚本就要麻烦很多,因为request没有getCookie(cookieName)方法,只能如此:

  • 获取上下文参数,不要和servlet初始化参数混淆

    若在DD配置有参数mainEmail:



    使用EL表达式获取mainEmail:

    ${initParam.mainEmail}

EL函数:不仅仅取属性或性质,还可以调用Java方法

使用EL函数有如下步骤:

  1. 编写有一个公共静态方法的Java类,放在WEB-INF/classes某个目录下
  2. 编写一个标记库描述文件(Tag Library Descriptor, TLD),放在WEB-INF某个目录下
  3. 在JSP中放一个taglib指令
  4. 使用EL调用函数
  • 涉及到的文件的部署时这样的:

  • 简单的示例如下图:



    EL函数后文将详述。

模板复用——include指令

若希望每个JSP都显示某个页眉或页脚:

标准页眉文件Header.jsp:

  • 使用include指令

    Web应用中的一个JSP Contact.jsp:

  • 使用include标准动作

  • 看似代码、效果相似,但是原理并不同

    include指令在转换时发生,虽然只转换一次,但是生成的servlet类会大一些,发布产品时采用;

    include标准动作在运行时发生,虽每次都是最新的页眉内容,但每次请求都会有一点性能开销。

为使用include指令的JSP生成的servlet:



为使用include标准动作的JSP生成的servlet:

  • include指令是位置敏感的

    JSP中只有这个指令的位置会带来区别。如,如果使用page指令,可以把它放在页面的任何位置(安惯例是放在最前面);但是include指令不同,他要告诉容器到底把包含的文件的源代码插到哪里,如页眉插到开头、页脚插到结尾。

复用的部件去掉一些HTML标签

不要把开始和结束HTML和BODY标记放在可重用部件中!设计和编写布局模板部件时(如页眉、导航条等),要假设它们会包含在其他页面中。

  • 优化后的部件以及引用:

个性化的部件复用——jsp:param定制包含的内容

若希望页眉上有一个与上下文相关的子标题,它要依页面而定。

修改后的页眉Header.jspf:



而引用它的JSP页面只能用include标准动作,而不是include指令了(指令不是动态的调用):

页面跳转——jsp:forward标准动作

  • 有条件地转发的JSP(Hello.jsp),不过这里使用脚本了,这不太好

  • 请求转发到的目标JSP(HandleIt.jsp)



    为什么第一次请求没有打印出“Welcome to out page!”这句在跳转判断之前的文本呢?

    因为,利用jsp:forward标准动作,缓冲区会在转发之前清空,即转发前写到响应的所有内容都会清掉。

    若有好事者,在““Welcome to out page!”这句话后使用脚本强制输出:

    <% out.flush(); %>

    那么的确输出了,并出现IIlegalStateException异常,且不会有跳转发生。故千万不要先刷新输出再转发。

  • 去掉有条件转发中的脚本——JSTL标记



    后文详述JSP标准标记库。

要点

  • JSP表达式语言(EL)复习

  • bean相关的标准动作复习

  • 总复习

《Head First Servlets & JSP》-8-无脚本的JSP的更多相关文章

  1. JavaWeb chapter11 编写无脚本的JSP页面

    1.  JSP表达式语言EL 使用jsp:getProperty的property属性只能访问Bean的属性,不能访问嵌套的属性. JSP EL(表达式语言 Expression Language), ...

  2. HeadFirst jsp 08 无脚本JSP

    web页面设计人员真的必须懂 java ? web页面人员可以很快学习 EL 语言. 目前不知道 EL 应用前景如何, 但是我们香港系统没有使用 EL. include 指令 include指令告诉容 ...

  3. 【Head First Servlets and JSP】笔记21:从有脚本到无脚本

    可以建立多态的bean引用吗 使用type,但没有class scope属性默认为“page” 从有脚本到无脚本 1.快速搭建一个测试环境:输入用户名,返回“Hello, 用户名” index.htm ...

  4. 编写无Java脚本的JSP页面

    在上一章中总结了Web开发中应用MVC架构模式,将Servlet 用做控制器,JSP作为视图,JavaBean作为模型,实现业务流程控制,页面逻辑和业务逻辑的分离.然而,使用前面的技术实现MVC,并不 ...

  5. SpringMVC内容略多 有用 熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器、过滤器等Web组件以及MVC架构模式进行Java Web项目开发的经验。

    熟悉基于JSP和Servlet的Java Web开发,对Servlet和JSP的工作原理和生命周期有深入了解,熟练的使用JSTL和EL编写无脚本动态页面,有使用监听器.过滤器等Web组件以及MVC架构 ...

  6. 基于JQuery+JSP的无数据库无刷新多人在线聊天室

    JQuery是一款非常强大的javascript插件,本文就针对Ajax前台和JSP后台来实现一个无刷新的多人在线聊天室,该实现的数据全部存储在服务端内存里,没有用到数据库,本文会提供所有源程序,需要 ...

  7. 复习:JSP基本的语法(JSP凝视 + JSP指令 + JSP脚本元素 + JSP动作元素)

    JSP原理: 1.    对于每个请求.jsp容器都会创建一个新的线程来处理它: 2.    Servlet容器载入jsp后转换成的servlet(.class文件)是常驻内存的,所以对应速度一般比較 ...

  8. 下列哪个为JSP的小脚本的标签?(选择1项)

    下列哪个为JSP的小脚本的标签?(选择1项) A.<% %> B.<@ %> C.<%! %> D.<%– %> 解答:A

  9. 【Head First Servlets and JSP】笔记17:JSP所生成的servlet相关问题

    1.容器根据你所写的JSP生成一个类, /* * Generated by the Jasper component of Apache Tomcat * Version: Apache Tomcat ...

随机推荐

  1. 幸运数字(数位dp)

    个人心得:数位dp处理起来是真的麻烦,本来动态规划就够头疼的了,菜的一批. 来看这个题目吧,题目在下面. 把题目变成可以求得就是求前n个数中1-n*9的情况的总和,所以用dp[i][j],表示前i个数 ...

  2. 基于Python语言使用RabbitMQ消息队列(四)

    路由 在上一节我们构建了一个简单的日志系统.我们能够广播消息给很多接收者. 在本节我们将给它添加一些特性——我们让它只订阅所有消息的子集.例如,我们只把严重错误(critical error)导入到日 ...

  3. 【HTML5】Canvas绘制基础

    什么是 Canvas? HTML5 的 canvas 元素使用 JavaScript 在网页上绘制图像. 画布是一个矩形区域,您可以控制其每一像素. canvas 拥有多种绘制路径.矩形.圆形.字符以 ...

  4. C# 代码注释规范文档

    C# 提供一种机制,使程序员可以使用含有 XML 文本的特殊注释语法为他们的代码编写文档.在源代码文件中,具有某种格式的注释可用于指导某个工具根据这些注释和它们后面的源代码元素生成 XML.使用这类语 ...

  5. RequireJS 也可以引入 VUE

    RequireJS 也可以引入 VUE 由于 FastAdmin 是使用 RequireJS 导入 JS 模块的. 有人想把 VUE 也引入进去,虽然说也是可以,VUE 还是推荐使用 Webpack ...

  6. python基础准备

    老男孩python全栈学习day1 第一讲python基础: 1.python起源:python的创始人为吉多·范罗苏姆(Guido van Rossum).1989年的圣诞节期间,吉多·范罗苏姆(中 ...

  7. 把ASM下的HDD VM转换成ARM下Managed Disk的SSD VM

    在ASM下,要把HDD的VM转换成SSD的VM步骤非常复杂.需要手工把Disk从普通存储账户复制到高级存储账户.再通过这个Disk创建VM. 目前在有了ASM到ARM的迁移工具,以及Managed D ...

  8. laravel 导出导入excel和csv文件的 使用

    在项目中用到的常用功能数据导入导出 在laravel有插件可以直接使用 方便快捷 学习源头: https://www.cnblogs.com/martianShu/p/5869270.html htt ...

  9. 蓝桥杯 算法训练 ALGO-139 s01串

    算法训练 s01串 时间限制:1.0s 内存限制:256.0MB 问题描述  s01串初始为”0”  按以下方式变换  0变1,1变01 输入格式  1个整数(0~19) 输出格式  n次变换后s01 ...

  10. 【转】bootstrap模态框(modal)使用remote方法加载数据,只能加载一次的解决办法

    http://blog.csdn.net/coolcaosj/article/details/38369787 bootstrap的modal中,有一个remote选项,可以动态加载页面到modal- ...