记录第一次使用JFinal,从简单的框架搭建到增删改查,从自带的方法到正常框架习惯的使用方式。

JFinal官网:http://www.jfinal.com/

JFinal 是基于 Java 语言的极速 WEB + ORM 框架,其核心设计目标是开发迅速、代码量少、学习简单、功能强大、轻量级、易扩展、Restful。在拥有Java语言所有优势的同时再拥有ruby、python、php等动态语言的开发效率。

JFinal有如下主要特点:

  • MVC架构,设计精巧,使用简单

  • 遵循COC原则,零配置,无xml

  • 独创Db + Record模式,灵活便利

  • ActiveRecord支持,使数据库开发极致快速

  • 自动加载修改后的java文件,开发过程中无需重启web server

  • AOP支持,拦截器配置灵活,功能强大

  • Plugin体系结构,扩展性强

  • 多视图支持,支持FreeMarker、JSP、Velocity

  • 强大的Validator后端校验功能

  • 功能齐全,拥有struts2的绝大部分功能

  • 体积小仅632K,且无第三方依赖

例子:

本人用的maven,首先创建一个maven项目:

我的项目创建之后首先要设置:

然后点Apply

还有其他一些设置等等,我的问题,这里先跳过

然后在pom.xml中引入jar包:

maven搜索jar包:http://mvnrepository.com/

官方demo的pom.xml:

这里没有引入json,我的这个demo最后的方法需要json

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo</groupId>
<artifactId>jfinal_demo_for_maven</artifactId>
<packaging>war</packaging>
<version>3.2</version>
<name>jfinal_demo_for_maven Maven Webapp</name>
<url>http://maven.apache.org</url> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.encoding>UTF-8</maven.compiler.encoding>
</properties> <!-- 使用阿里 maven 库 -->
<repositories>
<repository>
<id>ali-maven</id>
<url>http://maven.aliyun.com/nexus/content/groups/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
</repositories> <!-- 添加快照版本库,updatePolicy: always、daily、interval、never -->
<!-- repositories>
<repository>
<id>sonatype-nexus-snapshots</id>
<name>Sonatype Nexus Snapshots</name>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>daily</updatePolicy>
</snapshots>
</repository>
</repositories --> <dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jetty-server</artifactId>
<version>8.1.8</version>
<!--
此处的 scope 值为 compile 仅为支持 IDEA 下启动项目
打 war 包时需要改成 provided,以免将一些无用的 jar 打进去
-->
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>jfinal</artifactId>
<version>3.3</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.16</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.44</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
<dependency>
<groupId>com.jfinal</groupId>
<artifactId>cos</artifactId>
<version>2017.5</version>
</dependency> </dependencies> <build>
<finalName>jfinal_demo_for_maven</finalName>
<plugins>
<plugin>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty-maven-plugin</artifactId>
<version>8.1.8.v20121106</version>
<configuration>
<stopKey>stop</stopKey>
<stopPort>5599</stopPort>
<webAppConfig>
<contextPath>/</contextPath>
</webAppConfig>
<scanIntervalSeconds>5</scanIntervalSeconds>
<connectors>
<connector implementation="org.eclipse.jetty.server.nio.SelectChannelConnector">
<port>80</port>
<maxIdleTime>60000</maxIdleTime>
</connector>
</connectors>
</configuration>
</plugin>
</plugins>
</build>
</project>

然后是web.xml的配置:

注意:

注意:DemoConfig.java 文件所在的包以及自身文件名必须与 web.xml 中的 param-value 标签内的配置相一致(在本例中该配置为 demo.DemoConfig)。

<filter>
<filter-name>jfinal</filter-name>
<filter-class>com.jfinal.core.JFinalFilter</filter-class>
<init-param>
<param-name>configClass</param-name>
<param-value>demo.DemoConfig</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jfinal</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

接下来创建java文件:

创建DemoConfig并继承JFinalConfig,DemoConfig是主文件,运行这个文件启动项目,就像运行普通java文件main一样,同时运行之后如果修改其他代码,并不需要重启,框架会自动修改,直接刷新就可以看到修改后的内容。

这是初始的简单的demo:

package demo;
import com.jfinal.config.*;
public class DemoConfig extends JFinalConfig {
public void configConstant(Constants me) {
me.setDevMode(true);
}
public void configRoute(Routes me) {
me.add("/hello", HelloController.class);
}
public void configEngine(Engine me) {}
public void configPlugin(Plugins me) {}
public void configInterceptor(Interceptors me) {}
public void configHandler(Handlers me) {}
}

然后配置controller:

package demo;
import com.jfinal.core.Controller;
public class HelloController extends Controller {
public void index() {
renderText("Hello JFinal World.");
}
}

然后直接打开浏览器输入http://localhost/hello  就可以看到页面输出了  Hello JFinal World  。

这是最基本的使用的例子,下面是我的程序:

package demo;

import com.jfinal.config.*;

import com.jfinal.core.JFinal;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.c3p0.C3p0Plugin;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.template.Engine; import controller.StudentController;
import demo.model.Classes;
import demo.model.Student; public class DemoConfig extends JFinalConfig { public static void main(String[] args) {
JFinal.start("src/main/webapp", 80, "/", 5);
} public void configConstant(Constants me) {
me.setDevMode(true);
//此方法用来配置 JFinal 常量值,如开发模式常量 devMode 的配置,如下代码配置了 JFinal
//运行在开发模式:在开发模式下,JFinal 会对每次请求输出报告,如输出本次请求的 URL、Controller、Method
//以及请求所携带的参数。
} public void configRoute(Routes me) {
me.add("/", HelloController.class);
me.add("/test/mytest", HelloController.class,"test");
me.add("/student", StudentController.class);
//me.add("/classes", ClassesController.class);
} public void configEngine(Engine me) { } public void configPlugin(Plugins me) { // C3p0Plugin cp = new C3p0Plugin("jdbc:mysql://localhost/db_name",
// "userName", "password");
// me.add(cp); loadPropertyFile("a_little_config.txt");
DruidPlugin dp = new DruidPlugin(getProperty("jdbcUrl"),
getProperty("user"), getProperty("password"));
me.add(dp);
ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
me.add(arp);
arp.addMapping("student", "studentid", Student.class);
arp.addMapping("classes", "classesid", Classes.class); // 此方法用来配置JFinal的Plugin,如下代码配置了Druid数据库连接池插件与ActiveRecord
// 数据库访问插件。通过以下的配置,可以在应用中使用 ActiveRecord 非常方便地操作数据库。
} public void configInterceptor(Interceptors me) {
//me.add(new AuthInterceptor()); // 此方法用来配置 JFinal 的全局拦截器,全局拦截器将拦截所有 action 请求,除非使用
// @Clear 在 Controller 中清除,如下代码配置了名为 AuthInterceptor 的拦截器。
} public void configHandler(Handlers me) {
} }

这里面各个方法的简单说明都写在注释里了。

然后是controller:

这里虽然声明了service,但是并没有使用的,都是直接在controller方法里使用dao

package controller;

import java.util.List;
import java.util.Map; import com.alibaba.fastjson.JSONObject;
import com.jfinal.aop.Before;
import com.jfinal.core.Controller; import StudentInterceptor.StudentInterceptor;
import StudentValidator.StudentValidator;
import StudentValidator.StudentValidator2;
import demo.model.Student;
import service.StudentService; public class StudentController extends Controller { /**
* 获取studentid那里有多种方法,这个要和前台传参写法一致,Controller 提供了 getPara 系列方法,官网api里很详细 jfinal用的是原生态sql语句,简单,方便,setAttr("studentList", list);把结果集放到request范围里, jfinal也有直接获取表单里分装成对象的方法 getModel(Student.class);就是,和struts2一样,表单name对应上就可以了,非常方便 添加那里对于oracle用序列维护studentid student.set("studentid", "mysequence.nextval").save(); jfinal有多种返回方式,也可以返回json数据,render 系列方法,官网api里很详细
*/ static StudentService service = new StudentService(); @Before(StudentInterceptor.class)
public void index() {
List<Student> list = Student.dao.find("select * from student");
setAttr("studentList", list);
//注意下面路径的的前面如果带/则从根目录下开始找,也就是说 下代码 = render("/student/index.html");
render("index.html");
} public void add() {
render("add.html");
} public void test() {
List<Student> list = Student.dao.find("select * from student");
setAttr("studentList", list);
setAttr("student", list.get(0));
render("test.jsp");
} public void getlist() {
List<Student> list = Student.dao.find("select * from student");
JSONObject jo = new JSONObject();
jo.put("code", 0);
jo.put("msg", true);
jo.put("count",list.size());
jo.put("data", list);
renderJson(jo);
} public void layui() {
List<Student> list = Student.dao.find("select * from student");
setAttr("studentList", list);
render("index3.html");
} public void delete() {
// 获取表单域名为studentid的值
Student.dao.deleteById(getPara("studentid"));
forwardAction("/student");
} public void delete1() {
// 获取url请求中第一个值
Student.dao.deleteById(getParaToInt());
forwardAction("/student");
} public void update() {
Student student = getModel(Student.class);
student.update();
forwardAction("/student");
} public void get() {
Student student = Student.dao.findById(getPara("studentid"));
setAttr("student", student);
render("index2.html");
} public void get1() {
Student student = Student.dao.findById(getParaToInt());
setAttr("student", student);
render("index2.html");
} @Before(StudentValidator.class)
public void save() {
/**
* getModel用来接收页面表单域传递过来的model对象,表单域名称以”modelName.attrName”
http://www.jfinal.com
方式命名,getModel 使用的 attrName 必须与数据表字段名完全一样。
getBean 方法用于支持传统 Java Bean,包括支持使用 jfnal 生成器生成了 getter、setter 方法
的 Model,页面表单传参时使用与 setter 方法相一致的 attrName,而非数据表字段名。
getModel与getBean区别在于前者使用数表字段名而后者使用与setter方法一致的属性名进
行数据注入。建议优先使用 getBean 方法。
*/
//getBean(Student.class).save();
getModel(Student.class).save();
redirect("/student");
} @Before(StudentValidator2.class)
public void savebean() {
getBean(Student.class).save();
redirect("/student");
} }

同样的简单的说明也写在注释里了。

方法基本上都在这里了,下面是其他的一些配置:

这是实体类:

package demo.model;

import com.jfinal.plugin.activerecord.Model;

public class Student extends Model<Student> {
public static final Student dao = new Student(); /**
* ActiveRecord 是 jfinal 最核心的组成部分之一,通过 ActiveRecord 来操作数据库,将极大地减少代码量,极大地提升开发效率,配置在后面,我这里用的是Model,Model 是 ActiveRecord 中最重要的组件之一,它充当 MVC 模式中的 Model部分。
以上代码中的 User 通过继承 Model,便立即拥有的众多方便的操作数据库的方法。在 User 中声明的 dao 静态对象是为了方便查询操作而定义的,该对象并不是必须的。 基于ActiveRecord 的 Model 无需定义属性, 无需定义 getter、 setter方法,无需 XML 配置,无需 Annotation 配置,极大降低了代码量。Model常见方法见官方API。 JFinal还有 独创 Db + Record 模式,Db 类及其配套的 Record 类, 提供了在 Model 类之外更为丰富的数据库操作功能。使用 Db 与 Record 类时,无需对数据库表进行映射,Record 相当于一个通用的 Model。Db常见方法见官方API。
*/ }

StudentValidator:

package StudentValidator;

import com.jfinal.core.Controller;
import com.jfinal.validate.Validator; public class StudentValidator extends Validator { //在校验失败时才会调用
@Override
protected void handleError(Controller controller) {
controller.keepPara("student.studentname");//将提交的值再传回页面以便保持原先输入的值
controller.render("/add.html");
} @Override
protected void validate(Controller controller) {
//验证表单域name,返回信息key,返回信息value
validateRequiredString("student.studentname", "studentnameMsg",
"请输入学生名称!");
} }
package StudentValidator;

import com.jfinal.core.Controller;
import com.jfinal.validate.Validator; public class StudentValidator2 extends Validator { //在校验失败时才会调用
@Override
protected void handleError(Controller controller) {
controller.keepPara("studentname");//将提交的值再传回页面以便保持原先输入的值
controller.render("/add.html");
} @Override
protected void validate(Controller controller) {
//验证表单域name,返回信息key,返回信息value
validateRequiredString("studentname", "studentnameMsg",
"请输入学生名称!");
}
}

StudentInterceptor:

package StudentInterceptor;

import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation; public class StudentInterceptor implements Interceptor { public void intercept(Invocation ai) {
System.out.println("Before action invoking");
ai.invoke();
System.out.println("After action invoking");
}
}

然后是前台的显示页面:

关于前台页面,需要看一下文档第六章,JFinal模板引擎的内容,了解JFinal如何在前台显示,这是很重要的

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学生管理</title>
<script type="text/javascript" src="/jquery-1.12.4.min.js"></script>
</head>
<body>
<h1><a href="/student/jsp">学生管理</a></h1>
<a href="/student/layui">测试layui</a>
<a href="/student/test">编辑索引0</a><br>
<a href="/student/add">添加</a><br>
<form action="/student/get">
id:<input type="text" name="studentid">
<input type="submit" value="查询">
</form>
<a href="/student/delete">删除</a>
<form action="/student/delete">
id:<input type="text" name="studentid">
<input type="submit" value="删除">
</form> #for(x : [1..10])
#(x)
#end <table id="listtable" border="1">
<tbody>
<tr>
<th>id</th>
<th>姓名</th>
<th>性别</th>
<th>年龄</th>
<th>地址</th>
<th>邮箱</th>
<th>操作</th>
</tr>
#for(x : studentList)
<tr>
<td style="text-align:left;">#(x.studentid)</td>
<td style="text-align:left;">#(x.studentname)</td>
<td style="text-align:left;">#(x.sex)</td>
<td style="text-align:left;">#(x.age)</td>
<td style="text-align:left;">#(x.address)</td>
<td style="text-align:left;">#(x.email)</td>
<td style="text-align:left;">
&nbsp;&nbsp;<a href="/student/delete?studentid=#(x.studentid)">删除</a>
&nbsp;&nbsp;<a href="/student/delete1/#(x.studentid)">删除</a>
&nbsp;&nbsp;<a href="/student/get?studentid=#(x.studentid)">修改</a>
&nbsp;&nbsp;<a href="/student/get1/#(x.studentid)">修改1</a>
</td>
</tr>
#end
</tbody>
</table>
</body>
</html>

这就是页面效果,因为没有样式所以看起来比较粗狂,然后下面是用正常使用的layui,加上正常习惯的方法返回数据组成的:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>学生管理layui</title> <script type="text/javascript" src="/layui-v2.2.45/layui/layui.js"></script>
<link rel="stylesheet" href="/layui-v2.2.45/layui/css/layui.css" media="all">
</head>
<body>
<div style="margin: 0px; background-color: white; margin: 0 10px;">
<blockquote class="layui-elem-quote">
<a href="/student/add"><button type="button" id="usersAdd_btn"
class="layui-btn layui-btn-small">
<i class="fa fa-plus" aria-hidden="true"></i> 添加
</button></a>
<form class="layui-form" style="float: right;"
onsubmit="return false">
<div class="layui-form-item" style="margin: 0;">
<div class="demoTable">
搜索用户:
<div class="layui-inline">
<input class="layui-input" name="name" id="demoReload"
autocomplete="off">
</div>
<button class="layui-btn" style="transform: translateY(-3px);"
data-type="reload">搜索</button>
</div>
</div>
</form>
</blockquote>
</div> <table class="layui-table"
lay-data="{url:'/student/getlist',id:'idTest',height: 'full-60' ,}"
lay-filter="demo">
<thead>
<tr>
<th lay-data="{field:'studentid', width:'20%',}">id</th>
<th lay-data="{field:'studentname', width:'20%'}">姓名</th>
<th lay-data="{field:'sex', width:'20%'}">性别</th>
<th lay-data="{field:'age', width:'20%'}">年龄</th>
<th lay-data="{field:'address', width:'20%'}">地址</th>
<th lay-data="{fixed: 'right', width:'17%', align:'center', toolbar: '#barDemo1'}"></th>
</tr>
</thead>
</table>
<script type="text/html" id="barDemo1">
<a class="layui-btn layui-btn-xs" id="edit" lay-event="edit">修改</a>
<a class="layui-btn layui-btn-danger layui-btn-xs" lay-event="del">删除</a>
</script>
</body>
<script>
layui.use('table', function(){
var table = layui.table,
form = layui.form;; //监听表格复选框选择
table.on('checkbox(demo)', function(obj){
console.log(obj)
});
//监听工具条
table.on('tool(demo)', function(obj){
var data = obj.data;
if(obj.event === 'del'){
layer.confirm('真的删除用户吗', function(index){
$.ajax({
type:"post",
url:"/student/delete?studentid="+data.studentid,
dataType:"text",//返回的
success:function(returndata) {
table.reload("idTest");
},
error:function(msg) {
console.log(msg);
}
}); });
} else if(obj.event === 'edit'){ var index = layui.layer.open({
title : "修改",
type : 2,
area: ['380px', '80%'],
content : "/student/get?studentid="+data.studentid,
cancel: function(index, layero){
layer.close(index);
table.reload("idTest"); }
})
//改变窗口大小时,重置弹窗的高度,防止超出可视区域(如F12调出debug的操作)
$(window).resize(function(){
layui.layer.full(index);
})
layui.layer.full(index);
}else if(obj.event === 'detail'){
layer.confirm('确定通过该用户吗', function(index){
$.ajax({
type:"post",
url:"<%=basePath%>/sys/user/passuser",
data:{id:data.id},
//dataType:"text",//返回的
success:function(returndata) { layui.use('layer', function() {
layer.msg(returndata.msg);
});
table.reload('idTest', {
page: {
curr: 1 //重新从第 1 页开始
},
});
},
error:function(msg) {
console.log(msg);
}
}); });
}
}); var $ = layui.$, active = {
getCheckData: function(){ //获取选中数据
var checkStatus = table.checkStatus('idTest'),
data = checkStatus.data;
layer.alert(JSON.stringify(data)); }
,getCheckLength: function(){ //获取选中数目
var checkStatus = table.checkStatus('idTest')
,data = checkStatus.data;
layer.msg('选中了:'+ data.length + ' 个');
}
,isAll: function(){ //验证是否全选
var checkStatus = table.checkStatus('idTest');
layer.msg(checkStatus.isAll ? '全选': '未全选')
}
}; $('.demoTable .layui-btn').on('click', function(){
var type = $(this).data('type');
active[type] ? active[type].call(this) : '';
});
});
</script> </html>

这样感觉稍微好了一点,因为只是第一次使用,做一个测试,所以还是比较粗犷的。

然后需要注意的是这种方式的数据返回的问题:

    public void getlist() {
List<Student> list = Student.dao.find("select * from student");
JSONObject jo = new JSONObject();
jo.put("code", 0);
jo.put("msg", true);
jo.put("count",list.size());
jo.put("data", list);
renderJson(jo);
}

这是layui表格url指向的方法,在这里,需要将json数据用renderJson的方式返回。

然后需要 注意的是,我尝试过直接返回list集合,貌似方法是可行的,只是因为layui表格必须是以上格式才能接收数据所以没有显示到页面上,但是当我直接return jo的时候后台报错,这个问题只能等明天在学习并解决了。

以下是返回的render方法的几种使用方式:

然后需要注意的是方法的调用和传参:

如下两种方法和传参的方式:

            &nbsp;&nbsp;<a href="/student/delete?studentid=#(x.studentid)">删除</a>
&nbsp;&nbsp;<a href="/student/delete1/#(x.studentid)">删除</a>
&nbsp;&nbsp;<a href="/student/get?studentid=#(x.studentid)">修改</a>
&nbsp;&nbsp;<a href="/student/get1/#(x.studentid)">修改1</a>

下面是controller方法:

    public void delete() {
// 获取表单域名为studentid的值
Student.dao.deleteById(getPara("studentid"));
forwardAction("/student");
} public void delete1() {
// 获取url请求中第一个值
Student.dao.deleteById(getParaToInt());
forwardAction("/student");
} public void update() {
Student student = getModel(Student.class);
student.update();
forwardAction("/student");
} public void get() {
Student student = Student.dao.findById(getPara("studentid"));
setAttr("student", student);
render("index2.html");
} public void get1() {
Student student = Student.dao.findById(getParaToInt());
setAttr("student", student);
render("index2.html");
}

最后就是添加接受实体类的两种方式:

    @Before(StudentValidator.class)
public void save() {
/**
* getModel用来接收页面表单域传递过来的model对象,表单域名称以”modelName.attrName”
http://www.jfinal.com
方式命名,getModel 使用的 attrName 必须与数据表字段名完全一样。
getBean 方法用于支持传统 Java Bean,包括支持使用 jfnal 生成器生成了 getter、setter 方法
的 Model,页面表单传参时使用与 setter 方法相一致的 attrName,而非数据表字段名。
getModel与getBean区别在于前者使用数表字段名而后者使用与setter方法一致的属性名进
行数据注入。建议优先使用 getBean 方法。
*/
//getBean(Student.class).save();
getModel(Student.class).save();
redirect("/student");
} @Before(StudentValidator2.class)
public void savebean() {
getBean(Student.class).save();
redirect("/student");
}

其中第二中的getBean方式在我这个demo中,可能由于没有设置getset的原因,添加之后是只有生成了ID,没有其他数据的。

如果需要使用。下面是官方demo的写法:

package com.demo.common.model;

import com.demo.common.model.base.BaseBlog;

/**
* 本 demo 仅表达最为粗浅的 jfinal 用法,更为有价值的实用的企业级用法
* 详见 JFinal 俱乐部: http://jfinal.com/club
*
* Blog model.
* 数据库字段名建议使用驼峰命名规则,便于与 java 代码保持一致,如字段名: userId
*/
@SuppressWarnings("serial")
public class Blog extends BaseBlog<Blog> { }
package com.demo.common.model.base;

import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.IBean; /**
* Generated by JFinal, do not modify this file.
*/
@SuppressWarnings({"serial", "unchecked"})
public abstract class BaseBlog<M extends BaseBlog<M>> extends Model<M> implements IBean { public M setId(java.lang.Integer id) {
set("id", id);
return (M)this;
} public java.lang.Integer getId() {
return getInt("id");
} public M setTitle(java.lang.String title) {
set("title", title);
return (M)this;
} public java.lang.String getTitle() {
return getStr("title");
} public M setContent(java.lang.String content) {
set("content", content);
return (M)this;
} public java.lang.String getContent() {
return getStr("content");
}
}

JFinal极速开发框架使用笔记的更多相关文章

  1. JFinal极速开发框架使用笔记(三) 分析Model和ActiveRecord

    JFinal框架的一些新发现的用法: 在JFinal框架中,实体类并不需要设置属性,更不需要配置getset方法就可以很方便的操作数据库,如果需要设置或者获取属性,可以直接使用一下方式: User u ...

  2. JFinal极速开发框架使用笔记(二) 两个问题,一个发现

    最近给新人出了一个小测试,我也用JFinal框架做了一下,记录一下使用过程中遇到的坑和新学到的知识点 首先是遇到的两个小问题, 一个是用最新版的eclipse运行JFinal的maven项目报错,经过 ...

  3. JFinal极速开发框架使用笔记(四) _JFinalDemoGenerator实体类生成及映射自动化

    运行_JFinalDemoGenerator生成实体类和映射之前的项目结构: 运行之后: 生成和改变的文件: 实体类: package com.wazn.model; import com.wazn. ...

  4. JFinal 极速开发框架的优点和不足的地方

    http://www.360doc.com/content/16/1226/10/31460730_617731802.shtml http://www.sohu.com/a/122571150_46 ...

  5. jfinal框架教程-学习笔记

    jfinal框架教程-学习笔记 JFinal  是基于 Java  语言的极速  WEB  + ORM  开发框架,其核心设计目标是开发迅速.代码量少.学习简单.功能强大.轻量级.易扩展.Restfu ...

  6. Jfinal极速开发微信系列教程(一)--------------Jfinal_weixin demo的使用分析

    概述: Jfinal_weixin已经出了有好一段时间了!一直在关注当中......最近工作上有需要到这个东西,所以,话了两个小时来看看这个东西,看完demo以后,豁然开朗,原理微信和一般的web项目 ...

  7. MVC Bootstrap极速开发框架

    ASP.NET MVC Bootstrap极速开发框架 前言 每次新开发项目都要从头开始设计?有木有一个通用的快速开发框架?并且得是ASP.NET MVC  And Bootstrap?数据库不要手工 ...

  8. Rookey.Frame企业级极速开发框架

    项目详细介绍 Rookey.Frame是一套基于.NET MVC + easyui的企业级极速开发框架,支持简单逻辑模块零代码编程.支持工作流(BPM).支持二次开发,具有高扩展性.高复用性.高伸缩性 ...

  9. JFinal教程:JFinal极速开发企业实战百集JFinal视频教程发布

    课程名称:JFinal极速开发企业实战 课程长度:100课时 课程作者:小木(909854136) 课程地址:http://edu.csdn.net/course/detail/1968 官网网址:h ...

随机推荐

  1. TP框架Ajax如何使用

    ThinkPHP可以很好的支持AJAX请求,系统的\Think\Controller类提供了ajaxReturn方法用于AJAX调用后返回数据给客户端.并且支持JSON.JSONP.XML和EVAL四 ...

  2. PHP使用api的两种方法

    1.用file_get_contents()函数 $params = array('key' => '8d284859d04cfeeea6b0771f754adb49', 'location' ...

  3. 你绝不能错过的效率神器 —— Alfred

    文章首发于[博客园-陈树义],点击跳转到原文<你绝不能错过的效率神器 -- Alfred> Alfred 是 Mac 系统上一款专注于效率提升的著名应用,它能帮你快速打开网页.快速进行自定 ...

  4. c语言贪吃蛇详解1.画出地图

    c语言贪吃蛇详解-1.画出地图 前几天的实验室培训课后作业我布置了贪吃蛇,今天有时间就来写一下题解.我将分几步来教大家写一个贪吃蛇小游戏.由于大家c语言未学完,这个教程只涉及数组和函数等知识点. 首先 ...

  5. input required

    HTML <input> required 属性  HTML <input> 标签 实例 带有必填字段的 HTML 表单: <form action="demo ...

  6. 关于pipelineDB调用GetLocalStreamReaders的BUG

    如果想获取一个stream所有的reader,那么必须调用这个函数: Bitmapset *targets = GetLocalStreamReaders(relid); 如果stream下面没有re ...

  7. SSM框架开发web项目系列(三) MyBatis之resultMap及关联映射

    前言 在上篇MyBatis基础篇中我们独立使用MyBatis构建了一个简单的数据库访问程序,可以实现单表的基本增删改查等操作,通过该实例我们可以初步了解MyBatis操作数据库需要的一些组成部分(配置 ...

  8. java多线程编程核心技术——第二章

    第一节synchronized同步方法目录 1.1方法内的变量为线程安全的 1.2实例变量非线程安全 1.3多个对象多个锁 1.4synchronized方法与锁对象 1.5脏读 1.6synchro ...

  9. 初识AOP与动态代理

    AOP AOP是指在jvm运行时, 动态将代码切入到指定位置. OOP是一个维度上写代码, AOP是把他切开来, 变成立体的. 这样的好处是: 业务逻辑跟辅助逻辑分离, 例如日志打印, 性能监控, 安 ...

  10. tyvj4877 组合数

    1.组合数 (zero.cpp/c/pas) 时间限制:1s 内存限制:256MB [问题描述] 从m个不同元素中,任取n(n≤m)个元素并成一组,叫做从m个不同元素中取出n个元素的一个组合:从m个不 ...