作者:冰莲如水
本文讲述Struts应用在实际项目中的插件类开发技术。在我们的learndiaryV1.0项目中已经有了很好的应用。通过对它的讲解,我们可以了解在应用开发中这一技术的实做经验。首先说明Struts插件扩展技术的特点:
Struts框架的一大优势在于它允许开发人员根据实际需要来扩展框架,定制客户化的功能。
Struts1.1框架提供了动态插入和加载组件的功能,这种组件被称为Struts插件。Struts插件实际上就是一个Java类,它在Struts应用启动时Struts框架调用每个插件的init()方法进行初始化,在插件的初始化阶段可以完成一些初始化的操作,如建立数据库连接,和远程系统建立连接,在当前的应用范围内加入插件类自身的实例等。在应用关闭时Struts框架会调用每个插件的 destroy()方法,destroy()方法可以用来完成释放资源的任务,如关闭数据库连接,断开与远程的连接等。任何作为插件的Java类都应该实现org.apache.struts.action.PlugIn接口。PlugIn接口包括两个方法:
public interface PlugIn {
/**
*当struts应用启动时,下面的方法将被调用执行
*/
public void init(ActionServlet servlet, ApplicationConfig config)
throws ServletException;
/**
*当struts应用关闭时,将调用下面的方法,以释放资源。
*/
public void destroy();
}
我们在learndiaryV1.0这个项目中使用了Struts框架的PlugIn插件扩展来实现ServiceFactory类。ServiceFactory为应用中的业务逻辑工厂类,它将提供创建各种业务逻辑类实例的方法,我们是通过对业务逻辑类实例的方法调用最终实现后台的商业逻辑及业务数据的检索和持久化的。关于持久层的存取更新请参阅《Hibernate 存取及批量更新删除》这一章节。ServiceFactory 工厂类实现了 Struts 的 PlugIn 接口并在 Struts 的配置文件struts-config中对其进行了配置描述,使其在Struts系统启动时自动被加载。而在 ServiceFactory 工厂类所覆盖的 PlugIn 的 init() 方法中,此工厂类将其自身加入到应用的 ServletContext 实例当中去。在具体的项目中,因为ServiceFactory 工厂类已经被启动并加载,在加载的过程中init() 方法又将ServiceFactory 工厂类自身的实例加入到ServletContext当中,我们便可以通过servlet.getServletContext().getAttribute(Constants.SERVICE_FACTORY_KEY)这样的方法对此ServiceFactory工厂类进行引用。通常我们也可以在struts-config文件中的ServiceFactory工厂类插件配置项<plug-in>中加入插件类的启动参数<set-property>,在当前的应用中我们没有采用这样的方式。听上去可能会糊里糊途的,我们还是从代码中找到灵感吧!
首先我们构建出你的ServiceFactory类所要去实现的接口类,这有利于实现商业应用的面向接口的编程,这是一种良好的JAVA开发规范。在今后的开发环节当中我们还会遇到类似的开发案例。
package com.learndiary.website.services;
import java.lang.IllegalAccessException;
import java.lang.ClassNotFoundException;
import java.lang.InstantiationException;
/**
* 业务逻辑工厂的接口
* 应用程序开发后期将会扩充此工厂接口,
* 设置各种createService()方法,
* 返回均为此业务逻辑方法的接口。
*/
public interface IServiceFactory {
public IBusinessService createService() throws ClassNotFoundException,
IllegalAccessException,InstantiationException;
public IUserService createUserService(String serviceName) throws ClassNotFoundException,
IllegalAccessException,InstantiationException;
public IUserService createUserService() throws ClassNotFoundException,
IllegalAccessException,InstantiationException;
public void destroy();
}
你会发现上面的代码中所有方法返回的实例都定义为业务逻辑接口形式,如IBusinessService createService() 。在各类的IBusinessService接口中我们定义了这一类业务逻辑接口所要实现的方法。例如IUserService接口为我们定义了如下的一些方法。
public interface IUserService extends IBusinessService{
public User saveUser (User user) throws BusinessException;
public User findUserById(Long id) throws BusinessException;
public User findUserByName(String name) throws BusinessException;
public User findUserByEmail(String email) throws BusinessException;
public User findUserByPassword(String name, String password) throws BusinessException ;
public void saveOrUpdateUser(User user) throws BusinessException;
public List getUsers() throws BusinessException;
public int getAllUserNum() throws BusinessException;
}
此外IServiceFactory接口的定义中还存在着IUserService createUserService()的重载形式IUserService createUserService(String serviceName),这是为了方便大家对于这一应用形式的重构和扩展。
ServiceFactory的具体实现类如下:
package com.learndiary.website.services;
import javax.servlet.ServletException;
import java.lang.InstantiationException;
import java.lang.IllegalAccessException;
import org.apache.struts.action.ActionServlet;
import org.apache.struts.action.PlugIn;
import org.apache.struts.config.ModuleConfig;
import com.learndiary.website.Constants;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.Configuration;
/**
*业务逻辑工厂,ServiceFactory工厂类实现了struts 的PlugIn接口,
*使其将在系统启动时,自动被加载;在工厂类所覆盖的PlugIn的init()方法中,
*此工厂类将其自身加入到应用的ServletContext实例当中去。
*/
public class ServiceFactory implements IServiceFactory,PlugIn {
//由init()方法中传入ActionServlet实例
private ActionServlet servlet =null;
private String serviceClassname = "com.learndiary.website.services.ORMService";
/*
* 创建业务逻辑实例的模板
*/
public IBusinessService createService() throws ClassNotFoundException,
IllegalAccessException, InstantiationException {
IBusinessService serInstance =
(IBusinessService)Class.forName(serviceClassname).newInstance();
serInstance.setServletContext(servlet.getServletContext());
return serInstance;
}
/*
* 根据给定的服务类名,创建服务类的对象。
* 以接口IBusinessService型式返回。
*/
public IUserService createUserService(String serviceName) throws ClassNotFoundException,
IllegalAccessException, InstantiationException{
IUserService serInstance=
(IUserService)Class.forName(serviceName).newInstance();
serInstance.setServletContext(servlet.getServletContext());
return serInstance;
}
public IUserService createUserService() throws ClassNotFoundException,
IllegalAccessException,InstantiationException{
IUserService serInstance = new UserService();
serInstance.setServletContext(servlet.getServletContext());
return serInstance;
}
public void destroy() {
}
/*
* 扩展Struts PlugIn接口的 init()方法
* Struts框架会在启动系统时,自动加载扩展了PlugIn接口的组件。
* 并调用此组件中的init()方法,对其进行初始化。
*
*/
public void init(ActionServlet svt, ModuleConfig conf)
throws ServletException {
this.servlet = svt;
/*
* 此处,利用组件初始化时,将本工厂实例保存于当前的ServletContext中。
* 此后,我们便可以在应用当中,调用此工厂实例。即调用ServiceFactory。
*/
servlet.getServletContext().setAttribute(Constants.SERVICE_FACTORY_KEY,this);
}
}
其中的public IBusinessService createService() throws ClassNotFoundException,
IllegalAccessException, InstantiationException {
IBusinessService serInstance =
(IBusinessService)Class.forName(serviceClassname).newInstance();
serInstance.setServletContext(servlet.getServletContext());
return serInstance;
}
为构建业务逻辑实现类的模板。业务逻辑实现类的具体的实例采用IBusinessService serInstance =
(IBusinessService)Class.forName(serviceClassname).newInstance();
的方式构建。关于具体的业务逻辑实现类是怎么样实现业务功能的,将在后续的章节中介绍。
在你的应用中加入了以上ServiceFactory工厂类之后,我们要把它作为Struts应用的插件加入到Struts配置文件当中, Struts框架在启动时将根据插件类相关的配置信息来初始化插件。与插件对应的配置元素为 <plug-in>,在struts-config.xml中对ServiceFactory插件类进行的如下配置:
<plug-in className="com.learndiary.website.services.ServiceFactory">
</plug-in>
根据Struts 配置文件的DTD 定义,在Struts配置文件中, <plug-in>元素必须位于其他配置元素的后面,此外,如果在配置文件中布署了多个插件, Struts框架将按照它们在配置文件中的先后顺序来依次初始化它们。
合理的使用好Struts的插件类扩展,将使我们的应用更加健壮,功能上具有良好的可扩展性和可移植性。在本文中也许存有疏漏错误之处,请开发员朋友们不吝恩教,吾人当励行而改之!
以上代码均为开源社区learndiary.com 1.0版本下测试通过的实际应用代码,你可以联系作者取得相关原码文件。
联系本文作者:QQ 284508610
谢谢你的代码,很有启发!
不过你的代码扩展性不是很好
应该多考虑使用Ioc等技术。