高级 Java 编程综合指南
1. 受限属性与属性变更事件
在 Java 编程中,属性变更事件和受限属性是重要的概念。当一个属性发生变化时,我们可能需要通知相关的监听器。以下是一个展示属性变更事件处理的代码示例:
import java.beans.*;
public class DemoBean {
private int length = 10;
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
private VetoableChangeSupport vcs = new VetoableChangeSupport(this);
public int getLength() {
return length;
}
public void setLength(int l) throws PropertyVetoException {
int oldLength = length;
vcs.fireVetoableChange("length", oldLength, l);
length = l;
pcs.firePropertyChange("length", oldLength, l);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
public void addVetoableChangeListener(VetoableChangeListener listener) {
vcs.addVetoableChangeListener(listener);
}
public void removeVetoableChangeListener(VetoableChangeListener listener) {
vcs.removeVetoableChangeListener(listener);
}
}
上述代码中,
DemoBean
类包含了属性变更和受限属性的处理逻辑。
PropertyChangeSupport
用于处理普通的属性变更事件,而
VetoableChangeSupport
用于处理受限属性的变更。当调用
setLength
方法时,会先触发
fireVetoableChange
方法,若没有监听器否决该变更,才会更新属性值并触发普通的属性变更事件。
2. 通过 JSP 使用 Java Bean
在 JSP 页面中,我们可以使用
jsp:useBean
动作来加载 Java Bean。以下是使用该标签的基本语法:
<jsp:useBean id="name" class="package.Class" />
这个动作会实例化
class
属性指定的类的对象,并将其与
id
属性指定的名称绑定。例如,若要使用
beans
目录下的
CalculateBean.java
,可以这样写:
<jsp:useBean id="calc" class="beans.CalculateBean" >
这等价于以下脚本代码:
<% beans.CalculateBean calc = new beans.CalculateBean; %>
需要注意的是,所有类都应该属于某个包,这样才能在其他类中访问。创建 Bean 类时,要确保它属于某个包,编译后将其放置在
/WEB-INF/classes/beans/CalculateBean.class
路径下,然后就可以在 JSP 中引用它。
2.1 访问 Bean 属性
在 JSP 中,可以使用
jsp:getProperty
标签来访问 Bean 的属性。该标签有两个属性:
name
和
property
。
name
属性的值应与
jsp:useBean
的
id
属性相同,
property
属性的值应与 Bean 类中指定的实例变量匹配。例如,对于
CalculateBean
类的
name
属性,可以通过以下两种方式访问:
<jsp:getProperty name="calc" property="name" />
或者
<%= calc.getName() %>
2.2 设置 Bean 属性
可以使用
jsp:setProperty
标签来修改 Bean 的属性。该标签有三个属性:
name
(应与
jsp:useBean
中指定的
id
完全匹配)、
property
(要更改的属性名称)和
value
(属性的新值)。例如,若要更改
name
属性的值,可以这样做:
<jsp:setProperty name="calc" property="name" value="Peter" />
或者
<% calc.setName("Peter"); %>
当 Bean 的属性是数值类型,而传递的值是字符串时,JSP 容器可以自动处理类型转换。只需指定:
<jsp:useBean id = "calc" class = "beans.CalculateBean" />
<jsp:setProperty name = "calc" property = "*"/>
这种设置还可用于将 HTML 表单元素与 Java Bean 同步,减轻了重复编码的负担。
2.3 CalculateBean 示例
以下是一个完整的示例,展示了如何在 JSP 中使用 Java Bean:
JavaBeans.jsp
<Html>
<Head>
<title> Using Java Beans in JSP </title>
</Head>
<body>
Hello <br>
<jsp:useBean id="calc" class="beans.CalculateBean" >
After Instantiating Bean <br>
<jsp:setProperty name="calc" property="*" />
<jsp:setProperty name="calc" property="name" value="sachin" />
After Setting property: name <br>
<jsp:setProperty name="calc" property="var1" value="10" />
After Setting property: variable 1 <br>
<jsp:setProperty name="calc" property="var2" value="10" />
After Setting property: variable 2 <br>
Name: <jsp:getProperty name="calc" property="name" /><br>
Variable 1: <jsp:getProperty name="calc" property="var1" /><br>
Variable 2: <jsp:getProperty name="calc" property="var2" /><br>
<%= "Result: "+ calc.sum() %>
</jsp:useBean>
</body>
</Html>
CalculateBean.java
package beans;
import java.io.*;
public class CalculateBean implements Serializable {
private int var1;
private int var2;
private String name = new String();
public int getVar1() {
return var1;
}
public int getVar2() {
return var2;
}
public String getName() {
return name;
}
public void setName(String x) {
name = x;
}
public void setVar1(int x) {
var1 = x;
}
public void setVar2(int y) {
var2 = y;
}
public int sum() {
return var1 + var2;
}
}
这个示例中,
CalculateBean
类有两个整数变量
var1
和
var2
,以及一个字符串变量
name
。
sum
方法用于计算
var1
和
var2
的和。在 JSP 页面中,通过
jsp:useBean
实例化 Bean,使用
jsp:setProperty
设置属性值,使用
jsp:getProperty
访问属性值,并调用
sum
方法计算结果。
3. JAR 文件操作
JAR(Java Archive)文件类似于 ZIP 文件,Java 开发工具包(JDK)提供了
jar
工具来处理 JAR 文件。
3.1 创建 JAR 文件
创建 JAR 文件的基本命令如下:
jar -cvmf jar-file-name manifest-file-name input-file-names
各选项和参数的含义如下:
| 选项 | 含义 |
| ---- | ---- |
|
-c
| 创建 JAR 文件 |
|
-v
| 在标准输出上显示详细信息 |
|
-f
| 指定输出到文件而不是标准输出 |
|
-m
| 指定要添加到 JAR 中的清单文件 |
|
jar-file-name
| 生成的 JAR 文件的名称,扩展名为
.jar
|
|
input-file-names
| 要包含在 JAR 文件中的文件或目录,多个文件或目录用空格分隔 |
例如,创建
Calculator.jar
文件:
jar -cvfm Calculator.jar manifest.txt beans
3.2 查看 JAR 文件内容
使用以下命令查看 JAR 文件的内容:
jar -tf jar-file
其中,
-t
选项表示查看内容,
-f
选项指定要查看的 JAR 文件。
3.3 提取 JAR 文件内容
使用
-xf
命令提取 JAR 文件的内容:
jar -xf jar-file-name
-x
选项表示提取内容,
-f
选项指定要提取的 JAR 文件。提取的内容将被放置在当前目录下。
3.4 清单文件
清单文件(
.mf
)是一个特殊的文件,可以包含 JAR 文件中文件的相关信息。创建 JAR 文件时,如果没有提供清单文件,会自动创建一个默认的清单文件,路径为
META-INF/MANIFEST.MF
。默认清单文件包含以下内容:
Manifest-Version: 1.0
Created-By: 1.7.0_09 (Oracle Corporation)
若要修改清单文件,可以使用
-m
选项。首先创建一个包含要添加信息的文本文件,然后使用以下命令:
jar cfm jar-file manifest-file input-file(s)
需要注意的是,清单文件末尾要添加换行符,并且
-m
和
-f
选项及其参数的顺序必须匹配。
如果要指定 JAR 包中应用程序的入口类,可以在清单文件中添加以下头部信息:
Main-Class: classname
添加该清单文件后,可以使用以下命令运行 JAR 包中的应用程序:
java -jar JAR-name
另外,也可以使用
-e
选项来指定应用程序的入口点,而无需编辑或创建清单文件。例如:
jar cfe x.jar MyMain MyMain.class
如果入口类在某个包中,可以这样调用:
jar cfe x.jar App.MyMain App/MyMain.class
4. 远程方法调用(RMI)
远程方法调用(RMI)是 Java 实现的用于分布式计算的远程过程调用(RPC)机制。它基于客户端/服务器概念,允许运行在一个机器上的对象被运行在不同机器上的客户端访问。
4.1 RMI 网络模型
RMI 客户端/服务器应用程序基于 TCP/IP 网络模型。在 TCP/IP 中,应用层负责处理表示层和会话层的问题。RMI 为这些层提供了相应的功能,客户端和服务器的表示层功能分别由存根(Stub)和骨架(Skeleton)处理,远程引用层(RRL)负责管理客户端和服务器之间的会话。
4.2 存根和骨架
存根是客户端的代理类,骨架是服务器端的代理类,它们由特殊的编译器
rmic
生成。客户端与存根交互,存根将客户端的请求传递给服务器,骨架将服务器的响应传递给客户端。存根的主要功能包括:
- 编组参数和解组返回值
- 通知 RRL 应在服务器上调用某个方法
- 通知 RRL 调用已完成
骨架的主要功能包括:
- 编组返回值和解组参数
- 调用实际的远程对象实现
参数的编组和解组处理了如何将参数发送到服务器以及如何将响应返回给客户端的问题。由于网络具有异构性,不同机器可能使用不同的架构和协议,因此需要进行参数的转换和处理。
以下是 RMI 工作流程的 mermaid 流程图:
graph LR
classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px;
classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;
classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
A([客户端发起调用]):::startend --> B(存根编组参数):::process
B --> C(通过 JRMP 协议发送请求):::process
C --> D(服务器接收请求):::process
D --> E(骨架解组参数):::process
E --> F(调用实际远程对象方法):::process
F --> G(骨架编组返回值):::process
G --> H(通过 JRMP 协议发送响应):::process
H --> I(存根解组返回值):::process
I --> J([返回结果给客户端]):::startend
通过本文的介绍,我们了解了高级 Java 编程中的受限属性、通过 JSP 使用 Java Bean、JAR 文件操作以及远程方法调用等重要概念和技术。这些知识对于开发分布式、可维护的 Java 应用程序具有重要意义。在实际开发中,可以根据具体需求灵活运用这些技术,提高开发效率和应用程序的性能。
5. 实际应用中的注意事项
5.1 类路径和包管理
在使用 Java Bean 和 JAR 文件时,类路径和包管理至关重要。所有类都应放在特定的包中,以确保在其他类中可访问。例如,创建的
CalculateBean
类放在
beans
包中,编译后需将其放置在
/WEB-INF/classes/beans/CalculateBean.class
路径下。如果使用 JAR 文件替代单个类文件,需将 JAR 文件放在
/WEB-INF/lib/
目录下。
以下是一个简单的步骤列表,用于确保类路径和包管理正确:
1. 创建类时,明确指定包名,如
package beans;
。
2. 编译类文件,确保生成的
.class
文件位于正确的包路径下。
3. 如果使用 JAR 文件,将其放置在
/WEB-INF/lib/
目录下。
4. 在 JSP 或其他 Java 代码中,使用完整的包名引用类,如
beans.CalculateBean
。
5.2 异常处理
在处理受限属性和 RMI 时,异常处理是必不可少的。在
DemoBean
类的
setLength
方法中,调用
vcs.fireVetoableChange
时可能会抛出
PropertyVetoException
,因此需要在方法签名中声明该异常。在 RMI 中,网络通信可能会出现各种异常,如连接失败、超时等,需要在代码中进行适当的异常处理。
以下是
DemoBean
类中异常处理的示例:
public void setLength(int l) throws PropertyVetoException {
int oldLength = length;
vcs.fireVetoableChange("length", oldLength, l);
length = l;
pcs.firePropertyChange("length", oldLength, l);
}
5.3 性能优化
在实际应用中,性能优化是一个重要的考虑因素。对于 JAR 文件,合理组织文件结构可以减少加载时间。例如,将相关的类和资源放在同一个 JAR 文件中,避免不必要的文件查找。在 RMI 中,减少网络通信次数和数据传输量可以提高性能。可以通过批量调用远程方法或优化数据传输格式来实现。
6. 高级应用场景
6.1 分布式系统中的 RMI
RMI 在分布式系统中有着广泛的应用。例如,一个企业级的电子商务系统,可能有多个服务器负责不同的业务逻辑,如商品管理、订单处理、用户认证等。客户端可以通过 RMI 远程调用这些服务器上的方法,实现业务逻辑的分布式处理。
以下是一个简单的 RMI 分布式系统示例:
1. 定义远程接口:
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteService extends Remote {
String sayHello() throws RemoteException;
}
- 实现远程接口:
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class RemoteServiceImpl extends UnicastRemoteObject implements RemoteService {
protected RemoteServiceImpl() throws RemoteException {
super();
}
@Override
public String sayHello() throws RemoteException {
return "Hello from the remote server!";
}
}
- 服务器端代码:
import java.rmi.Naming;
import java.rmi.registry.LocateRegistry;
public class RMIServer {
public static void main(String[] args) {
try {
LocateRegistry.createRegistry(1099);
RemoteService service = new RemoteServiceImpl();
Naming.rebind("rmi://localhost:1099/RemoteService", service);
System.out.println("Server is ready.");
} catch (Exception e) {
System.err.println("Server exception: " + e.toString());
e.printStackTrace();
}
}
}
- 客户端代码:
import java.rmi.Naming;
public class RMIClient {
public static void main(String[] args) {
try {
RemoteService service = (RemoteService) Naming.lookup("rmi://localhost:1099/RemoteService");
String result = service.sayHello();
System.out.println(result);
} catch (Exception e) {
System.err.println("Client exception: " + e.toString());
e.printStackTrace();
}
}
}
6.2 JSP 和 Java Bean 的结合应用
在 Web 开发中,JSP 和 Java Bean 的结合可以实现动态网页的开发。例如,一个用户注册页面,用户输入的信息可以通过 JSP 页面收集,然后传递给 Java Bean 进行处理,如数据验证、存储到数据库等。
以下是一个简单的用户注册示例:
1. 创建 Java Bean:
package beans;
import java.io.Serializable;
public class UserBean implements Serializable {
private String username;
private String password;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
- 创建 JSP 页面:
<Html>
<Head>
<title> User Registration </title>
</Head>
<body>
<jsp:useBean id="user" class="beans.UserBean" />
<form action="register.jsp" method="post">
Username: <input type="text" name="username" /><br>
Password: <input type="password" name="password" /><br>
<input type="submit" value="Register" />
</form>
<jsp:setProperty name="user" property="*" />
</body>
</Html>
- 创建处理注册的 JSP 页面:
<Html>
<Head>
<title> Registration Result </title>
</Head>
<body>
<jsp:useBean id="user" class="beans.UserBean" />
<jsp:setProperty name="user" property="*" />
<%
// 这里可以添加数据验证和存储到数据库的代码
out.println("User " + user.getUsername() + " registered successfully!");
%>
</body>
</Html>
6. 总结
通过本文的介绍,我们全面了解了高级 Java 编程中的多个重要方面,包括受限属性、通过 JSP 使用 Java Bean、JAR 文件操作以及远程方法调用等。这些技术在开发分布式、可维护的 Java 应用程序中起着关键作用。
在实际开发中,需要注意类路径和包管理、异常处理和性能优化等问题。同时,要根据具体的应用场景,灵活运用这些技术,如在分布式系统中使用 RMI,在 Web 开发中结合 JSP 和 Java Bean。通过不断学习和实践,我们可以更好地掌握这些技术,提高 Java 开发的效率和应用程序的质量。
| 技术点 | 关键信息 |
|---|---|
| 受限属性 |
使用
VetoableChangeSupport
处理受限属性变更,变更前咨询监听器
|
| JSP 使用 Java Bean |
通过
jsp:useBean
实例化 Bean,
jsp:setProperty
设置属性,
jsp:getProperty
访问属性
|
| JAR 文件操作 |
使用
jar
工具创建、查看、提取 JAR 文件,可自定义清单文件
|
| 远程方法调用(RMI) | 基于客户端/服务器模型,通过存根和骨架实现远程对象访问,使用 JRMP 协议通信 |
希望这些知识能帮助你在 Java 开发的道路上更进一步,不断探索和创新,开发出更加优秀的 Java 应用程序。
超级会员免费看
3738

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



