- 浏览: 262025 次
- 性别:
- 来自: 多伦多
文章分类
- 全部博客 (127)
- Java 基础 (46)
- Java EE (3)
- Clouds (1)
- Spring 编程 (7)
- Spring Batch 编程 (1)
- Quartz 编程 (9)
- Seam 编程 (4)
- Hibernate 编程 (1)
- JSF 编程 (3)
- jQuery 编程 (3)
- Interview Question 汇总 (3)
- 日常应用 (3)
- Maven 编程 (2)
- WebService 编程 (10)
- Scala 编程 (5)
- Coherence 编程 (8)
- OO 编程 (1)
- Java 线程 (6)
- DB 编程 (2)
- WebService 安全 (4)
- Oracle Fusion 编程 (2)
- JavsScript/Ajax 编程 (1)
最新评论
-
chainal:
赞,说的很好
Scala 有趣的Trait -
wuliupo:
RRRR-MM-DD HH24:MI:SS
如何让Oracle SQL Developer显示的包含在日期字段中的时间 -
pengain:
...
使用Spring Roo ,感受ROR式的开发 -
zeng1990:
def getPersonInfo() = {
(&quo ...
Java 的继位人? - Scala简介 -
zeng1990:
我使用的是2.9.2版本的!
Java 的继位人? - Scala简介
(转自: http://www.ibm.com/developerworks/cn/java/j-jsf2fu1/ )
2009 年 6 月 15 日 有关 Web 应用程序框架的最佳发源地,人们一直争论不休:是象牙塔(由理论家空想而来)还是现实世界。在后一种情况下,框架的诞生经受了实际需求的严酷考验。凭直觉判断,经受了实际需求的考验要胜过理论家的空想,并且我认为这种直觉完全经得起更进一步的检验。 JSF 1 就是在象牙塔中开发的,因此,它的出现并没有引起太大的轰动。但是,JSF 做对了一件事情 — 它使市场上出现了大量来自实际开发的创新。早些时候,Facelets 的初次登场成为了 JavaServer Pages (JSP) 的强有力候补。然后出现了 Rich Faces,一个出色的 JSF Ajax 库;接着是 ICEFaces,将 Ajax 和 JSF 联合起来的新颖方法;还有 Seam、Spring Faces、Woodstock 组件、JSF Templating,等等。所有这些开源 JSF 项目都是由开发人员根据自己需要的功能构建的。 JSF 2.0 专家组实际上对来自这些开源项目的最佳特性进行了标准化。尽管 JSF 2 规范确实是由一些理论家编写的,但它也受到了来自实际开发的创新的驱动。回想起来,专家组的工作其实非常轻松,因为我们正站在巨人的肩膀上,比如 Gavin King (Seam)、Alexandr Smirnov (Rich Faces)、Ted Goddard (ICEFaces) 和 Ken Paulson (JSF Templating)。实际上,所有这些巨人都是 JSF 2 专家组的成员。因此,JSF 2 在许多方面都结合了象牙塔和真实世界的长处。并且它展示了这一点。JSF 2 是对 JSF 1 的重大改进。 本文是共三部分的系列文章的开篇,主要有两个目标:展示激动人心的 JSF 2 新特性,展示如何最佳地利用这些特性,这样您就能够利用 JSF 2 提供的功能。通过演示 JSF 2 的应用并伴随一些最佳使用技巧,我将阐述前面两个问题。下面是本文将要介绍的技巧: 但是,我将首先介绍贯穿整个系列文章的示例应用程序。本文的应用程序源代码可以
下载
获得。 图 1 展示了一个 JSF mashup — 我将它称为 places 应用程序 — 它使用 Yahoo! Web 服务将地址转换为地图,并显示缩放级别和天气预报: 要创建一个地点,需要填写地址表单,激活 Go 按钮,然后应用程序将把地址发送给两个 Web 服务:Yahoo! Maps 和 Yahoo! Weather。 Map 服务在 Yahoo! 服务器上返回指向地址映射的 11 个地图 URL,使用不同的缩放级别。Weather 服务返回一些预先组装的 HTML。图像 URL 和 HTML 内容都轻松地显示在一个 JSF 视图中,这要分别感谢
places 应用程序使您能够输入任意数量的地址。您甚至可以多次使用同一个地址 ,如图 2 所示,它实际上演示了缩放级别: places 应用程序有 4 个托管 bean(managed bean),如
表 1
所示: 要运行 places 应用程序,需要访问developer.yahoo.com/maps/ajax
,从 Yahoo! 获得一个应用程序 ID,这样才能使用 Yahoo! Web 服务。单击 Yahoo! Maps Web Service 中的Get an App ID
按钮。得到 ID 后,在
应用程序在会话范围内存储了一组
创建地点非常简单。清单 1 显示了
图 1
中的视图所含的地址表单的代码: 当用户激活 Go 按钮并提交表单后,JSF 将调用按钮的操作方法: 清单 2 展示了
注意
清单 3
中的代码使用 Facelets
zoom 菜单(参见
图 3
和
清单 3
)有一个
如果曾经使用过 JSF 1,那么很可能会注意到本文的 JSF 2 代码中存在一些细微的差别。首先,我使用了 JSF 2 的新的显示技术 — Facelets — 而不是 JSP。您将从本系列后续文章中看到,Facelets 提供了许多强大的特性来帮助您实现健壮、灵活和可扩展的用户界面。但是在前面的代码清单中,我并没有过多利用这种功能。然而,Facelets 为 JSF 带来的众多微小改进之一便是能够将 JSF 值表达式直接放入到 XHTML 页面;例如,在
清单 1
中,我将
从 Facelets 角度来讲,还需要注意
清单 3
中的
目前为止,前面的代码并没有使用 Facelets,与 JSF 1 相比没有出现显著的变化。现在,我将展示更加大的差异。第一个比较大的差异体现在将要为 JSF 2 应用程序编写的 XML 配置的数量方面。 Web 应用程序的 XML 配置始终是个麻烦问题 — 它非常冗长并且容易出现错误,因此最好将 XML 配置委托给一个框架,比如通过注释、约定或特定于领域的语言。作为开发人员,我们应该能够集中精力实现一些操作,而不是将浪费时间在冗长的 XML 方面。 作为一个典型的例子,清单 6 展示了在使用 JSF 1 的情况下,在 places 应用程序中声明托管 bean 所需的 20 行 XML 代码: 对于 JSF 2,XML 消失了,您将对类使用注释,如清单 7 所示: 按照约定,托管 bean 的名称与类名相同,类名的第一个字母被转换为小写。例如,清单 7
中创建的托管,从上到小依次为: 在
清单 7
中,我对
也可以使用
以托管 bean 的形式注册一个类实例,然后将其放入到使用其中一个
注释必须结合使用一个实现零参数构造器的 Java 类。 为托管 bean 设置一个属性。注释必须放在类成员变量的声明之前。 在定制范围内存储托管 bean。 定制范围就是指可以由页面创建者访问的地图。可以通过编程的方式控制定制范围内的 bean 的可视性和生命周期。 从 faces-config.xml 中移除托管 bean 声明将极大地减少 XML,但是在 JSF 2 中,通过使用注释(如我对托管 bean 所做的一样)或是约定(比如 JSF 2 的简化的导航处理),几乎可以去掉所有的 XML 内容。 在 JSF 1 中,导航使用 XML 指定。比如,要从 login.xhtml 转到 places.xhtml,可能使用清单 8 所示的导航规则: 要去除
清单 8
中的 XML,可以利用 JSF 2 的导航约定:JSF 将 .xhtml 添加到按钮操作的末尾并加载该文件。这意味着不需要使用注释或其他内容,只需要使用约定就可以完整地避免编写导航规则的需求。在清单 9 在,按钮的操作是
对于
清单 9
来说,不需要任何导航 XML。清单 9 中的按钮加载 places.xhtml,但是前提是该文件和按钮所在的文件处于同一个目录中。如果操作并没有以斜杠( 当用户激活
清单 10
中的按钮时,JSF 将加载 /pages/places.xhtml 文件。 默认情况下,JSF 将从一个 XHTML 页面转至另一个 XHTML 页面,但是通过指定
Java 技术的最大优势并不是 Java 语言,而是 Java 虚拟机(JVM)。在 JVM 上运行着强大、新颖和创新的语言,比如 Scala、JRuby 和 Groovy,这使您在编写代码时拥有了更多选择。Groovy 这个名字有些奇怪,但是功能非常强大,融合了 Ruby、Smalltalk 和 Java 语言,它是这些语言中最为流行的一种语言(参见
参考资料
)。 使用 Groovy 的理由有很多。首先,它要比 Java 语言更加简洁、功能更加强大。还有两个原因:不使用分号,不需要强制转换(casting)。 您可能还没有注意到,在
清单 2
中, 可以将 Groovy 用于任何使用 Java 代码编写的 JSF 工件 — 例如,组件、呈现器、验证器和转换器。事实上,这对于 JSF 2 来说并不新鲜 — 因为 Groovy 源文件编译为 Java 字节码,您只需使用 Groovy 生成的 .class 文件,就好象它们是由
JSF 2 提供了定义和访问资源的标准机制。您将自己的资源放到名为 resources 的顶级目录下,并使用一些 JSF 2 标记来在视图中访问这些资源。例如,图 4 展示了 places 应用程序的资源: 对资源的惟一需求是它必须位于 resources 目录或 resources 目录的子目录中。可以随意命名 resources 目录的子目录。 在您的视图代码中,可以使用两个 JSF 2 标记访问资源: 开发人员需要能够在页面中指定想要呈现他们的资源的位置。例如,如果将 JavaScript 放在页面体中,浏览器将在加载页面时执行 JavaScript。另一方面,如果将 JavaScript 放到页面的头部,那么 JavaScript 只有在得到调用时才会被执行。由于资源的放置位置会影响它的使用方式,因此需要能够指定希望在哪些位置显示资源。 JSF 2 资源是可重新定位的
,这意味着您可以在页面中指定希望放置资源的位置。您将使用
有些情况下,需要使用 JSF 表达式语言(EL)访问资源。比如,清单 13 展示了如何使用
无可否认,清单 13 中的语法不是很直观。它访问了一个 JSF 为了存储资源而创建的地图,因此很少需要使用这种语法。实际上,可以使用 在 EL 表达式内访问资源的语法是
随着 2.0 版本的发布,Java™Server Faces (JSF) 现在可以轻松地实现健壮的、Ajax 风格的 Web 应用程序。本文是共三部分的系列文章的开篇,JSF 2.0 专家组成员 David Geary 将展示如何利用 JSF 2 中的新特性。在这期文章中,您将了解到如何使用 JSF 2 流线化开发,您将使用注释和约定代替 XML 配置,简化导航,并轻松访问资源。并且您将看到如何在您的 JSF 应用程序中使用 Groovy。
图 1. 从 Yahoo! Web Services 中查看地图和天气信息
<h:graphicImage>
和
<h:outputText>
。
图 2. 缩放级别
表 1. places 应用程序中的托管 bean
托管 bean 名称
类
范围
mapService
com.clarity.MapService
应用程序
weatherService
com.clarity.WeatherService
应用程序
places
com.clarity.Places
会话
place
com.clarity.Place
请求
运行 places 应用程序
MapService.java
和WeatherService.java
中用您的 ID 替换
YOUR_ID_HERE
。Place
,如
图 1
所示,并在请求范围内维护了一个
Place
。应用程序还分别使用应用程序范围内的
mapService
和
weatherService
托管 beans 为 Yahoo! 的 map 和 weather Web 服务提供了简单的 API。
<h:form>
<h:panelGrid columns="2">
#{msgs.streetAddress} <h:inputText value="#{place
.streetAddress}" size="15"/>
#{msgs.city} <h:inputText value="#{place
.city}" size="10"/>
#{msgs.state} <h:inputText value="#{place
.state}" size="2"/>
#{msgs.zip} <h:inputText value="#{place
.zip}" size="5"/>
<h:commandButton
value="#{msgs.goButtonText}"
style="font-family:Palatino;font-style:italic"
action="#{place.fetch}"
/>
</h:panelGrid>
</h:form>
place.fetch()
。该方法将信息从 Web 服务发送到
Place.addPlace()
,后者创建一个新的
Place
实例,使用传递给方法的数据初始化实例,并将其存储在请求范围内。Place.fetch()
:
清单 2.
Place.fetch()
方法
public class Place {
...
private String[] mapUrls
private String weather
...
public String fetch() {
FacesContext fc = FacesContext.getCurrentInstance()
ELResolver elResolver = fc.getApplication().getELResolver()
// Get maps
MapService ms = elResolver.getValue(
fc.getELContext(), null, "mapService")
mapUrls = ms.getMap(streetAddress, city, state)
// Get weather
WeatherService ws = elResolver.getValue(
fc.getELContext(), null, "weatherService")
weather = ws.getWeatherForZip(zip, true)
// Get places
Places places = elResolver.getValue(
fc.getELContext(), null, "places")
// Add new place to places
places.addPlace(streetAddress, city, state, mapUrls, weather)
return null
}
}
Place.fetch()
使用 JSF 的变量分解器(resolver)查找
mapService
和
weatherService
托管 bean,并且使用这些托管 bean 从 Yahoo! Web 服务获得地图和天气信息。随后
fetch()
调用places.addPlace()
,后者使用地图和天气信息以及地址,在请求范围内创建一个新的
Place
。fetch()
返回
null
。由于
fetch()
是一个与按钮有关的操作方法,null
返回值使得 JSF 重新加载同一个视图,其中显示用户会话中的所有位置,如清单 3 所示:
清单 3. 在视图中显示位置
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:form>
<!-- Iterate over the list of places
-->
<ui:repeat value="#{places.placesList
}" var="place
">
<div class="placeHeading">
<h:panelGrid columns="1">
<!-- Address at the top
-->
<h:panelGroup>
<div style="padding-left: 5px;">
<i><h:outputText value="#{place.streetAddress
}"/></i>,
<h:outputText value="#{place.city
}"/>
<h:outputText value="#{place.state
}"/>
<hr/>
</div>
</h:panelGroup>
<!-- zoom level prompt and drop down
-->
<h:panelGrid columns="2">
<!-- prompt
-->
<div style="padding-right: 10px;margin-bottom: 10px;font-size:14px">
#{msgs.zoomPrompt}
</div>
<!-- dropdown
-->
<h:selectOneMenu onchange="submit()
"
value="#{place.zoomIndex
}"
valueChangeListener="#{place.zoomChanged
}"
style="font-size:13px;font-family:Palatino">
<f:selectItems value="#{places.zoomLevelItems}"/>
</h:selectOneMenu>
</h:panelGrid>
<!-- The map
-->
<h:graphicImage url="#{place.mapUrl
}" style="border: thin solid gray"/>
</h:panelGrid>
<!-- The weather
-->
<div class="placeMap">
<div style="margin-top: 10px;width:250px;">
<h:outputText style="font-size: 12px;"
value="#{place.weather
}"
escape="false"/>
</div>
</div>
</div>
</ui:repeat>
</h:form>
</ui:composition>
<ui:repeat>
标记迭代用户会话中存储的位置列表。对于每个位置,输出应当如图 3 所示:
图 3. 视图中显示的位置
onchange="submit()"
属性,因此当用户选择某个缩放级别时,JavaScript
submit()
函数提交菜单的环绕(surrounding)表单。提交表单后,JSF 调用菜单的相关值修改侦听器 —
Place.zoomChanged()
方法,如清单 4 所示:
清单 4.
Place.zoomChanged()
public void zoomChanged(ValueChangeEvent e) {
String value = e.getComponent().getValue()
zoomIndex
= (new Integer(value)).intValue()
}
Place.zoomChanged()
在一个名为
zoomIndex
的
Place
类的成员变量中存储缩放级别。由于导航不会受到与服务器通信的影响,JSF 将重新加载页面,并且地图使用新的缩放级别进行更新,如下所示:<h:graphicImage url="#{place.mapUrl}
..."/>
。当绘制地图时,JSF 调用
Place.getMapUrl()
,它返回当前缩放级别下的地图 URL,如清单 5 所示:
清单 5.
Place.getMapUrl()
public String getMapUrl() {
return mapUrls == null ? "" : mapUrls[zoomIndex
]
}
#{msgs.city}
等表达式直接放入页面中。如果使用 JSF 1,则必须将表达式封装到
<h:outputText>
中,例如
<h:outputText value="#{msgs.city}"/>
。但要注意,出于安全考虑,必须始终将来自用户输入的文本进行转义,例如,在
清单 3
中我使用了
<h:outputText>
,它在默认情况下转义其文本来显示位置信息。<ui:composition>
标记。该标记指定清单 3 中的 XHTML 页面将被包含到其他 XHTML 页面中。Facelets composition 是 Facelets
templating
的中心组件,类似于流行的 Apache Tiles 框架。在本文的后续文章中,我将讨论 Facelets 模板并展示如何根据
Composed Method
Smalltalk 模式构建您的视图。
回页首
清单 6. JSF 1 的托管 bean 声明
<managed-bean>
<managed-bean-class>com.clarity.MapService</managed-bean-class>
<managed-bean-name>mapService</managed-bean-name>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-class>com.clarity.WeatherService</managed-bean-class>
<managed-bean-name>weatherService</managed-bean-name>
<managed-bean-scope>application</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-class>com.clarity.Places</managed-bean-class>
<managed-bean-name>places</managed-bean-name>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
<managed-bean>
<managed-bean-class>com.clarity.Place</managed-bean-class>
<managed-bean-name>place</managed-bean-name>
<managed-bean-scope>request</managed-bean-scope>
</managed-bean>
清单 7. JSF 2 的托管 bean 注释
@ManagedBean(eager=true)
public class MapService {
...
}
@ManagedBean(eager=true)
public class WeatherService {
...
}
@ManagedBean()
@SessionScoped
public class Places {
...
}
@ManagedBean()
@RequestScoped
public class Place {
...
}
mapService
、weatherService
、places
和
place
。也可以使用ManagedBean
注释的
name
属性显式地指定一个托管 bean,比如:@ManagedBean(name = "place")
。mapService
和
webService
托管 bean 使用
eager
属性。当
eager
属性为
true
时,JSF 将在启动时创建托管 bean 并将其放入应用程序范围。@ManagedProperty
注释设置托管 bean 属性。表 2
展示了 JSF 2 托管 bean 注释的完整列表:
表 2. JSF 2 托管 bean 注释(@...Scoped
注释只对
@ManagedBean
有效)
托管 bean 注释
描述
属性
@ManagedBean
@...Scoped
注释指定的范围内。如果没有指定任何范围,JSF 将把此 bean 放入请求范围,如果没有指定任何名称,JSF 将把类名的第一个字母转换为小写,形成一个托管 bean 名称;例如,如果类名为
UserBean
,那么 JSF 将创建一个托管 bean,其名为
userBean
。eager
和
name
属性都是可选的。
eager
,name
@ManagedProperty
name
属性指定特性的名称,默认情况下为成员变量的名称。value
属性是特性的值,可以是一个字符串,也可以是一个 JSF 表达式,比如
#{...}
。
value
,name
@ApplicationScoped
在应用程序范围内存储托管 bean。
@SessionScoped
在会话范围内存储托管 bean。
@RequestScoped
在请求范围内存储托管 bean。
@ViewScoped
在视图范围内存储托管 bean。
@NoneScoped
将托管 bean 指定为没有范围。无范围的托管 bean 在被其他 bean 引用时比较有用。
@CustomScoped
value
属性指向一个地图。
value
回页首
清单 8. JSF 1 中的导航配置规则和用例
<navigation-rule>
<navigation-case>
<from-view-id>/pages/login.xhtml</from-view-id>
<outcome>places</outcome>
<to-view-id>/pages/places.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
places
,因此 JSF 加载 places.xhtml:
清单 9. 通过约定进行导航
<h:commandButton id="loginButton"
value="#{msgs.loginButtonText}"
action="places
"/>
/
)开头,那么 JSF 认为这是一个相对路径。如果需要更加明确一点,可以指定一个绝对路径,如清单 10 所示:
清单 10. 使用绝对路径的导航
<h:commandButton id="loginButton"
value="#{msgs.loginButtonText}"
action="/pages/places
"/>
faces-redirect
参数可以重定向,如清单 11 所示:
清单 11. 通过重定向进行导航
<h:commandButton id="loginButton"
value="#{msgs.loginButtonText}"
action="places?faces-redirect=true
"/>
回页首
Place
类是使用 Groovy 编写的。这一点可以通过代码中没有使用分号看出来,但是注意下面这行代码:MapService ms = elResolver.getValue(...)
。对于 Java 代码,我必须强制转换
ElResolver.getValue()
的结果,因为该方法返回类型
Object
。Groovy 可以为我自动完成转换。javac
生成的一样。当然,Groovy 生成的 .class 文件可以正常工作后,需要了解如何热部署 Groovy 源代码,并且对于 Eclipse 用户,答案非常简单:下载并安装 Groovy Eclipse 插件(参见
参考资料
)。Mojarra 是 Sun 的 JSF 实现,从版本 1.2_09 之后提供了对 Groovy 的明确支持(参见
参考资料
)。
回页首
图 4. places 应用程序的资源
<h:outputScript>
和
<h:outputStylesheet>
。这些标记可以结合用于 JSF 2 的
<h:head>
和
<h:body>
标记,如清单 12 所示:
清单 12. 在 XHTML 中访问资源
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html">
<h:head
>
...
</h:head
>
<h:body
>
<h:outputStylesheet
library="css" name="styles.css" target="body"/>
<h:outputScript
library="javascript" name="util.js" target="head"/>
...
</h:body
>
</html>
<h:outputScript>
和
<h:outputStylesheet>
标记有两个属性,分别指定了脚本或样式表:library
和
name
。library
名称对应于 resources 目录下的子目录,这是保存资源的位置。例如,如果在 resources/css/en 目录中有一个样式表,那么
library
将为
css/en
。name
属性是资源本身的名称。target
属性指定位置;比如,在
清单 12
中,我将 CSS 放到页面体中,而将 JavaScript 放到页面头部中。<h:graphicImage>
访问一个图像:
清单 13. 使用 JSF 表达式语言访问资源
<h:graphicImage value="#{resource['images:cloudy.gif']
}"/>
清单 13 的非 EL 备选方法
<h:graphicImage/>
访问图像,而不需要使用 EL,比如:<h:graphicImage library="images" name="cloudy.gif"/>
resource['LIBRARY
:NAME
']
,其中
LIBRARY
和
NAME
对应于
<h:outputScript>
和
<h:outputStylesheet>
标记的
library
和<span
发表评论
相关推荐
JSF是一个基于组件的、事件驱动的Web应用框架,它由Sun Microsystems(现已被Oracle收购)提出,并被标准化为JSR 127规范。JSF的目标是提供一种简洁而强大的方式来构建用户界面,同时保持良好的可维护性和可扩展性。...
- **编程模型:**JSF使用声明式编程,Struts则更偏向于程序化的控制流。 - **灵活性:**Struts的配置文件更加灵活,而JSF则通过组件库提供更简单的UI创建方式。 - **生态支持:**两者都有丰富的社区和第三方库,但...
JavaServer Faces (JSF) 和 Apache Struts 是两种流行的Java Web开发框架,它们都有各自的优点和缺点。在选择使用哪种框架时,开发者需要考虑项目的特定需求、团队的技术背景以及对框架未来发展的预期。 JSF,作为...
1. **组件化编程:**Tapestry的核心思想之一就是组件化编程,这意味着开发者可以将Web页面分解为多个可复用的组件,每个组件都可以独立开发和维护。 2. **自动表单处理:**Tapestry框架提供了自动表单处理功能,可以...
Java EE 5 的主题是简化企业级应用开发的复杂度,而到了Java EE 6,这一理念得到了进一步深化。2009年底,Sun公司发布了Java EE 6 Final版,标志着Java EE技术的新里程碑。 #### Java EE 6 & JSR 316 Java EE 6 的...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
6. **Java Web开发**:Java在Web领域的应用广泛,如Servlet、JSP、JSF等技术用于构建服务器端应用,而Spring框架则提供了一个全面的企业级应用解决方案。 7. **Java EE**:Java企业版(Java Enterprise Edition,...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
凯撒加密解密程序 1个目标文件 1、程序结构化,用函数分别实现 2、对文件的加密,解密输出到文件 利用随机函数抽取幸运数字 简单 EJB的真实世界模型(源代码) 15个目标文件 摘要:Java源码,初学实例,基于EJB的真实...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...
Blister是一个用于操作苹果二进制PList文件格式的Java开源类库(可用于发送数据给iOS应用程序)。 重复文件检查工具 FindDup.tar FindDup 是一个简单易用的工具,用来检查计算机上重复的文件。 OpenID的Java客户端...