Skip to content
sunlet edited this page Jan 10, 2016 · 34 revisions

1.JPlugin基本介绍

软件架构的本质在于模块拆分,这些经过拆分的模块经过某种契约协同满足应用软件的对外需求。在当今,软件的需求都是迭代产生的,易变的。所以,对软件本身来说,如何最大限度的应对变化,“预见未来”,甚至“随需应变”是对架构设计的极致目标。

那么,什么样子的架构才能应对未来尽可能多的可能性呢?在客户端开发工具层面,Eclipse应该是业界最成功的案例。Eclipse最早提供的功能就是一个Java的IDE,但是基于Eclipse,可以扩展出几乎任何桌面式GUI应用;并且既有的Java开发环境也可以进行无限想象的功能扩展。Eclipse之所以能够支持如此“多样性的未来”,是因为Eclipse采用了插件式框架,以及OSGI类加载机制。

JPlugin借鉴Eclipse设计思想,引入到服务端(Server Side),希望能够做到服务端的Eclipse。JPlugin引入插件的思想,插件、扩展点、扩展等基本概念都有实现,插件的生命周期有完整的实现。插件式架构的核心就是,在可能变化的地方定义扩展点,让所有产生变化的地方都扩展来实现;同时,用插件在组织应用软件的模块,最大限度实现松耦合和依赖倒置;还有,由于可以在扩展点方便地管理所有扩展,这对系统的监控以及开发高性能的应用都提供了很多方便。

使用JPlugin,对于应对复杂的应用以及应用未来的变化应该说是非常好的选择;同时,对于一次性的或者较简单的应用来说,JPlugin也提供了现成的核心插件可供使用。这些基本插件提供了诸如MVC、交易、日志、数据持久化(提供了Mybatis和Hiberinate的集成器)、缓存、调度等功能,可以方便地快速开发应用。

2.如何引用

在Maven项目中增加如下依赖:

<dependency>
		<groupId>net.jplugin.mvn</groupId>
		<artifactId>jplugin-core</artifactId>
		<version>1.4.0-SNAPSHOT</version>
	</dependency>
	<dependency>
		<groupId>net.jplugin.mvn</groupId>
		<artifactId>jplugin-web</artifactId>
		<version>1.4.0-SNAPSHOT</version>
	</dependency>
	<dependency>
		<groupId>org.mybatis</groupId>
		<artifactId>mybatis</artifactId>
		<version>3.2.8</version>
	</dependency>
	<dependency>
		<groupId>javax.servlet</groupId>
		<artifactId>servlet-api</artifactId>
		<version>2.4</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>javax.servlet.jsp</groupId>
		<artifactId>jsp-api</artifactId>
		<version>2.1</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>mysql</groupId>
		<artifactId>mysql-connector-java</artifactId>
		<version>5.1.36</version>
		<scope>provided</scope>
	</dependency>
	<dependency>
		<groupId>junit</groupId>
		<artifactId>junit</artifactId>
		<version>3.8.1</version>
		<scope>test</scope>
	</dependency>

#3.相关配置文件 ##数据库配置 数据库配置文件部署以后发布在在WEB-INF/classes/config目录下面。

#jdbc driver class name
driverClassName=com.mysql.jdbc.Driver
#the database url
url=jdbc:mysql://localhost:3306/weapp?useUnicode=true&amp;characterEncoding=utf8

dbuser=root
dbpassword=toor

maxActive=100 
#max idle connections 
maxIdle=50
#max wait seconds till time out
maxWait=2000

##日志配置 日志配置文件在 WEB-INF/classes/config/log4j.properties,默认配置如下,一般无需修改。另外,Jplugin体系支持专用的单独日志文件,请在后面“日志”章节查看。

log4j.rootLogger=ERROR, root,stdout
log4j.appender.root=org.apache.log4j.DailyRollingFileAppender
log4j.appender.root.file=${work-dir}/logs/root
log4j.appender.root.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.root.layout=org.apache.log4j.PatternLayout
log4j.appender.root.layout.ConversionPattern=%d %-5p %F %L - %m%n

log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%p [%c] %m%n

##Plugin注册配置 WEB-INF/classes/config/plugin.cfg文件注册一个或者多个Plugin类。在“Plugin与Plugin注册”章节有详细介绍。

#4.Plugin与Plugin的注册 ##Plugin类及其作用

在JPlugin项目中,理论上所有代码都被分到不同的Plugin当中,在实际使用中,一个Plugin一般为Eclipse中一个Java项目。

每一个Plugin必须包含一个Plugin主类,该类继承自AbstractPlugin父类。Plugin主类为该Plugin在软件体系中的实际标识,在主类注册该Plugin的扩展点、扩展,提供该Plugin的优先级。

##系统级Plugin和用户级Plugin Plugin分两类:系统级Plugin、用户级Plugin。系统级Plugin为框架本身提供的Plugin。用户级Plugin为在应用中开发的Plugin。

##系统级别Plugin的注册和加载 系统级Plugin无需注册,系统启动时自动加载。系统级Plugin的优先级都小于0(负数),所以一般会优先加载。

##用户级Plugin的注册和加载

用户级Plugin需要在WEB-INF/classes/config/plugin.cfg文件中进行注册,这个文件中可以注册一个或者多个类,每一行代表一个类名称。比如:

com.hello.HelloPlugin

#5.Web控制器

Web控制器提供一个类作为Web请求的源。JPlugin提供两种格式的Web控制器,基础Web控制器和扩展Web控制器。

##基础Web控制器

基础Web控制器不需要继承任何父类,但是每个方法都需要传入HttpServletRequest和HttpServletResponse对象作为参数。下例支持 http://xxxxx/custbasic.do 访问:

Plugin.java这样写:
public class Plugin extends AbstractPlugin{
public Plugin(){
		ExtensionWebHelper.addWebControllerExtension(this, "/custbasic", CustomerControllerBasic.class);
}
public void init() {
}
@Override
public int getPrivority() {
	return 0;
}
}

CustomerControllerBasic.java:
public class CustomerControllerBasic {
public void list(HttpServletRequest req,HttpServletResponse res) {
   。。。。。。
}
}

##扩展Web控制器

扩展Web控制器需要继承AbstractExController父类,每个方法都不需要参数。下例支持 http://xxxxx/list.do 访问:

Plugin.java这样写:
public class Plugin extends AbstractPlugin{
public Plugin(){
        ExtensionWebHelper.addWebExControllerExtension(this, "/cust", CustomerController.class);
}
public void init() {
}
@Override
public int getPrivority() {
	return 0;
}
}

CustomerControllerBasic.java:
public class CustomerControllerBasic extends AbstractExController{

public void list() {
     //可以调用getParam, getAttr,setAttr等父类方法
     //可以调用renderJsp、renderJson等方法
}
}

#6.开发和使用服务

如果想发布一些Singleton的服务,并通过ServiceFacotory.getService()方法获取到,可以先在Plugin类中把服务扩展出去,然后所有的代码中都可以使用了:比如在Plugin类构造函数中加入如下代码片段: ExtensionServiceHelper.addServiceExtension(this,”s1” , MyService.class); 然后在需要的地方,就可以用ServiceFactory.getService("s1",MyService.class);

##注意: ServiceFactory.getService(cls)的会最终实现为下面的代码:ServiceFactory.getService(cls.getName(),cls); 所以,鼓励把服务的实现和接口分离。然后,把注册的服务名字定位接口类的全名。如此就可以用 ServiceFactory.getService(接口类) 来获取服务了。

#7.开发和使用业务规则服务

#8.使用日志

#9.使用独立日志文件

#10.使用Mybatis

#11.使用Hiberinate 略,目前不要使用Hiberinate

#12.发布和使用Restful服务

#13.发布和使用远程服务

#14.使用HTTP请求过滤器