【我的2022下半年回顾-2】- Java EE - JSF简述
前言
2022过去了,迎来崭新的一年,在过去的半年里,我不仅在课内,还在课外通过各种方式了解和学习到了不少新的语言、框架、技术等等。平时急于产出和学习,没能好好的整理所学,遂在这个寒假,从这篇文章开始,以一系列文章作为对这段时间所学所作进行一个系统性回顾整理的过程,希望给自己查漏补缺,并能给一些正在或将要学习其中某些内容的朋友们一点启发。
JavaEE这个系列,将分别主要介绍 Java EE 8各方面的技术规范,并实战演练。
这篇文章,将简述JSF技术的基本概念,应用范围和使用方法。
导航
发文顺序从上到下,顺序大致按我接触它们的时间点排的,可能个别文章会提早或延后
- Springboot
- Java EE【√】
- Java EE 概览
- Java servlet
- JSF(Java Server Faces)【√】
- REST(Restful Web Services API)
- WebSocket
- Web Security
- Global Components and asynchronous
- EJB(Enterprise Java Bean)
- JPA(Java Persistence API)
- 网络安全框架 (Java)
- Spring Security
- Sa-Token
- Vue.js
- Web UI
- Mybatis
- Auto.js
- 浏览器3D引擎(轻量级): Three.js
- Uniapp / Unicloud 开发
- 微信小程序开发
- 前端深度学习引擎: Tensorflow.js
- 其他
- 利用Git管理源代码
- 利用maven管理java项目
- 利用npm管理项目
- Node.js配置和管理
- Sqlite: 内存中的轻数据库
- 软件过程和项目管理浅谈
- 打造自己的前端组件库
- 软件测试工具
- 文档撰写利器
正文
JSF 是什么
JSF(JavaServer Faces)是Java EE 中,一种基于组件库构建Web页面的规范,是服务器构建UI界面的MVC框架。
JSF 为Web提供了覆盖面较广的UI组件,并为其提供状态管理,同时还提供服务端验证、数据转换、页面导航、多种拓展机制等服务。
JSF 应用架构
- XHTML(页面)
- Java Class(Beans)
- 数据实体化
- 与UI通信渲染
- JSF CONFIG(如: faces-config.xml)
- 页面处理规则
- 导航
- 校验…
- 配置 Managed Beans
- 页面处理规则
JSF-MCV
JSF 生命周期
JSF应用程序的生命周期,从客户端对页面发出http请求开始,到服务器相应页面时结束,主要分为两个阶段:1.处理阶段;2.渲染阶段
- 处理阶段
第一次请求时,构建视图界面。在后续请求中,接收传值的参数,更新受托管的Beans,调用程序逻辑
- 渲染阶段
请求源页面收到来自服务器的响应,el组件根据其关联的托管Beans更新视图
JSF Bean
JSF 中托管的Bean,即Java实体类,或者是为实体类服务的实例类,必须包含基本的getter和setter,是UI组件的Model部分,如果你熟悉Vue和Spring,那JSF Bean类似于Vue data和spring Bean的结合体,xhtml页面调用Bean属性和方法,就好比Vue调用data里的对象。
-
JSF Bean 的生命周期 (和JSP Bean差不多)
只举几个主要的,还有@NoneScoped、@CustomScoped等等不常用的- @ViewScoped
页面范围内有效,当跳转到新的页面,Bean就失效了 - @RequestScoped
发送http请求到响应结束为止,每个请求都会创建独立的新示例 - @SessionScoped
Session(会话)范围内有效,当创建了一个session后一直Bean存在,直到session被invalidate终结 - @ApplicationScoped
Web应用程序结束运行前,Bean一直存在,并且可为应用内各个session会话共享 - @ConversationScoped
对话范围随着bean的存在而保持为日志 - @FlowScoped
Flow存在,Bean就会持续存在,Flow可以定义为一组包含页面(或视图)的页面
- @ViewScoped
-
如何托管JSF Bean
- XML配置Bean
创建faces-config.xml,按如下格式配置
<managed-bean> <managed-bean-name>user</managed-bean-name> <managed-bean-class>User</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean>
xml内配置Bean是比较老旧的办法了,选择我们通常直接采用注解托管Beans
-
注解配置Bean
- 首先创建一个Java实体类,比如 User.java,并为其写好样板代码
- 在 User类 的生命语句上方添加两个注解:@Named(value=“Bean名字”) 和 @XxxScoped,前者定义该Bean的名字,后者定义其生命周期。
- 注意:Bean的名称和属性不要有大写字母,不要用驼峰命名法,javax-el表达式将无法解析
示例代码:
@Named(value="user") // Using ManagedBean annotation @RequestScoped // Using Scope annotation public class User implements Serializable { private static final long serialVersionUID = 1L; // 通常是需要序列化的 private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
- XML配置Bean
xhtml 与 Bean 互联
这里直接进行项目示例
-
maven 创建一个java webapp项目
mvn archetype:generate -DarchetypeGroupId=io.openliberty.tools -DarchetypeArtifactId=liberty-archetype-webapp -DarchetypeVersion=3.6.1 -DgroupId=com.example -DartifactId=jsf_demo -Dversion=1.0-SNAPSHOT - DinteractiveMode=false
-
修改src下,liberty下的server.xml和webapp下web.xml以支持Javaee 8
-
server.xml 中 servlet feature 改 javaee-8
<featureManager> <feature>javaee-8.0</feature> </featureManager>
-
web.xml 中 servlet-api 改 javaee-api,并为jsf配置servlet(如果学过JSP,应该不陌生)
<dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>8.0</version> <scope>provided</scope> </dependency> <servlet> <servlet-name>Faces Servlet</servlet-name> <servlet-class>javax.faces.webapp.FacesServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.xhtml</url-pattern> </servlet-mapping>
-
java目录下创建一个JSF Bean,包含一个name属性
@Named(value="user") @ViewScoped public class User implements Serializable { private static final long serialVersionUID = 1L; private String name = “default name”; // ... // 省略的是构造函数和getter、setter }
-
webapp目录下创建一个 user.xhtml (名字随意,.xhtml结尾,.jsf好像也行,总之后缀要和web.xml中为 jsf 配置的servlet url pattern 要对应)
-
如果你是用IDE创建的.xhtml文件,并且是对jsf支持较友好的IDE(比如idea),那可以跳过这步,否则如果是直接创建文件的方式,引入普通html模板,需要再引入xhtml需要的一些tags和组件库/标记库,如
<?xml version="1.0" encoding="UTF-8"?> <!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:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core" > ```
-
在 user.xhtml 的标签中注入Bean
JSF 常用的html标记用法在网上很容易就可以找到,我就不在这里介绍了<h:outputText value="#{user.name}" />
-
mvn liberty:dev 运行,访问user.xhtml,你将在页面上看到,default name
-
假设,我们又创建了一个Bean叫userlist,里面已经存放了3个user,我们可以用 h:dataTable 渲染
<!-- 如果你熟悉Vue的elem Ui等UI库,var就好比迭代的item,value就好比绑定的数据源data --> <h:dataTable var="user" value="#{userlist}"> <h:column> <f:facet name="header">Name</f:facet> <h:outputText value="#{user.name}"/> </h:column> </h:dataTable>
-
注:建议采用Idea等对JSF支持较好的IDE编写xhtml代码,比如我输到 “user.” 的时候,只要你Bean的配置和代码没问题,它就能跳出来属性,否则不会提示,可以用来检查Bean有没有问题
-
JSF 核心标记 f:Core
上面给的是一个h标记的简单示例,接下来我们来看f标签
xhtml里面写js的script是不起效的,承担响应工作的 f 标签,常用于数据检验,数据转换和事件处理
这里简单介绍几个:
-
<f:convertNumber>
<h:inputText id="price" value="#{good.price}" size="20"> <!-- f 标签将h 标签输入的字符串转为数字,格式为货币,单位美元,小数位最小和最大数都为2 --> <!-- 如: 999,999.98 $ --> <f:convertNumber type="currency" currencySymbol="$" minFractionDigits="2" maxFractionDigits="2" /> </h:inputText>
-
<f:convertDateTime>
<h:outputText value="#{good.date}" > <!-- 将Bean good 的日期格式化为 dd-mm-yyyy 的形式 --> <f:convertDateTime pattern="dd-MM-yyyy" /> </h:outputText>
-
<f:validateLength>
<h:inputText id="uname" value="#{user.name}"> <!-- 注册用户名,要求5-10个字符 --> <f:validateLength minimum="5" maximum="10" /> <f:validateRequired /> </h:inputText>
-
<f:validateRegex>
<h:inputSecret id="password" value="#{user.password}"> <!-- 注册密码,要求6-16位,包含大小写字母和数字 --> <f:validateRegex pattern="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)[\S]{6,16}" /> <f:validateRequired /> </h:inputSecret>
-
<f:validateRequired />
代表必填,非空的验证更多具体的 f:Core 标记用法可以网上搜搜,w3c就很不错
UI 拓展 与 模块化
如果学过JSP,应该是知道这块的,就是自定义标签,写一个xhtml,注册到本地标记库和web.xml里,这里就不讲了,ui组件化绝大部分前端框架都有。
后记
JSF 相当于比较原始的 Java Web 前后端耦合状态下的通信服务,又承担了UI,在其基础上,有着thymeleaf等优秀的框架,而JSF是它们所遵守的标准。