31、Java Web开发:JSP、JSTL与JSF的深入探索

Java Web开发:JSP、JSTL与JSF的深入探索

1. JavaServer Pages(JSP)与自定义标签库

在JSP开发中,若标签需要参数,需在 .tld 文件中使用 <attribute> 标签指定。例如:

<tag>
  ...
  <attribute>
    <name>tradeDate</name>
    <required>false</required>
  </attribute>
</tag>

同时,在标签处理类中要为每个参数提供 setter 方法,其命名需遵循Java Bean的命名规范,示例如下:

public void setTradeDate(String tradeDate){
...
} 

应用开发者可创建自定义标签库以满足特定项目需求,第三方也能提供非标准的标签库,如Apache Taglibs项目(http://tomcat.apache.org/taglibs/)中的JSP标签库开源实现。

2. JSP标准标签库(JSTL)

JSP标准标签库(JSTL)是针对库组件的标准化规范,包含许多可在基于JSP的应用中复用的操作。标准JSTL确保任何符合Java EE的JSP容器都会包含并支持这些组件,共有五个JSTL库,涵盖迭代器、 if 语句、XML处理标签、执行SQL的标签、国际化标签以及常用函数。
标准化库有预定义的URL,例如使用 forEach 迭代器需指定以下URI: http://java.sun.com/jsp/jstl/core ,XML处理标签的URI为: http://java.sun.com/jsp/jstl/xml 。使用迭代器的代码片段示例如下:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<c:forEach var="item" items="${sessionScope.cart.items}">
    ...
</c:forEach>

若要学习JSTL和表达式语言编程,可参考Oracle教程:http://download.oracle.com/javaee/5/tutorial/doc/bnake.html。

3. 实践:使用JSP和Java Bean重写股票服务器应用

以下是具体操作步骤:
1. 创建JSP文件 :在Eclipse项目 Lesson28 中,选择 File➤New ,创建名为 StockQuote.jsp 的新JSP文件,Eclipse生成的文件如下:

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Insert title here</title>
  </head>
  <body>
  </body>
</html>
  1. 创建Java类 :创建名为 StockServer 的Java类,包含一个以股票代码为参数的方法,用于计算指定股票的价格报价,代码可参考相关示例,无需实现 Remote 接口。
  2. 引入Java类并显示信息 :使用所需的JSP标签将 StockServer 类引入 StockQuote.jsp ,通过调用 getQuote() 方法显示价格报价,并调用 getNasdaqSymbols() 显示所有可用股票代码列表。
  3. 添加HTML表单 :在 StockQuote.jsp 中添加HTML <form> 标签,包含一个文本输入字段和一个提交按钮,让用户输入股票代码并请求价格报价。
  4. 运行和测试 :在Eclipse中运行并测试 StockQuote.jsp
4. JavaServer Faces(JSF)开发Web应用

JSP规范是在Servlet之上创建的,旨在简化Web应用开发并实现网页设计师和开发者的职责分离,但JSP并未强制减少Java代码的使用。而JavaServer Faces(JSF)则能做到这一点,它是开发具有瘦客户端的Java EE Web应用的最佳方式。
当前的JSF 2.0版本基于最初为开源产品的Facelets框架,使用可扩展HTML( .xhtml 文件)创建JSF网页,这要求HTML格式良好,每个开放标签都有对应的闭合标签,标签属性值需用引号括起来,元素标签区分大小写,且文档必须有单个根标签。

与JSP相比,JSF具有以下重要优势:
| 优势 | 描述 |
| ---- | ---- |
| 自带UI组件 | JSF框架自带一套UI组件,而JSP使用标准HTML组件 |
| 事件驱动 | JSF是事件驱动的 |
| 代码分离 | 不能在 .xhtml 文件中添加Java代码,强制实现Java和HTML的代码分离 |
| 页面导航 | JSF提供简单的页面导航功能 |
| 可配置托管Bean | JSF引入可配置的托管Bean,包含处理逻辑和导航信息 |

以下是使用JSF开发学生注册应用的详细步骤:
1. 创建动态Web项目 :在Eclipse IDE中创建一个名为 Lesson29 的新动态Web项目。
2. 创建托管Bean :在 com.practicaljava.Lesson29.beans 文件夹中创建Java类 Student ,并在类名上方添加 @ManagedBean 注解,使用 Quick Fix 导入该注解类(来自 javax.faces.bean 包),同时添加 @RequestScoped 注解,确保容器为每个用户请求创建该Bean的新实例。代码如下:

package com.practicaljava.lesson29.beans;
import java.io.Serializable;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
@ManagedBean
@RequestScoped
public class Student implements Serializable{
      private long studentId;
      private String name;
       private int classId;

       public long getStudentId() {
            return studentId;
      }
      public void setStudentId(long studentId) {
            this.studentId = studentId;
      }
      public String getName() {
            return name;
      }
      public void setName(String name) {
            this.name = name;
      }
      public int getClassId() {
            return classId;
      }
      public void setClassId(int classId) {
            this.classId = classId;
      }
}

托管Bean的配置使用注解完成,无需额外的配置文件,但如果在 WEB-INF 目录中指定 faces-config.xml 文件,其设置将覆盖注解值。

  1. 使用模板创建JSF网站
    • 创建模板文件 :在Eclipse中选择 File➤New➤XHTML page ,接受默认位置( WebContent 目录),输入 StudentTemplate 作为文件名,点击 Next ,选择 New Facelet Template ,将创建一个包含头部、内容和页脚三个部分的基本网页模板,示例如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
  <title><ui:insert name="title">Student Portal</ui:insert></title>
</head>
<body>
<div id="header">
    <ui:insert name="header">
          <h1>Welcome to my Students Portal</h1>
    </ui:insert>
</div>
<div id="content">
  <ui:insert name="content">
          The content of my student portal goes here  </ui:insert>
</div>
<div id="footer">
  <ui:insert name="footer">
          <h1>The footer of my portal is here</h1>
  </ui:insert>
</div>
</body>
</html>

可在Eclipse中运行并测试该模板,也可在普通浏览器中输入URL(http://localhost:8080/Lesson29/StudentTemplate.xhtml)查看。
- 创建组合页面 :创建一个名为 EnrollStudent.xhtml 的新文件,选择 New Facelets Composition Page 。将 StudentTemplate.xhtml 添加到 template 属性,移除头部和页脚的 <ui:define> 标签以复用模板中的头部和页脚,示例如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="StudentTemplate.xhtml">
      <ui:define name="content">
          Add your content here or delete to use the default
      </ui:define>
</ui:composition>
</html>

在URL中添加 /faces 运行该页面,如:http://localhost:8080/Lesson29/faces/EnrollStudent.xhtml。
- 完善注册页面 :添加几个JSF标签( form inputText outputText commandButton ),将每个 inputText 标签的 value 属性绑定到 student Bean的相应字段,示例如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="StudentTemplate.xhtml">
 <ui:define name="content">
  <h:form>

    <h:outputText value="Student Name:"/>
    <h:inputText  value="#{student.name}" title="name" id="name" /> <br/>

    <h:outputText value="Student ID:"/>
    <h:inputText value="#{student.studentId}" title="id" id="studentId"/> <br/>

    <h:outputText value="Class ID:"/>
    <h:inputText  value="#{student.Id}" title="classId" id="classId" /> <br/>
    <h:commandButton action="enrolled" value="submit" />

  </h:form>          
 </ui:define>
</ui:composition>
</html>
5. JSF页面导航

EnrollStudent.xhtml 中的命令按钮有 action="enrolled" 属性,意味着表单处理后,Web应用将导航到另一个名为 Enrolled.xhtml 的JSP页面,示例如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="StudentTemplate.xhtml">
  <ui:define name="content">

   <h:outputText value="#{student.name}"/>, thank you for enrolling in class 
   <h:outputText value="#{student.classId}" />

  </ui:define>
</ui:composition>
</html>

此外, commandButton 按钮还可用于调用Bean上的方法,方法可返回包含下一个JSF页面名称的字符串,示例如下:

class Student{
...
  public String doSomething(){
       // Do something and navigate to the next page
      return "TheNextPage.xhtml";
  }
}

若要熟悉Facelets中的其他标签,可参考Java EE 6教程的第5章(http://download.oracle.com/javaee/6/tutorial/doc/giepx.html)。

综上所述,通过JSP、JSTL和JSF,开发者能够高效地开发出功能强大、结构清晰的Web应用。JSP和JSTL为基础开发提供了便利,而JSF则进一步提升了代码的可维护性和开发效率,尤其是在大型项目中,其优势更为明显。希望本文能帮助你更好地掌握这些技术,为你的Web开发之路助力。

Java Web开发:JSP、JSTL与JSF的深入探索

6. JSF托管Bean的深入理解

托管Bean在JSF开发中扮演着重要角色,它不仅可以存储数据,还能包含页面导航信息,由FacesServlet进行控制。以学生注册示例中的 Student 托管Bean为例,通过注解 @ManagedBean @RequestScoped 进行配置。

@ManagedBean 注解将 Student 类注册为JSF资源, @RequestScoped 注解确保容器为每个用户请求创建一个新的Bean实例。这种方式使得每个用户的请求都有独立的数据处理环境,避免数据混淆。

在实际应用中,托管Bean可以根据不同的作用域进行配置,常见的作用域还有 @SessionScoped (会话作用域)和 @ApplicationScoped (应用程序作用域)。不同的作用域适用于不同的场景:
- @RequestScoped :适用于每次请求都需要创建新实例的情况,如学生注册示例,每次用户提交注册请求时,都会创建一个新的 Student 实例。
- @SessionScoped :适用于在用户会话期间保持数据状态的情况,例如用户登录后,在整个会话期间都需要保存用户信息。
- @ApplicationScoped :适用于整个应用程序共享数据的情况,如应用程序的全局配置信息。

以下是不同作用域的使用示例:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.bean.ApplicationScoped;

// 会话作用域的托管Bean
@ManagedBean
@SessionScoped
public class UserSessionBean {
    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

// 应用程序作用域的托管Bean
@ManagedBean
@ApplicationScoped
public class AppConfigBean {
    private String appName;

    public String getAppName() {
        return appName;
    }

    public void setAppName(String appName) {
        this.appName = appName;
    }
}
7. JSF模板和组合页面的高级应用

在使用Facelets创建JSF网站时,模板和组合页面的设计可以更加灵活和高效。除了基本的头部、内容和页脚部分,还可以添加侧边栏等其他布局元素。

例如,在 StudentTemplate.xhtml 中添加侧边栏:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
          "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets">
<head>
  <title><ui:insert name="title">Student Portal</ui:insert></title>
</head>
<body>
<div id="sidebar">
    <ui:insert name="sidebar">
          Sidebar area. You can add navigation links here.
    </ui:insert>
</div>
<div id="header">
    <ui:insert name="header">
          <h1>Welcome to my Students Portal</h1>
    </ui:insert>
</div>
<div id="content">
  <ui:insert name="content">
          The content of my student portal goes here  </ui:insert>
</div>
<div id="footer">
  <ui:insert name="footer">
          <h1>The footer of my portal is here</h1>
  </ui:insert>
</div>
</body>
</html>

在组合页面中,可以根据需要对侧边栏进行定义或复用模板中的默认设置。以下是 EnrollStudent.xhtml 中添加侧边栏定义的示例:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="StudentTemplate.xhtml">
      <ui:define name="sidebar">
          <ul>
              <li><a href="#">Home</a></li>
              <li><a href="#">About</a></li>
              <li><a href="#">Contact</a></li>
          </ul>
      </ui:define>
      <ui:define name="content">
          <h:form>

            <h:outputText value="Student Name:"/>
            <h:inputText  value="#{student.name}" title="name" id="name" /> <br/>

            <h:outputText value="Student ID:"/>
            <h:inputText value="#{student.studentId}" title="id" id="studentId"/> <br/>

            <h:outputText value="Class ID:"/>
            <h:inputText  value="#{student.Id}" title="classId" id="classId" /> <br/>
            <h:commandButton action="enrolled" value="submit" />

          </h:form>          
      </ui:define>
</ui:composition>
</html>

通过这种方式,可以实现不同页面的个性化布局,同时复用模板中的公共部分,提高开发效率。

8. JSF页面导航的扩展应用

JSF的页面导航功能十分强大,除了简单的通过 commandButton action 属性进行导航外,还可以通过编程方式实现导航。

例如,在 Student 托管Bean中添加一个方法来实现页面导航:

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.faces.application.NavigationHandler;

@ManagedBean
@RequestScoped
public class Student {
    private long studentId;
    private String name;
    private int classId;

    public long getStudentId() {
        return studentId;
    }

    public void setStudentId(long studentId) {
        this.studentId = studentId;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getClassId() {
        return classId;
    }

    public void setClassId(int classId) {
        this.classId = classId;
    }

    public String navigateToEnrolled() {
        // 可以在这里添加更多的业务逻辑
        return "enrolled";
    }
}

EnrollStudent.xhtml 中调用该方法:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:ui="http://java.sun.com/jsf/facelets"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core">
<ui:composition template="StudentTemplate.xhtml">
 <ui:define name="content">
  <h:form>

    <h:outputText value="Student Name:"/>
    <h:inputText  value="#{student.name}" title="name" id="name" /> <br/>

    <h:outputText value="Student ID:"/>
    <h:inputText value="#{student.studentId}" title="id" id="studentId"/> <br/>

    <h:outputText value="Class ID:"/>
    <h:inputText  value="#{student.Id}" title="classId" id="classId" /> <br/>
    <h:commandButton action="#{student.navigateToEnrolled}" value="submit" />

  </h:form>          
 </ui:define>
</ui:composition>
</html>

此外,还可以通过配置 faces-config.xml 文件来实现更复杂的页面导航规则。以下是一个简单的 faces-config.xml 配置示例:

<faces-config xmlns="http://xmlns.jcp.org/xml/ns/javaee"
              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
              xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
                                  http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd"
              version="2.2">
    <navigation-rule>
        <from-view-id>/EnrollStudent.xhtml</from-view-id>
        <navigation-case>
            <from-outcome>enrolled</from-outcome>
            <to-view-id>/Enrolled.xhtml</to-view-id>
        </navigation-case>
    </navigation-rule>
</faces-config>

通过这种方式,可以根据不同的业务需求,灵活配置页面导航规则。

9. 总结与展望

在Java Web开发中,JSP、JSTL和JSF各有其独特的优势。JSP和JSTL为开发者提供了基本的Web开发功能,通过自定义标签库和标准标签库,可以快速搭建Web应用。而JSF则进一步提升了开发效率和代码可维护性,尤其是在大型项目中,其事件驱动、页面导航和代码分离等特性使得开发过程更加清晰和高效。

未来,随着Web技术的不断发展,JSF可能会与其他前端框架进行更深度的融合,以提供更好的用户体验。例如,结合Vue.js或React.js等前端框架,实现前后端分离的开发模式,进一步提升应用的性能和响应速度。

同时,随着云计算和微服务架构的兴起,JSF应用也可以更好地适应分布式环境,通过容器化技术(如Docker)和编排工具(如Kubernetes)实现应用的快速部署和弹性伸缩。

希望开发者能够深入掌握JSP、JSTL和JSF技术,不断探索其在不同场景下的应用,为Web开发领域带来更多的创新和突破。

技术 优势 适用场景
JSP 基于Servlet,可嵌入Java代码 快速开发小型Web应用
JSTL 提供标准标签库,可复用操作 简化JSP开发,提高代码复用性
JSF 强制代码分离,自带UI组件,事件驱动 开发大型、复杂的Java EE Web应用
graph LR
    A[用户请求] --> B[FacesServlet]
    B --> C[托管Bean]
    C --> D[处理业务逻辑]
    D --> E[页面导航]
    E --> F[返回响应页面]
    F --> A

通过以上的学习和实践,相信你已经对JSP、JSTL和JSF有了更深入的理解,能够在实际项目中灵活运用这些技术,开发出高质量的Web应用。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值