JFinal之Controller和Active Record

一、Action

        Controller是JFinal核心类之一,是定义和组织Action的地点和方式,一个Controller可以包含多个Action,并且是线程安全的。,

     1.Action的定义

        Action 是请求的最小单位,Action 方法必须在 Controller 中定义,且必须是 public 可见性,除此之外 Action可以有返回值,返回值可在拦截器中通过invocation.getReturnValue() 获取到,以便进行render控制。

     2.@NotAction注解

        但不需要使controller中的public方法不成为一个action,则可以使用@NotAction。该注解通常用于引入BaseContoller的中间Contorller

    3.控制器超类的路由映射

        如果需要超类中的方法也被映射为Action,则按如下配置即可:

    public void configRoute(Routes me) {
        me.setMappingSuperClass(true);
    }

    4.Action参数注入

        Action 参数注入是指用action方法传入参数

    public class ProjectController extends Controller {
        public void index(Project project) {
           project.save();
           render("index.html");
        }
    }

        注意:如果 action 形参是一个 model 或者 bean,原先通过 getBean(User.class, "") 获取时第二个参数为空字符串或null,那么与之等价的形参注入只需要用一下 @Para("") 注解即可: public void action(@Para("")User user) { …. }。使用 Action 参数注入功能需要在开发工具中配置打开编译参数保留住方法参数名称。

二、get/getPara系列方法

       Controller提供了getPara系列方法用来从请求中获取参数。getPara系列方法分为两种类型。第一种类型为第一个形参为String的getPara系列方法。该系列方法是对HttpServletRequest.getParameter(String name)的封装,这类方法都是转调了HttpServletRequest.getParameter(String name)。第二种类型为第一个形参为int或无形参的getPara系列方法。该系列方法是去获取urlPara中所带的参数值。getParaMap与getParaNames分别对应HttpServletRequest的getParameterMap与getParameterNames。

        记忆技巧:第一个参数为String类型的将获取表单或者url中问号挂参的域值。第一个参数为int或无参数的将获取urlPara中的参数值。

        在Jfinal 3.6中getPara()、getToInt()、setAttr()三种方法分别替换为get()、getInt()、set()

        在Jfinal 3.5中增加了getRawData()方法,可以很方便地从 http 请求 body 中获取 String 型的数据(json 或 XML 数据),例如:

    String json = getRawData();
    User user = FastJson.getJson().parse(json, User.class);


三、getModel和getBean方法

getModel与getBean区别在于前者使用数据库表字段名而后者使用与setter方法一致的属性名进行数据注入。例子:

// 在页面表单中采用modelName.attrName形式为作为表单域的name
<form action="/blog/save" method="post">
  <input name="blog.title" type="text">
  <input name="blog.content" type="text">
  <input value="提交" type="submit">
</form>
public class BlogController extends Controller {
  public void save() {
    // 页面的modelName正好是Blog类名的首字母小写
    Blog blog = getModel(Blog.class);
    // 如果表单域的名称为 "otherName.title"可加上一个参数来获取
    blog = getModel(Blog.class, "otherName");
  }
}

四、render方法--访问路径的配置

      1.render(String view)方法

        将对 view 所指向的模板进行渲染,view 参数最终指向的模板文件规则如下:String template = baseViewPath + viewPath + view

public void configRoute(Routes me) {
   // baseViewPath 为 "/_view",该 Routes 对象之下映射的所有 Controller 都将取这个值
   me.setBaseViewPath("/_view");
   
   // basePath 为第三个参数 "/index"
   me.add("/", IndexController.class, "/index");
   
   // 第三个参数省略时, basePath 取第一个参数的值 : "/project"
   me.add("/project", ProjectController.class);
}
public class IndexController extends Controller {
   public void demo() {
     // 模板指向 : "/_view/index/abc.html"
     render("abc.html");
   }
}

         当需要打破 baseViewPath 与 viewPath 这两个参数的限制时,view 参数以 "/" 打头即可

     2.render方法配置模板引擎

public void configConstant(Constants me) {
  me.setViewType(ViewType.JFINAL_TEMPLATE);
}

      render(String view) 将根据 configConstant(Constants me) 中配置的 me.setViewType(ViewType) 方法选择一种模板引进渲染模板文件。以上配置将选择 jfinal 内置的 enjoy 模板引擎渲染模板,该配置是默认值,在使用时无需配置。注意该配置仅仅针对 Controller.render(String view) 方法,其它 render 系方法完全不受影响。

五、renderFile文件下载和getFile文件上传

      1. renderFile 方法使用一个 baseDownloadPath 参数为基础路径去寻找文件。最终下载文件总是:baseDownloadPath + renderFile 传入的参数。

      2. 配置 baseDownloadPath

          baseDownloadPath 可以根据需要在 configConstant(Constants me) 中自由配置,例如:me.setBaseDownloadPath("files");此时的baseDownloadPath 为src/main/webapp/files。也可以将其设为绝对路径,例如:me.setBaseDownloadPath("D:/download");

      3.renderFile(File file) 方法也可以直接使用 File 参数去获取下载文件,指向任意地点的文件,例如:

    String file = "D:/my-project/share/files/jfinal-all.zip";
    renderFile(new File(file));

     4.重命名下载文件:renderFile("老文件名.txt", "新文件名.txt");

     5.使用getFile时需要先添加如下依赖:

    <dependency>
        <groupId>com.jfinal</groupId>
        <artifactId>cos</artifactId>
        <version>2019.8</version>
    </dependency>

        特别注意:如果客户端请求为multipart request(form表单使用了enctype="multipart/form-data"),那么必须先调用getFile系列方法才能使getPara系列方法正常工作,因为multipart request需要通过getFile系列方法解析请求体中的数据,包括参数。同样的道理Interceptor、Validator中也需要先调用getFile。文件默认上传至项目根路径下的upload子路径之下,该路径称为文件上传基础路径。可以JFinalConfig.configConstant(Constants me)方法中通过me.setBaseUploadPath(baseUploadPath) 设置文件上传基础路径,该路径参数接受以”/”打头或者以windows磁盘盘符打头的绝对路径

六、renderQrCode 二维码生成

       1.renderQrCode 用法

    // 二维码携带的数据
    String data = "weixin://wxpay/bizpayurl?appid=xx&mch_id=xx......";
    // 渲染二维码图片,长度与宽度为 200 像素
    renderQrCode(data, 200, 200,'M');

        上述代码中的M为该二维码的纠错级别为M,该纠错参数可以在二维码图片被遮挡或者被损坏一部分时仍然可以正确读取其中的内容,纠错级别从高到低可以指定为:'H'、'Q'、'M'、'L',其纠错率分别为:30%、25%、15%、7%。 不指定该参数值默认为 'L'。

        使用renderQrCode需要在pom.xml中添加如下依赖:

    <dependency>
        <groupId>com.google.zxing</groupId>
        <artifactId>javase</artifactId>
        <version>3.2.1</version>
    </dependency>

七.session操作

       通过 setSessionAttr(key, value) 可以向 session 中存放数据,getSessionAttr(key) 可以从 session 中读取数据。还可以通过 getSession()得到 session 对象从而使用全面的session API。

八.keep方法

    1.keepPara方法,keepPara 一般用在 Validator 或者拦截器之中。若不指定表单域的类型,则都将转换成 String 类型,所以,如果表单域的类型必须要保持住的话可以使用如下的方式:

    // 指定 keep 后的类型为 Date
    keepPara(Date.class, "createAt");
    // 指定 keep 后的类型为 Integer
    keepPara(Integer.class, "age");

        如果age 被 keepPara() 后为 String 型,那么 age.toInt() 会将其转化成 Integer 型。

    2.keepModel 可以将以 modelName 前缀的表单域保持住内容与类型

        keepBean 与 keepModel 的功能相似,只不过 keepBean 针对的是传统 java bean,而不是 Model。当然,如果 Model 使用生成器生成了 setter 方法,使用 keepBean 也可以。

九、ActiveRecord

      在JFinal中使用 ActiveRecord 来操作数据库。ActiveRecord 模式的核心是:一个 Model 对象唯一对应数据库表中的一条记录,而对应关系依靠的是数据库表的主键值。因此,ActiveRecord 模式要求数据库表必须要有主键。当数据库表没有主键时,只能使用 Db + Record 模式来操作数据库。

     1.ActiveRecordPlugin--配置数据库资源以及数据表和model的映射

         ActiveRecord是作为JFinal的Plugin而存在的,所以使用时需要在JFinalConfig中配置ActiveRecordPlugin。

        Plugin配置示例代码:

public class DemoConfig extends JFinalConfig {
  public void configPlugin(Plugins me) {
//druid数据源插件
  DruidPlugin dp = new DruidPlugin("jdbc:mysql://localhost/db_name", "userName", "password");
    me.add(dp);
    
//ActiveRecrod支持插件
    ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
//add Mapping(String tableName, Class<? extends Model> modelClass>)方法建立了数据库表名到Model的映射关系。
//user表的主键名为默认为 "id",如果主键名称为 "user_id" 则需要手动指定
   // arp.addMapping("user", User.class);
   // arp.addMapping("article", "article_id", Article.class);
   _MappingKit.mapping(arp);
   me.add(arp);
  }
}

     2.Generator与JavaBean

        ActiveRecord 模块的 com.jfinal.plugin.activerecord.generator 包下,提供了一个 Generator 工具类,可自动生成 Model、BaseModel、MappingKit、DataDictionary 四类文件。其中MappingKit用于生成table到Model的映射关系,并且会生成主键/复合主键的配置。 生成后的 Model 与 java bean 合体,立即拥有了 getter、setter 方法,使之遵守传统的 java bean 规范。使用生成器通常只需配置Generator的四个参数即可,以下是具体使用示例:

// base model 所使用的包名
String baseModelPkg = "model.base";
// base model 文件保存路径
String baseModelDir = PathKit.getWebRootPath() + "/../src/model/base";
 
// model 所使用的包名
String modelPkg = "model";
// model 文件保存路径
String modelDir = baseModelDir + "/..";
 
Generator gernerator = new Generator(dataSource, baseModelPkg, baseModelDir, modelPkg, modelDir);
// 在 getter、setter 方法上生成字段备注内容
gernerator.setGenerateRemarks(true);
gernerator.generate();












评论区

JFinal

2019-09-02 21:46

分享内容似曾相识,好像是文档中的内容

704442497

2019-09-03 16:16

这样分享是为了什么?是自己的记忆方式吗

ZANYM

2019-09-04 09:12

chcode

2019-09-04 09:53

复制粘贴 我不会看文档吗

快乐的蹦豆子

2019-09-09 19:55

为了爱情