Servlet与JSP学习笔记(六) JSP进阶

系列写到这里也差不多可以收尾了,本文将是系列的最后一篇。主要的参考资料是《Tomcat与Java Web开发技术详解》和 菜鸟笔记。菜鸟笔记的问题在于,学完之后还是觉得什么都不会,因为没有人指导去做个项目,因而对真正的项目没有概念。而《Tomcat》则提供了一些项目的感觉。

没错,JSP已经不再流行了,但是想学习Java Web,JSP和Servlet的基本功的修行是必不可少的。何况,很多技术都是触类旁通的。我会继续加油的!

表达式语言EL

这个还是蛮简单的。阅读菜鸟笔记就可以。回想起来,第一遍看它,还觉得它跟WPF中的属性绑定很像(也许是“.”号的提醒)。但其实用点号表示属性还是比较普遍的。

自定义标签

自定义标签就是对JSP内置标签的扩展,可以让开发人员创建可重用的第三方标签,帮助处理复杂的逻辑和事物,让JSP代码更加简洁。

例如,下面是一些自定义标签的用法:



How are you. 

自定义标签是从JSP 1.1版本出现的,后来在JSP 2.0中又加入了简单标签。下面先来看看传统的自定义标签。

要让JSP容器理解自定义标签的含义,很显然需要定义一些约定和接口。通常会把一组功能相关的标签放在同一个标签库中。开发标签库的步骤如下:

  1. 创建自定义标签的处理类(Tag Handler),实现标签的具体功能。
  2. 创建TLD标签库描述文件,描述标签的用法等。
方法 描述
setPageContext() 由容器调用,传入当前的PageContext对象
setParent() 由容器调用,传入此标签的父标签的处理对象
getParent() 得到父标签的处理对象
doStartTag() 容器解析到标签的起始标志时调用
doEndTag() 容器解析到标签的结束标志时调用
release() 释放Tag资源时调用。

自定义标签处理类要继承Tag接口:

方法 描述
setPageContext() 由容器调用,传入当前的PageContext对象
setParent() 由容器调用,传入此标签的父标签的处理对象
getParent() 得到父标签的处理对象
doStartTag() 容器解析到标签的起始标志时调用
doEndTag() 容器解析到标签的结束标志时调用
release() 释放Tag资源时调用。

为了帮助编写Tag Handler,JSP还提供了TagSupportBodyTagSupport两个具体类,可以继承其中之一。

使用自定义标签时,需要把Tag Handler的class文件以及TLD文件拷到WEB-INF下,然后在web.xml中指明引入标签库:

  
    
      /mytaglib
      /WEB-INF/mytaglib.tld
    
  

在JSP中使用自定义标签前用<%@taglib>指令声明对标签库的生命。属性prefix指明前缀。

<%@page contentType="text/html; charset=GB2312" %>
<%@taglib uri="/mytaglib" prefix="mm" %>

greet
  
  
    
      Hi,${param.username} 

简单标签

传统自定义标签的编写还是太复杂了,因此JSP 2.0推出了简单标签(SimpleTag)。这个接口基本上只需要你实现doTag()方法来完成主要工作。更棒的是,还可以让你用采用JSP语法的标签文件制作标签,其原理和思想就像用JSP写Servlet一样。一个简单的greetings.tag示例:

<%@ tag pageEncoding="UTF8" %>
朋友们,大家好!

和编译JSP文件一样,容器也会编译标签文件,生成Tag Handler类。标签文件甚至也有隐含对象和指令,确实和JSP异曲同工。

标准标签库JSTL

既然可以随意自定义JSP标签,那往往会有一套官方标准库。一般标签库往往把所有文件打成JAR包,内含所有的class和TLD文件。对于官方标准库,只需要把JAR包放入WEB-INF/lib目录下,在JSP文件中使用时先用<%@ taglib>的uri属性指定具体的库就行了。如:

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

JSTL主要包括以下五个部分:

  1. 标签 描述
    用于在JSP中显示数据,就像<%= ... >
    用于保存数据
    与我们在一般程序中用的if一样
    基础迭代标签,接受多种集合类型
    Core标签库。包括常用的功能,以及条件、迭代等标签。如:
    标签 描述
    用于在JSP中显示数据,就像<%= ... >
    用于保存数据
    与我们在一般程序中用的if一样
    基础迭代标签,接受多种集合类型
  2. 格式标签库。用来格式化并输出文本、日期、时间、数字,提供国际化支持。
  3. SQL标签库。与数据库交互的标签。现在肯定没人用。
  4. XML标签库。操作XML文档。
  5. Functions标签库。包含一系列标准函数,大部分是通用的字符串处理函数。

设计网站模板

这里说的模板可不是后来出现的FreeMarker这样的模板引擎。这里说的是,同一个Web应用的页面往往需要保持外观上的统一的风格,因而可以定义统一的网页模板,不同的页面通过模板来动态生成。这里介绍的是利用自定义的JSP标签来实现。

假设对于一个bookstore应用,所有的网页都有如下结构:




    <!-- title -->



    
    


所有网页都有title、banner、body这三部分。可以创建一个template.jsp文件,当客户请求某个网页时,采用某种方法把这三个部分动态地填充进去,生成客户所需的网页。
因此就需要让所有的请求都被template.jsp文件处理。这里是使用一个DispatcherServlet类,接受所有的客户请求,然后把URL保存到request中,再转发给template.jsp。

Servlet与JSP学习笔记(六) JSP进阶_第1张图片
流程1

模板JSP文件的内容是这样的:


<%@ page contentType="text/html; charset=GB2312" %>
<%@ taglib uri="/mytaglib" prefix="mm" %>
<%@ page errorPage="errorpage.jsp" %>
<%@ page import="java.util.*" %>
<%@ include file="screendefinitions.jsp" %>



        <mm:insert definition="bookstore" parameter="title"/>


        
        


自定义的标签在其他自定义标签的帮助下,可以根据客户请求的具体URL,把对应的内容JSP文件包含进来。

Servlet与JSP学习笔记(六) JSP进阶_第2张图片
图片描述

以上就完成了主要功能。其实介绍这个项目是为后面的MVC话题做个铺垫。

引入MVC

MVC的概念和优点就不介绍了,直接进入主题。

JSP Model 1和JSP Model 2

早期的JSP页面把业务逻辑和控制网页流程的事情都干了,造成代码非常混乱。为了解决问题,SUN公司先后制定了两种设计模式,分别为JSP Model 1和JSP Model 2。

下图为Model 1. 它采用了JavaBean处理业务逻辑(Model),但JSP仍要干 View + Controller的活。只适应简单应用的需要。

Servlet与JSP学习笔记(六) JSP进阶_第3张图片
Model 1

Model 2模式则联合使用了JSP和Servlet,吸取了它们各自的优点,用JSP生成表示层的内容,让Servlet完成深层次的处理任务。在这里,Servlet充当控制器的角色,负责处理客户请求,创建JSP页面需要使用的JavaBean对象,并返回合适的JSP页面给客户。JSP页面没有流程控制的逻辑,只负责把由Servlet创建的JavaBean对象包含的数据作为动态内容插入到静态模板中。下面为结构图:

Servlet与JSP学习笔记(六) JSP进阶_第4张图片
Model 2

Struts框架

Struts是一个经典的Web MVC框架,是在JSP Model 2的基础上实现的。下面是其结构图:

Servlet与JSP学习笔记(六) JSP进阶_第5张图片
Struts结构

Struts框架是利用其核心过滤器FilterDispatcher来拦截所有的客户请求,然后映射到不同的Action模块中处理。Action类继承自Action接口,核心是用execute()方法来处理客户请求。为方便,可以继承Struts的实现类ActionSupport

Action类调用Model组件(JavaBean等)处理业务并返回结果,核心过滤器再根据映射配置转发到具体的视图(如JSP),视图页面生成响应内容返回给核心过滤器,后者再把响应发送到客户端。

Servlet与JSP学习笔记(六) JSP进阶_第6张图片
Struts流程

以上过程解释了如何根据请求定位到具体页面。可是如何用视图页面返回动态内容呢?也就是如何让JSP页面获得JavaBean的数据?
有两种方法。

  1. Struts提供的自定义标签。Struts 2甚至不需要你的Action类继承Action接口,只需要在类中定义一些属性和get/set方法,在JSP中使用Struts标签就能访问到。使用标签则能够访问struts资源文件中的属性。
  2. 在Action中访问Servlet API中的各种对象,就可以在对象中设置各种Attributes。通过ActionContext.getContext()可以得到HttpServletRequest的一个封装类。实现ServletContextAware、ServletRequestAware等接口则可以直接获得Servlet API的核心对象。

你可能感兴趣的:(Servlet与JSP学习笔记(六) JSP进阶)