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>
-
创建Java类
:创建名为
StockServer的Java类,包含一个以股票代码为参数的方法,用于计算指定股票的价格报价,代码可参考相关示例,无需实现Remote接口。 -
引入Java类并显示信息
:使用所需的JSP标签将
StockServer类引入StockQuote.jsp,通过调用getQuote()方法显示价格报价,并调用getNasdaqSymbols()显示所有可用股票代码列表。 -
添加HTML表单
:在
StockQuote.jsp中添加HTML<form>标签,包含一个文本输入字段和一个提交按钮,让用户输入股票代码并请求价格报价。 -
运行和测试
:在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
文件,其设置将覆盖注解值。
-
使用模板创建JSF网站
:
-
创建模板文件
:在Eclipse中选择
File➤New➤XHTML page,接受默认位置(WebContent目录),输入StudentTemplate作为文件名,点击Next,选择New Facelet Template,将创建一个包含头部、内容和页脚三个部分的基本网页模板,示例如下:
-
创建模板文件
:在Eclipse中选择
<!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应用。
超级会员免费看
96

被折叠的 条评论
为什么被折叠?



