Skip to content
This repository has been archived by the owner on Aug 20, 2019. It is now read-only.

Latest commit

 

History

History
648 lines (580 loc) · 20.9 KB

doc.org

File metadata and controls

648 lines (580 loc) · 20.9 KB

JFinal-Ext文档(v3.1.3)

JFinal测试框架

在非web环境下对jfinal Controller 进行单元测试

使用说明

所有对Controller的测试必须继承ControllerTestCase,此类中方法说明如下

use需要调用的url
postpost数据包,支持String和File
writeToresponse数据写入文件
invoke调用url
findAttrAfterInvokeaction调用之后getAttr的值

示例代码

public class PostTestCase extends ControllerTestCase<Config> {

    @Test
    public void line() throws Exception {
        String url = "/post";
        String filePath = Thread.currentThread().getContextClassLoader().getResource("dataReq.xml").getFile();
        String fileResp = "/home/kid/git/jfinal-ext/resource/dataResp.xml";
        String resp = use(url).post(new File(filePath)).writeTo(new File(fileResp)).invoke();
        System.out.println(resp);
    }

    @Test
    public void test3() {
        String url = "/post/1?age=1&age=2&name=2";
        String body = "<root>中文</root>";
        use(url).post(body).invoke();
    }
}

Plugin扩展

自定绑定表 AutoTableBindPlugin

简介

扫描clsspath和lib中继承了model的类自动注册,可选择不同的命名规则自定映射表名,也可以在每一个model上用注解指定表名

AutoTableBindPlugin使用示例

基本使用

AutoTableBindPlugin 继承自ActivitiRecordPlugin,所以如果你使用 AutoTableBindPlugin则不用再使用ActivitiRecordPlugin,其他需要在 ActiviRecordPlugin中的设置都在此plugin中设置,比如方言,大小写不敏 感等..

	DruidPlugin druid = new DruidPlugin("jdbc:mysql://127.0.0.1/jfinal_demo", "root", "root");
	AutoTableBindPlugin atbp = new AutoTableBindPlugin(druid);

*记住一定要在启动atbp之前启动连接池的plugin

jar包扫描

如果你需要载入jar包中的model,需要调用以下的api将jar包加入扫描

		atbp.addJar("modelInJar.jar");
		atbp.addJars("jar1,jar2");

表名风格INameStyle 配置

一个model自动绑定的表明默认是该类的simpleClassname,如果需要用其他 的命名风格,需要在构造函数中指定,如

AutoTableBindPlugin atbp = new AutoTableBindPlugin(cp,SimpleNameStyles.LOWER);

SimpleNameStyles 中已有的命名风格以及映射的表明如下表:

DEFAULTFIRST_LOWERUPLOWERUP_UNDERLINELOWER_UNDERLINE
DevInfo.javaDevInfodevInfoDEVINFOdevinfoDEV_INFOdev_info

ParamNameStyles 含有构造参数的命名风格:

module(test)lowerModule(test)upModule(test)upUnderlineModule(test)lowerUnderlineModule(test)
DevInfo.javatest_DevInfotest_devinfotest_DEVINFOtest_DEV_INFOtest_dev_info

TableName 配置

如果有Model到表的映射命名不符合规范需要单独配置,则在Model上加上 TableName注解,属性说明如下:

tableName表名必填
pkName外键名默认””
configName数据源名默认””

关闭自动扫描

如果你只想用注解而不想让没有注解的model被自动注册,则如下使用

 	atbp.setAutoScan(false);

忽略不想自动扫描的Model

如果你打开了自动扫描,但是又有不想要被扫描进去的,如通用的BaseModel

atbp.addExcludeClass(Class<? extends Model> clazz)

多数据源

推荐将不同数据源的Model放在不同的package中然后调用 addScanPackages 设置要扫描的package

atbp = new AutoTableBindPlugin(druidPlugin)
        .addScanPackages("com.xx.yy.service1.model");
atbp2 = new AutoTableBindPlugin("another",druidPlugin2)
        .addScanPackages("com.xx.yy.service2.model2","com.xx.yy.service2.model3")

如果在一个package里面有属于不同数据源的model(如果不是因为无法避 免的历史遗留原因不要采用这样的方式),那么给Model加上TableBind注 解并给configName属性赋值

SqlInXmlPlugin

简介

类似ibatis的在xml中管理sql.主要用于复杂的sql管理或者有dba的开发团 队

使用示例

插件会扫描classpath根目录下以”.sql”结尾的xml文件. 用一个xml举例,文件名为user-sql.xml,内容如 下:

<sqlGroup name="blog" >
      <sql id="findBlog">select * from blog</sql>
      <sql id="findUser">select * from user</sql>
</sqlGroup>

插件会将name+id作为一个sql语句的唯一标识, 在java中获取该sql的方法为 SqlKit.sql(“blog.findBlog”)

jms消息处理 JmsPlugin

消息接收

如果你需要处理某个消息号对应的消息,需要实现com.jfinal.plugin.jms.ReceiveResolver

public class AReceiveResolver implements ReceiveResolver {

	@Override
	public void resolve(Serializable objectMessage) throws Exception {
		System.out.println("AReceiveResolver");
	}

}

消息发送

  • 示例 JmsKit.sendQueue(“q1”, new M(), “a”);
  • 接口 public static boolean sendQueue(String queueName, Serializable

message, String msgName)

  • 参数说明
    queueNamemessagemsgName
    发送队列的名字发送的消息对象发送的消息名字

配置文件说明

################################
#          server info         #
################################
# jms服务器地址
serverUrl=tcp://localhost:61616
username=system
password=manager

################################
#          queue info          #
################################
# 发送的队列名字,用“,”号分隔
sendQueues=q1,q2

# 接受的队列的名字,用“,”号分隔
receiveQueues=q1,q3
# 队列q1上消息名字为a的消息号
queue.q1.a=10000
#接受到队列q1上消息名字为a的消息的时候调用的处理器
queue.q1.a.resolver=test.com.jfinal.plugin.jms.AReceiveResolver

queue.q1.b=20000
queue.q1.b.resolver=test.com.jfinal.plugin.jms.BReceiveResolver

################################
#          topic info          #
################################

sendTopics=t1,t2

receiveTopics=t1,t3
topic.t1.c=30000
topic.t1.c.resolver=test.com.jfinal.plugin.jms.CReceiveResolver

topic.t3.d=40000
topic.t3.d.resolver=test.com.jfinal.plugin.jms.DReceiveResolver

任务调度 QuartzPlugin Cron4jPlugin

业务如何调度

QuartzPlugin

需要进行的调度任务实现必须实现org.quartz.Job接口

Cron4jPlugin

需要进行的调度任务实现必须实现java.lang.Runnable接口

如何加载配置

插件默认加载classpath根目录下job.properties文件。 如果需要加载指定的配置文件,需要在构造方法中传入参数

配置文件说明

job.properties配置示例

#JobA
a.job=test.com.jfinal.plugin.quzrtz.JobA
a.cron=*/5 * * * * ?
a.enable=true
#JobB
b.job=test.com.jfinal.plugin.quartz.JobB
b.cron=*/10 * * * * ?
b.enable=false

配置说明 job cron enable为配置关键字 a和b为任务的名字,仅作为标识,无其他用处。

任务名字.job调度任务的类全名
任务名字.cron调度任务的cron表达式
任务名字.enable调度任务是否启用

如何在代码中添加任务

在plugin上调用add方法

Quartz 1.X和2.X版本不兼容问题

quartz 2.X版本和1.X不兼容. JobDetail 和 CornTrigger 在 1.X版本中是Class,但是在2.X版本中是Interface. QuartzPlugin 解决了兼容问题,默认使用2.X版本,如果需要使用1.X,调用quartzPlugin.version(QuartzPlugin.VERSION_1)即可.

ConfigPlugin

分优先级加载配置文件 在团队开发中如果自己有测试配置需要长期存在但是又不需要提交中心库的时候 可以采用分级配置加载的策略。 如中心库中有config.properties这个配置,你可以创建 config-test.properties文件,配置相同的key,ConfigKit中的方法会优先加载 xx-test.properties文件。

如何加载配置

	ConfigPlugin configPlugin = new ConfigPlugin();
		configPlugin.addResource(".*.properties");

addResource支持正则表达式 当我们加载config.properties时候会找config-test.properties一起加载.

配置说明

如果我们加载了以下两个配置,下面的测试用例能通过,也就是说当*-test中同 名的key优先读取. config.properties

name=aa
age=1

config-test.properties

name=test
	@Test
	public void testGetStr() throws InterruptedException {
		Assert.assertEquals("test",ConfigKit.getStr("name"));
		Assert.assertEquals(1,ConfigKit.getInt("age"));
	}

MongodbPlugin

简介

MongodbPlugin 是Jfinal-ext扩展的nosql插件,在MongoKit中封装mongodb 的常用操作。

使用方法

创建

默认ip和端口

MongodbPlugin mongodbPlugin = new MongodbPlugin("log")
MongodbPlugin mongodbPlugin = new MongodbPlugin("127.0.0.1", 8888, "other");

分页查询

Map<String, Object> filter = new HashMap<String, Object>();
filter.put("age", "20") ;  //精确过滤
Map<String, Object> like = new HashMap<String, Object>();
like.put("name","zhang");  //模糊匹配,相当于sql 的 like %zhang%
Map<String, Object> sort = new HashMap<String, Object>();
sort.put("age","desc");     //排序
Page<Record> page = MongoKit.paginate("sns", 1, 10, filter, like,sort);

新增

MongoKit.save("sns", record) //保存一个record
MongoKit.save("sns", records)//批量保存record

删除

MongoKit.removeAll("sns")  //删除所有sns

Map<String, Object> filter  = new HashMap<String,Object>();
filter.put("name", "bb");
filter.put("age", "1");
MongoKit.remove("sns", filter);  //删除符合条件的sns

修改

Map<String, Object> src = new HashMap<String, Object>();
src.put("age", "1");  //查询条件
Map<String, Object> desc = new HashMap<String, Object>();
desc.put("addr", "test"); //将符合查询条件的文档修改为此文档
MongoKit.updateFirst("sns", src, desc); //只能修改符合条件的第一条数据..

Render扩展

DwzRender

      public void save() {
		Blog model = getModel(Blog.class);
		if (model.getInt("id") == null) {
			model.save();
		} else {
			model.update();
		}
		render(DwzRender.closeCurrentAndRefresh("pageBlog"));
	}

	public void edit() {
		int id = getParaToInt(0);
		Blog blog = Blog.dao.findById(id);
		if (id == -1) {
			blog = new Blog();
		} else if (blog == null) {
			render(DwzRender.error("该记录已被删除,请您先刷新列表"));
		}
		setAttr("blog", blog);
	}

	public void delete() {
		Blog.dao.deleteById(getParaToInt());
		render(DwzRender.success());
	}

JxlsRender

通过list数据生成excel,支持的数据类型为map ,record , model。

PoiRender

通过list数据生成excel,支持多sheet导出,支持的数据类型为map ,record , model.

示例代码

PoiRender.me(data,data2,...dataN).fileName("your_file_name.xls").headers(headers,headers2,...headerN).cellWidth(5000).headerRow(2)

excel2003和2007版本问题

2003版一个sheet只支持最多65535行,2007则没有此限制.对此PoiRender做了如 下处理

  • 默认使用2007版,单个sheet的data无限制,如果想用2003版调用以下API:
    PoiRender.me(data).version(PoiKit.VERSION_2003)
        

多sheet支持

  • data ,sheetNames,headers,columns长度必须相同.
  • 2003版本,如果data长度大于1,会检查每个data的item的数据长度,不允许超 过65535
  • 2003版本,如果data长度等于1,如果数据超过65535,会自动拆分为多个sheet

CsvRender

通过list数据生成csv,支持的数据类型为map ,record , model。

AmChartsRender

对AmCharts报表工具进行了简单的封装

      public void pie(){
		List<KeyLabel> pies = new ArrayList<KeyLabel>();
		KeyLabel e= new KeyLabel("java","111");
		pies.add(e);
		KeyLabel e2= new KeyLabel("c","11");
		pies.add(e2);
		render(AmChartsRender.pie(pies, "ampie.swf", "pie_settings.xml",500,500));
	}

	public void multiple(){
		List<String> data = new ArrayList<String>();
		data.add("10");
		data.add("11");
		data.add("12");
		data.add("13");
		data.add("14");
		List<String> data1 = new ArrayList<String>();
		data1.add("20");
		data1.add("21");
		data1.add("22");
		data1.add("23");
		data1.add("24");
		List<List<String>> list = new ArrayList<List<String>>();
		list.add(data);
		list.add(data1);
		List<String> series = new ArrayList<String>();
		series.add("1月");
		series.add("2月");
		series.add("3月");
		series.add("4月");
		series.add("5月");
		render(AmChartsRender.graph(list, series, "amline.swf", "line_settings.xml"));
	}
	public void simple(){
		List<String> data = new ArrayList<String>();
		data.add("10");
		data.add("11");
		data.add("12");
		data.add("13");
		data.add("14");
		List<String> series = new ArrayList<String>();
		series.add("1月");
		series.add("2月");
		series.add("3月");
		series.add("4月");
		series.add("5月");
		render(AmChartsRender.graph(data, series, "amline.swf", "line_settings.xml"));
	}public void pie(){
		List<KeyLabel> pies = new ArrayList<KeyLabel>();
		KeyLabel e= new KeyLabel("java","111");
		pies.add(e);
		KeyLabel e2= new KeyLabel("c","11");
		pies.add(e2);
		render(AmChartsRender.pie(pies, "ampie.swf", "pie_settings.xml",500,500));
	}

	public void multiple(){
		List<String> data = new ArrayList<String>();
		data.add("10");
		data.add("11");
		data.add("12");
		data.add("13");
		data.add("14");
		List<String> data1 = new ArrayList<String>();
		data1.add("20");
		data1.add("21");
		data1.add("22");
		data1.add("23");
		data1.add("24");
		List<List<String>> list = new ArrayList<List<String>>();
		list.add(data);
		list.add(data1);
		List<String> series = new ArrayList<String>();
		series.add("1月");
		series.add("2月");
		series.add("3月");
		series.add("4月");
		series.add("5月");
		render(AmChartsRender.graph(list, series, "amline.swf", "line_settings.xml"));
	}
	public void simple(){
		List<String> data = new ArrayList<String>();
		data.add("10");
		data.add("11");
		data.add("12");
		data.add("13");
		data.add("14");
		List<String> series = new ArrayList<String>();
		series.add("1月");
		series.add("2月");
		series.add("3月");
		series.add("4月");
		series.add("5月");
		render(AmChartsRender.graph(data, series, "amline.swf", "line_settings.xml"));
	}

FreeMarkerXMLRender

利用freemaker生成xml

Routes扩展

自动注册Route AutoBindRoutes

简介

扫描clsspath和lib中继承了Route的类按照约定的规则自动注册,也可以在 每一个Route上用注解配置

示例代码

public void configRoute(Routes me) {
    me.add(new AutoBindRoutes());
}

如果我们有一个AController,以上代码则相当于

public void configRoute(Routes me) {
     me.add("/a",AController.class);
 }

默认的注册规则是截取类名Controller前的部分并首字母小写.

ControllerBind配置

如果需要单独配置Route,需要在Controller上加上ControllerBind注解

ControllerBind 注解,属性说明如下:

controllerKey访问某个 Controller 所需要的一个字符串
viewPathController 返回的视图的相对路径

Interceptor扩展

ExceptionInterceptor统一异常处理

简介

对Controller抛出的异常按照类型进行定制化处理

示例代码

ExceptionInterceptor exceptionInterceptor = new ExceptionInterceptor();
exceptionInterceptor.addMapping(IllegalArgumentException.class, "/exceptions/a.html");
exceptionInterceptor.addMapping(IllegalStateException.class, "exceptions/b.html");
exceptionInterceptor.setDefault(new ErrorRender("测试系统"));

addMapping 设置一个异常类型对应的View,可以是一个视图路径,也可以是 一个ExceptionRender的子类,类似Controller的 render(String) 和 render(Render)方法 setDefault是当抛出的异常在mapping中没有找到的时候调用的默认的异常处 理方式。

I18nInterceptor 国际化拦截器

简介

简化国际化页面的render处理。

render策略

会在原有的render路径上加上当前请求参数中的country和language。 例如(/p?language=zh&country=CN)

原始viewcountrylanguage改变之后的view
/pzhCN/zh_CN/p/index.html

country 默认值为zh language默认值为CN

SysInterceptor 系统日志拦截器

简介

ActionReport的人性化版本,用于后台管理系统的日志记录

使用方法

配置LogConfig

SysLogInterceptor log = new SysLogInterceptor();
log.addConfig("/blog", new LogConfig("查看博客").addPara("user", "作者名字"));

实现LogProcessor

需要实现以下方法

| process(SysLog sysLog)                                   | 处理条日志       |
| getUsername(Controller c)                                | 获取当前登陆用户名 |
| formatMessage(String title, Map<String, String> message) | 格式化日志信息     |

示例代码

一个简单的日志处理器的实现

public class DefaultLogProccesor implements LogProccesor {
    @Override
    public void process(SysLog sysLog) {
        Map map = BeanUtils.describe(sysLog);
        map.remove("class");
        Record record = new Record();
        record.setColumns(map);
        Db.save("syslog", record);
    }

    @Override
    public String getUsername(Controller c) {
        User user = c.getSessionAttr("user");
        return user.getStr("username");
    }

    @Override
    public String formatMessage(String title, Map<String, String> message) {
        String result = title;
        if (message.isEmpty()) {
            return result;
        }
        result += ", ";
        Set<Entry<String, String>> entrySet = message.entrySet();
        for (Entry<String, String> entry : entrySet) {
            String key = entry.getKey();
            String value = entry.getValue();
            result += key + ":" + value;
        }
        return result;
    }

}

ExcelUploadInterceptor

简介

上传excel文件解析为model并持久化

使用方法

配置解析规则Rule

 <rule>
  <sheetNo>1,2<sheetNo>  非必须,默认解析所有sheet.可指定解析对应的sheet,解析多个sheet用","分隔
    <start>1</start> 非必须,默认0.解析开始行坐标,从0开始
    <end>-1</end> 非必须,默认-1.解析结束行坐标,负数时候从最后一行往回索引.
    <postExcelProcessorn>com.xx.xx.AProcessor</postExcelProcessor>
    <postListProcessor>com.xx.xx.BProcessor</postListProcessor>
    <preExcelProcessor>com.xx.xx.CProcessor</preExcelProcessor>
    <preListProcessor>com.xx.xx.DProcessor</preListProcessor>
    <cells> 每一个单元格的解析策略
        <cell>
            <index>1</index> 单元格索引,从0开始
            <attribute>en_name</attribute> model属性名
        </cell>
        <cell>
            <index>2</index>
            <attribute>cn_name</attribute>
        </cell>
        <cell>
            <index>3</index>
            <attribute>explanation</attribute>
        </cell>
     ...
    </cells>
</rule>

实现ExcelUploadInterceptor

示例代码

eclipse代码片段

将jfinal-templates.xml导入eclipse的Preferences-java-Editor-Templates

jfl

在任何类中使用,生成logger

protected final Logger logger = Logger.getLogger(getClass());
protected final static Logger logger = Logger.getLogger(Object.class);

jfd

在Model中使用,生成dao

public final static Model dao = new Model();

jfld

在需要打印日志的变量下面使用

logger.debug("var :" + var);

jfli

在需要打印日志的变量下面使用

logger.info("var :" + var);

jfle

在需要打印日志的变量下面使用

logger.error("var :" + var);