约定参考：

```xml
//资源路径约定（不用配置；也不能配置）
resources/app.yml（ 或 app.properties ） #为应用配置文件

resources/static/     #为静态文件根目录（v2.2.10 后支持）
resources/templates/  #为视图模板文件根目录（v2.2.10 后支持）

//调试模式约定：(调试模式下，可以热更新模板)
启动参数添加：--debug=1
```


### 1、支持多种视图模板引擎，可同时共用


| 插件 | 适配的渲染器 | 默认视图后缀名 | 备注  |
| -------- | -------- |  -------- |   -------- | 
| [solon-view-freemarker](/article/100)    |  FreemarkerRender |  .ftl     |  solon-web 快捷组合包里，引用了此包 | 
| [solon-view-jsp](/article/101)               |  JspRender             |  .jsp     |     | 
| [solon-view-velocity](/article/102)        |  VelocityRender       |  .vm     |     | 
| [solon-view-thymeleaf](/article/103)     |  ThymeleafRender     |   .html     |     | 
| [solon-view-enjoy](/article/104)           |  EnjoyRender           |  .shtm     |     | 
| [solon-view-beetl](/article/105)           |  BeetlRender            |  .htm     |     | 



以 freemaerker 视图为例，helloworld.ftl

```html
<!doctype html>
<html>
<head>
    <meta charset="UTF-8">
    <title>${title}</title>
</head>
<body>
<div>
     ${message}
</div>
</body>
</html>
```

控制器

```java
@Controller
public class HelloworldController {
    @Mapping("/helloworld")
    public Object helloworld(){
        ModelAndView vm = new ModelAndView("helloworld.ftl"); //注意，带后缀

        vm.put("title","demo-app");
        vm.put("message","hello world!");

        return vm;
    }
}
```

### 2、视图后缀与模板引擎的映射配置

默认不要修改，不要添加。需要改哪条，加哪条。

```yaml
solon.view.prefix: "resources/templates/" #默认为资源目录，使用体外目录时以"file:"开头（例："file:/data/demo/"）

#默认约定的配置（不需要配置，除非要修改）
solon.view.mapping.htm: BeetlRender #简写
solon.view.mapping.shtm: EnjoyRender
solon.view.mapping.ftl: FreemarkerRender
solon.view.mapping.jsp: JspRender
solon.view.mapping.html: ThymeleafRender
solon.view.mapping.vm: VelocityRender

#添加自义定映射时，需要写全类名
solon.view.mapping.vm: org.noear.solon.view.velocity.VelocityRender #全名（一般用简写）
```


### 3、可以写控制器基类，加些公共的内容


```java
public class BaseController {
    public ModelAndView view(String viewUri){
        ModelAndView vm = new ModelAndView("helloworld.ftl"); //注意，带后缀

        vm.put("context", Context.current());
        vm.put("title","demo-app");

        return vm;
    }
    
    public ModelAndView view(String viewUri, Map<String,Object> model){
        ModelAndView vm = new ModelAndView("helloworld.ftl"); //注意，带后缀

        vm.put("context", Context.current());
        vm.put("title","demo-app");
        vm.putAll(model);

        return vm;
    }
}

@Controller
public class HelloworldController {
    @Mapping("/helloworld")
    public Object helloworld(){
        //注意，带后缀  //支持链式写法
        return view("helloworld.ftl").put("message","hello world!");
    }
}
```

### 4、在模板中使用请求上下文对象接口

使用之前，需要手动把它 put 到 model里（见上面第2节的代码）。以 freemaerker 视图为例：


```html
<div>${context.sessionAsLong("user.id")}</div>
```

关于 Context 的接口，参考[《认识请求上下文（Context）》](/article/216)


### 5、在模板中使用认证标签

以 freemaerker 视图为例：


```html
<@authPermissions name="user:del">
我有user:del权限
</@authPermissions>

<@authRoles name="admin">
我有admin角色
</@authRoles>
```


### 6、在模板中使用国际化接口

以 freemaerker 视图为例：

```html
<div>
i18n::${i18n["login.title"]}
i18n::${i18n.get("login.title")}
i18n::${i18n.getAndFormat("login.title",12,"a")}
</div>
```

具体内容可参考 国际化的章节。



