Struts中的Action 单例与多例详解
什么是Action
Action就是一个Struts框架中的组件之一,其作用是接收并处理客户端发送的请求,并在处理完请求后,将结果返回给客户端。
一个让人头疼的问题就是,Struts框架中的Action是单例还是多例?这个问题的答案对于我们写出可靠的代码是非常重要的,因此我们需要详细了解其单例和多例的区别。
Struts中的Action单例模式
当一个请求过来时,Struts会从Action类的工厂中获取Action的实例。
在Struts中,Action实例默认是单例的。这意味着,只有一个实例对象处理所有的请求。
具体来说,Struts框架在单例模式下,会通过Action类的类加载器生成一个唯一的实例,运行整个程序时,这个实例唯一存在,所有的请求处理都通过这个实例来完成。
单例模式的优点在于减少了内存占用,使代码运行更加高效和稳定。但是,单例模式下Action存在线程安全问题,因为多个请求可能同时访问同一个实例,导致线程安全问题和数据紊乱。
下面的代码展示了如何配置一个Action为单例模式。
<action name="login" class="com.example.LoginAction" scope="singleton" method="execute">
<result name="success">/success.jsp</result>
<result name="fail">/fail.jsp</result>
</action>
上述代码中,scope属性设置为"singleton"意味着该Action为单例模式。
Struts中的Action多例模式
与单例模式不同,Struts框架中的Action可以选择多例模式,多例模式下,每个请求都会产生一个新的Action实例,从而避免了线程安全问题和数据紊乱问题。
在Struts中,我们可以使用prototype
来将Action设置为多例模式。这样,每次请求都会创建一个新的Action实例。
下面的代码展示了如何配置一个Action为多例模式。
<action name="login" class="com.example.LoginAction" scope="prototype" method="execute">
<result name="success">/success.jsp</result>
<result name="fail">/fail.jsp</result>
</action>
上述代码中,scope属性设置为"prototype"意味着该Action为多例模式。
示例展示
下面我们使用两个示例来进一步说明单例模式和多例模式之间的区别。
示例1:单例模式
我们首先来看一个简单的登录示例,其中LoginAction为单例模式。在该示例中,如果有多个用户同时登录,会出现数据冲突问题。
public class LoginAction extends ActionSupport {
private String username;
private String password;
private static Map<String, String> currentUser = new HashMap<>(); // 当前登录用户,使用静态变量存储
@Override
public String execute() {
if ("admin".equals(username) && "admin".equals(password)) {
currentUser.put(username, getCurrentTime()); // 登录成功,将用户名和登录时间存入currentUser
return "success";
}
return "fail";
}
public String getCurrentTime() { // 获取当前时间
return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
}
public static Map<String, String> getCurrentUser() {
return currentUser;
}
// setter和getter方法
}
在上述示例中,将当前登录用户使用静态变量 currentUser 存储。因为 LoginAction 为单例模式,同时 如果多个用户同时登录,登录进来的用户只会替换 currentUser 中的值,导致数据紊乱问题。修复该问题只需要将 currentUser 改变为普通变量即可。
示例2:多例模式
下面我们来看一个使用多例模式的登录示例,在该示例中,每个请求都会创建一个新的LoginAction实例,从而避免了数据冲突问题。
@Namespace("/login")
@ResultPath("/")
@Action(value = "login", results = {
@Result(name = "success", location = "success.jsp"),
@Result(name = "fail", location = "fail.jsp")
})
@Scope("prototype")
public class LoginAction extends ActionSupport {
private String username;
private String password;
private String message;
public LoginAction() {
System.out.println("创建了一个新的LoginAction实例!");
}
@Override
public String execute() {
if ("admin".equals(username) && "admin".equals(password)) {
message = "登录成功!";
return "success";
} else {
message = "用户名或密码错误!";
return "fail";
}
}
// setter和getter方法
}
在注解中,使用@Scope("prototype")
将该Action设置为多例模式。
总结
在Struts中,如果我们需要在一个Action中保存状态信息,那么必须将其设置为多例模式。否则,单例模式下的Action会存在线程安全问题和数据紊乱问题。
而对于基本的Action请求,可以使用单例模式来提高代码运行的效率和稳定性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Struts中的Action 单例与多例详解 - Python技术站