Beetl学习总结(4)——Web集成

来源:互联网 发布:高中信息技术编程解答 编辑:程序博客网 时间:2024/06/02 21:00

4.1. Web提供的全局变量

Web集成模块向模板提供web标准的变量,做如下说明

  • request 中的所有attribute.在模板中可以直接通过attribute name 来引用,如在controller层 request.setAttribute("user",user),则在模板中可以直接用${user.name} .

  • session 提供了session会话,模板通过session["name"],或者session.name 引用session里的变量

  • request 标准的HTTPSerlvetRequest,可以在模板里引用request属性(getter),如${request.requestURL}。

  • parameter 用户读取用户提交的参数。如${parameter.userId} (仅仅2.2.7以上版本支持)

  • ctxPath Web应用ContextPath

  • servlet 是WebVariable的实例,包含了HTTPSession,HTTPSerlvetRequest,HTTPSerlvetResponse.三个属性,模板中可以通过request.response,session 来引用,如 ${serlvet.request.requestURL};

  • 所有的GroupTemplate的共享变量

  • pageCtx是一个内置方法 ,仅仅在web开发中,用于设置一个变量,然后可以在页面渲染过程中,调用此api获取,如pageCtx("title","用户添加页面"),在其后任何地方,可以pageCtx("title") 获取该变量。(仅仅2.2.7以上版本支持)

你可以在模板任何地方访问这些变量

如果你需要扩展更多属性,你也可以配置beetl.properties配置文件的WEBAPP_EXT属性,实现WebRenderExt接口,在渲染模板之前增加自己的扩展,如:

12
RESOURCE.root=/WEB-INF/viewsWEBAPP_EXT = com.park.oss.util.GlobalExt
 1 2 3 4 5 6 7 8 910
public class GlobalExt implements WebRenderExt{        static long version = System.currentTimeMillis();        @Override        public void modify(Template template, GroupTemplate arg1, HttpServletRequest arg2, HttpServletResponse arg3) {                //js,css 的版本编号                template.binding("sysVersion",version);        }}

这样,每次在模板里都可以访问变量sysVersion了,不需要再controller里设置,或者通过servlet filter来设置

4.2. 集成技术开发指南

Beetl默认提供了WebRender用于帮助web集成开发,所有内置的集成均基于此方法。如果你认为Beetl内置的各个web框架集成功能不够,你可以继承此类,或者参考此类源码重新写,其代码如下

  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
package org.beetl.ext.web;import java.io.IOException;import java.io.OutputStream;import java.io.Writer;import java.util.Enumeration;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import org.beetl.core.GroupTemplate;import org.beetl.core.Template;import org.beetl.core.exception.BeetlException;/** *  通常web渲染的类,将request变量赋值给模板,同时赋值的还有session,request,ctxPath *  其他框架可以继承此类做更多的定制 * @author joelli * */public class WebRender{        GroupTemplate gt = null;        public WebRender(GroupTemplate gt)        {                this.gt = gt;        }        /**         * @param key 模板资源id         * @param request         * @param response         * @param args 其他参数,将会传给modifyTemplate方法         */        public void render(String key, HttpServletRequest request, HttpServletResponse response, Object... args)        {                Writer writer = null;                OutputStream os = null;                try                {                        //                      response.setContentType(contentType);                        Template template = gt.getTemplate(key);                        Enumeration<String> attrs = request.getAttributeNames();                        while (attrs.hasMoreElements())                        {                                String attrName = attrs.nextElement();                                template.binding(attrName, request.getAttribute(attrName));                        }                        WebVariable webVariable = new WebVariable();                        webVariable.setRequest(request);                        webVariable.setResponse(response);                        webVariable.setSession(request.getSession());                        template.binding("session", new SessionWrapper(webVariable.getSession()));                        template.binding("servlet", webVariable);                        template.binding("request", request);                        template.binding("ctxPath", request.getContextPath());                        modifyTemplate(template, key, request, response, args);                        String strWebAppExt = gt.getConf().getWebAppExt();                        if(strWebAppExt!=null){                                WebRenderExt renderExt = this.getWebRenderExt(strWebAppExt);                                renderExt.modify(template, gt, request, response);                        }                        if (gt.getConf().isDirectByteOutput())                        {                                os = response.getOutputStream();                                template.renderTo(os);                        }                        else                        {                                writer = response.getWriter();                                template.renderTo(writer);                        }                }                catch (IOException e)                {                        handleClientError(e);                }                catch (BeetlException e)                {                        handleBeetlException(e);                }                finally                {                        try                        {                                if (writer != null)                                        writer.flush();                                if (os != null)                                {                                        os.flush();                                }                        }                        catch (IOException e)                        {                                handleClientError(e);                        }                }        }        /**         * 可以添加更多的绑定         * @param template 模板         * @param key 模板的资源id         * @param request         * @param response         * @param args  调用render的时候传的参数         */        protected void modifyTemplate(Template template, String key, HttpServletRequest request,                        HttpServletResponse response, Object... args)        {        }        /**处理客户端抛出的IO异常         * @param ex         */        protected void handleClientError(IOException ex)        {                //do nothing        }        /**处理客户端抛出的IO异常         * @param ex         */        protected void handleBeetlException(BeetlException ex)        {                throw ex;        }}

4.3. Serlvet集成

只需要在Servlet代码里引用ServletGroupTemplate就能集成Beetl,他提供了一个render(String child, HttpServletRequest request, HttpServletResponse response)方法。例子如下:

 1 2 3 4 5 6 7 8 910
protected void doGet(HttpServletRequest request,                        HttpServletResponse response) throws ServletException, IOException {                response.setContentType("text/html;charset=UTF-8");                //模板直接访问users                request.setAttribute("users",service.getUsers());                ServletGroupTemplate.instance().render("/index.html", request, response);        }

ServletGroupTemplate同其他web集成一样,将读取配置文件来配置,如果需要通过代码配置,可以在Serlvet listener里 ServletGroupTemplate.instance().getGroupTemplate()方法获取GroupTemplate

4.4. SpringMVC集成

需要做如下配置即可

123456
<bean id="beetlConfig" class="org.beetl.ext.spring.BeetlGroupUtilConfiguration" init-method="init"/><bean id="viewResolver" class="org.beetl.ext.spring.BeetlSpringViewResolver">        <property name="contentType" value="text/html;charset=UTF-8"/></bean>

同其他集成方式一样,模板的配置将放在beetl.properties中。

如果想获取GroupTemplate,可以调用如下代码

123
BeetlGroupUtilConfiguration config = (BeetlGroupUtilConfiguration) this.getApplicationContext().getBean(                                "beetlConfig");GroupTemplate group = config.getGroupTemplate();

Controller代码如下:

1234567
@RequestMapping(value = "/", method = RequestMethod.GET)public ModelAndView index(HttpServletRequest req) {        ModelAndView view = new ModelAndView("/index");        //total 是模板的全局变量,可以直接访问        view.addObject("total",service.getCount());  return view;}

http://git.oschina.net/xiandafu/springbeetlsql 有完整例子

4.5. SpringMVC集成高级

spring集成还允许注册被spring容器管理的Function,Tag等,也还允许配置多个视图解析器等功能

 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435
<bean name="beetlConfig" class="org.beetl.ext.spring.BeetlGroupUtilConfiguration" init-method="init">        <property name="configFileResource" value="/WEB-INF/beetl.properties"/>        <property name="functions">             <map>               <entry key="testFunction" value-ref="testFunction"/>            </map>        </property>        <property name="functionPackages">             <map>               <entry key="fp" value-ref="testFunctionPackage"/>            </map>        </property>        <property name="tagFactorys">             <map>               <entry key="html.output" value-ref="testTagFactory"/>               <entry key="html.output2" value-ref="testTagFactory2"/>            </map>        </property></bean><bean name="testTagFactory" class="org.beetl.ext.spring.SpringBeanTagFactory">     <property name="name" value="testTag"/></bean><bean name="testTagFactory2" class="org.beetl.ext.spring.SpringBeanTagFactory">     <property name="name" value="testTag2"/></bean><bean name="beetlViewResolver" class="org.beetl.ext.spring.BeetlSpringViewResolver">        <property name="config" ref="beetlConfig"/>        <property name="contentType" value="text/html;charset=UTF-8"/></bean>

如上图所示,BeetlGroupUtilConfiguration有很多属性,列举如下

  • configFileResource 属性指定了配置文件所在路径,如果不指定,则默认在classpath下

  • functions 指定了被spring容器管理的function,key为注册的方法名,value-ref 指定的bean的名称

  • functionPackages,指定了被spring容器管理的functionPackage,key为注册的方法包名,value-ref 指定的bean的名称

  • tagFactorys ,注册tag类,key是tag类的名称,value-ref指向一个org.beetl.ext.spring.SpringBeanTagFactory实例,该子类是一个Spring管理的Bean。属性name对应的bean就是tag类。需要注意,由于Tag是有状态的,因此,必须申明Scope为 "prototype"。如代码:

1234
@Service@Scope("prototype")public class TestTag extends Tag {}
  • typeFormats: 同functions,参数是 Map<Class<?>, Format>,其中key为类型Class

  • formats:同functions,参数是 Map<String, Format>,其中key为格式化函数名

  • virtualClassAttributes 同functions,参数Map<Class<?>, VirtualClassAttribute>,其中key为类型Class

  • virtualAttributeEvals ,类型为List<VirtualAttributeEval>

  • resourceLoader,资源加载器 ,值是 实现ResourceLoader的一个Bean

  • errorHandler ,错误处理,值是实现ErrorHandler的一个Bean

  • sharedVars,同functions,类型是Map<String, Object>,可以在此设置共享变量

  • configProperties,类型是Properties,可以覆盖配置文件的某些属性

如下配置,指定了三个视图解析器,一个用于beetl页面渲染,一个用于cms,采用了beetl技术,另外一个一些遗留的页面采用jsp

 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041424344454647484950
<bean name="beetlConfig" class="org.beetl.ext.spring.BeetlGroupUtilConfiguration" init-method="init">        <property name="configFileResource" value="/WEB-INF/beetl.properties"/></bean><bean name="cmsbeetlConfig" class="org.beetl.ext.spring.BeetlGroupUtilConfiguration" init-method="init">        <property name="configFileResource" value="/WEB-INF/cms-beetl.properties"/></bean><!-- Beetl视图解析器1 --><bean name="beetlViewResolver" class="org.beetl.ext.spring.BeetlSpringViewResolver">        <!-- 多视图解析器,需要设置viewNames和order -->        <property name="viewNames">                <list>                        <value>/template/**</value>                </list>        </property>        <property name="suffix" value=".btl"/>        <property name="contentType" value="text/html;charset=UTF-8"/>        <property name="order" value="0"/>        <!-- 多GroupTemplate,需要指定使用的bean -->        <property name="config" ref="beetlConfig"/></bean><!-- Beetl视图解析器2 --><bean name="cmsBeetlViewResolver" class="org.beetl.ext.spring.BeetlSpringViewResolver">        <!-- 多视图解析器,需要设置viewNames和order -->        <property name="viewNames">                <list>                        <value>/cmstemplate/**</value>                </list>        </property>        <property name="contentType" value="text/html;charset=UTF-8"/>        <property name="order" value="1"/>        <!-- 多GroupTemplate,需要指定使用的bean -->        <property name="config" ref="cmsbeetlConfig"/></bean><!-- JSP视图解析器 --><bean name="JSPViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">        <!-- 注意JSP的这个视图解析器order必须在最后 -->        <property name="order" value="256"/>        <!-- beetl配置不支持前缀,这不同于jsp 和 freemaker -->        <property name="prefix" value="/WEB-INF/"/>        <property name="suffix" value=".jsp"/>        <property name="contentType" value="text/html;charset=UTF-8"/></bean>

Beetl视图解析器属性同spring自带的视图解析器一样,支持contentType,order,prefix,suffix等属性。

注意视图解析器里属性viewNames,这个用于判断controller返回的path到底应该交给哪个视图解析器来做。

  • 以/template开头的是beetlViewResolver来渲染。

  • 以/cmstemplate是交给cmsBeetlViewResolver渲染。

  • 如果都没有匹配上,则是jsp渲染

如果你想更改此规则,你只能增加canHandle方法指定你的逻辑了。详情参考org.springframework.web.servlet.view.UrlBasedViewResolver.canHandle

对于仅仅需要redirect和forward的那些请求,需要加上相应的前缀

  • 以"redirect:"为前缀时:表示重定向,不产生BeetlView渲染模版,而直接通过Servlet的机制返回重定向响应.redirect:前缀后面的内容为重定向地址,可以采用相对地址(相对当前url),绝对地址(完整的url),如果采用/开头的地址,会自动的在前面接上当前Web应用的contextPath,即contextPath为test的Web应用中使用redirect:/admin/login.html 实际重定向地址为 /test/admin/login.html

  • 以"forward:"为前缀时:表示转发,不产生BeetlView渲染模版。而是直接通过Servlet的机制转发请求(关于转发和重定向的区别,请自行查看Servlet API) forward:前缀后面的内容为转发地址,一般都是以/开头相对于当前Web应用的根目录

其他集成需要注意的事项:

  • spring集成,请不要使用spring的 前缀配置,改用beetl的RESOURCE.ROOT 配置,否则include,layout会找不到模板

4.6. Spring Boot集成

Spring Boot 通过java config来配置 beetl需要的BeetlGroupUtilConfiguration,和 BeetlSpringViewResolver,参考代码如下

 1 2 3 4 5 6 7 8 91011121314151617181920212223242526272829
@Configurationpublic class BeetlConf {        @Value("${beetl.templatesPath}") String templatesPath;//模板跟目录        @Bean(initMethod = "init", name = "beetlConfig")    public BeetlGroupUtilConfiguration getBeetlGroupUtilConfiguration() {        BeetlGroupUtilConfiguration beetlGroupUtilConfiguration = new BeetlGroupUtilConfiguration();        try {            ClasspathResourceLoader cploder = new ClasspathResourceLoader(BeetlConf.class.getClassLoader(),templatesPath);            beetlGroupUtilConfiguration.setResourceLoader(cploder);            return beetlGroupUtilConfiguration;        } catch (Exception e) {            throw new RuntimeException(e);        }    }    @Bean(name = "beetlViewResolver")    public BeetlSpringViewResolver getBeetlSpringViewResolver(@Qualifier("beetlConfig") BeetlGroupUtilConfiguration beetlGroupUtilConfiguration) {        BeetlSpringViewResolver beetlSpringViewResolver = new BeetlSpringViewResolver();        beetlSpringViewResolver.setContentType("text/html;charset=UTF-8");        beetlSpringViewResolver.setOrder(0);        beetlSpringViewResolver.setConfig(beetlGroupUtilConfiguration);        return beetlSpringViewResolver;    } }

spring boot集成需要注意的是要添加spring-devtools.properties文件,并配置如下选项

12
restart.include.beetl=/beetl-xxx.jarrestart.include.beetlsql=/beetlsql-xxx..jar

spring-devtools.properties 为spring boot的配置文件,位于META-INF目录下

4.7. Jodd集成

需要配置web.xml,将所有请求交给jodd处理,参考:http://jodd.org/doc/madvoc/setup.html

 1 2 3 4 5 6 7 8 91011121314151617
<filter>        <filter-name>madvoc</filter-name>        <filter-class>jodd.madvoc.MadvocServletFilter</filter-class>        <init-param>                        <param-name>madvoc.webapp</param-name>                        <param-value>test.MyWebApplication</param-value>          </init-param>    <init-param>                <param-name>madvoc.configurator</param-name>                <param-value>test.MyAutomagicMadvocConfigurator</param-value>        </init-param></filter><filter-mapping>        <filter-name>madvoc</filter-name>        <url-pattern>/*</url-pattern></filter-mapping>

MyWebApplication 和 MyAutomagicMadvocConfigurator 需要自己参照如下例子写一个,前者用来设置beetl作为视图渲染,后者配置Jodd不要扫描beetl struts集成里引用的struts类

123456789
public class MyAutomagicMadvocConfigurator extends AutomagicMadvocConfigurator {        public MyAutomagicMadvocConfigurator(){                super();                //不扫描beetl 里jar文件里的action和result,否则,会扫描StrutsResultSupport不相干的class                this.rulesJars.exclude("**/*beetl*.jar");        }}
12345678
public class MyWebApplication  extends WebApplication{     @Override     protected void init(MadvocConfig madvocConfig, ServletContext servletContext) {                 //设置默认         madvocConfig.setDefaultActionResult(BeetlActionResult.class);     } }

最后,可以写Action了,浏览器输入/index.html,jodd将执行world方法,并渲染ok.html模板。如果你想配置GroupTemplate,正如其他集成框架一样,只需要写一个beetl.properties 即可。

 1 2 3 4 5 6 7 8 9101112
@MadvocActionpublic class IndexAction {     @Out     String value;     @Action("/index.html")     public String world() {         value = "Hello World!";         return "/ok.html";     }}

https://git.oschina.net/xiandafu/beetl-jodd-sample 有完整例子

4.8. JFinal集成

Beetl提供 JFinal 集成,使用BeetlRenderFactory ,通过如下注册即可使用beetl模板引擎

 1 2 3 4 5 6 7 8 91011
import org.beetl.ext.jfinal.BeetlRenderFactorypublic class DemoConfig extends JFinalConfig{        public void configConstant(Constants me)        {                me.setMainRenderFactory(new BeetlRenderFactory());                // 获取GroupTemplate ,可以设置共享变量等操作                GroupTemplate groupTemplate = BeetlRenderFactory.groupTemplate ;}

业务逻辑代码:

123456789
        public void modify(){                int artId = getParaToInt(0, -1);                setAttr("title", "修改文章");                List<Cate> cateLists = Cate.getAllCate();                //模板里访问cateLists,atr,                setAttr("cateLists", cateLists);                setAttr("art", Article.dao.findById(artId));                render("/modify.html");        }

BeetlRenderFactory 默认使用FileResourceLoader ,其根目录位于WebRoot目录下,如果你需要修改到别的目录,可以设置配置文件,如

1
RESOURCE.root= /WEB-INF/template/

https://git.oschina.net/xiandafu/beetl-jfinal-sample 有完整例子,采用jfinal+beetl写的一个博客系统

4.9. Nutz集成

Nutz集成提供了 BeetlViewMaker ,实现了 ViewMaker方法,如下代码

 1 2 3 4 5 6 7 8 91011
        @At("/ctx")        @Ok("beetl:ctx.btl")        public Context withContext() {                Context ctx = Lang.context();                Pager pager = dao.createPager(1, 20);                pager.setRecordCount(dao.count(UserProfile.class));                List<UserProfile> list = dao.query(UserProfile.class, null, pager);                ctx.set("pager", pager);                ctx.set("list", list);                return ctx;        }
 1 2 3 4 5 6 7 8 9101112131415
<html><head><title>Beetl&Nutz</title></head><body><p>总共 ${list.~size}<p/><%for(user in list){%><p>hello,${user.nickname};<p/><%}%><p>当前页${pager.pageNumber},总共${pager.pageCount}页<p/></body></html>

需要注意的是,如果使用了nutz的obj(http://www.nutzam.com/core/mvc/view.html),则需要在模板顶部申明obj是动态对象,如

123456
<%directive dynamic obj%>${obj.user.title}${obj.user.name}

4.10. Struts2集成

需要在struts2配置文件里添加result-types做如下配置

 1 2 3 4 5 6 7 8 91011121314151617
<package name="default" namespace="/" extends="struts-default">.......<result-types>        <result-type name="beetl"                                class="org.beetl.ext.struts2.Struts2BeetlActionResult" default="true" >                                <param name="contentType">text/html; charset=UTF-8</param>        </result-type></result-types><action name="HelloWorld" class="com.beetl.struts.HelloWorld">    <result>/hello.html</result></action><action name="Ajax" class="com.beetl.struts.AjaxHtml">        <result>/table.html#table</result></action>........</package>

该类会根据struts配置文件获取模板,如上例的hello.html,并将formbean的属性,以及request属性作为全局变量传递给模板

https://git.oschina.net/xiandafu/beetl-struts2-sample 有完整例子

郑重申明

鉴于struts2有安全漏洞,而官方补丁打法很消极,所以请谨慎使用Struts2,Beetl的安全性已经通过在线体验和多个使用Beetl的网站得以体现 一旦你的struts2网站被攻破,请先确定是否是struts2 的问题

4.11. 直接Web中运行Beetl模板

对于web应用来说,必须通过controller才能渲染模板,beetl也可以写完模板后,在未完成controller情况下,直接渲染模板 此方法既可以作为通常的全栈式开发人员使用,也可以用于前端人员单独开发模板用。

步骤如下:

  • 配置监听器,监听器指定对*.btl的请求进行监听(假定模板名字都是以btl.结尾)。

  • 实现监听器,该监听器继承父类 org.beetl.ext.web.SimpleCrossFilter,实现protected abstract GroupTemplate getGroupTemplate()方法。依据不同的集成方式,比如你的环境是Servlet,则只需要调用ServletGroupTemplate.instance().getGroupTemplate(),如果是Jfinal,需要调用BeetlRenderFactory.groupTemplate等

  • SimpleCrossFilter 提供一些有用的方法,可以帮助你定制一些特性,可以参考源码了解

  • 置完成后,对于要测试的模板,可以新建一个对应的伪模型文件,比如要测试模板WebRoot/user/userList.html,可以新建立WebRoot/values/user/userList.html.var 。 values是监听器默认的伪模型的根目录

  • 编辑伪模型文件,对应于userList.html需要的全局变量,userList.html.var可以申明这些些变量

123
var proudct = {id:1,name:'测试产品',pic:'xxxx.jpg'};var userList = [{id:2,name:'用户一'}];var session= {admin:{id:1,name:'admin'}};
  • 通过浏览器直接访问http://ip:port/user/userList.html,监听器会预先执行userList.html.var,并将返回值作为模板的全局变量,传给userList.html

  • 可以将一些公共的变量放到WebRoot/values/common.var里(比如上面代码的session). 监听器会先执行common.var,然后再执行userList.html.var

直接访问模板前提是使用了伪模型,这与实际的项目采用的模型并不一致,因此当模板采用伪模型验证后,需要重启web应用,才能使用真正的模型去测试,否则,模板引擎会报错,这是因为beetl默认的FastRuntimeEngine会根据模型优化模板,对同一个模板不同的模型会报错,除非采用DefaultTemplateEngine 或者页面申明类型变量是动态的。

4.12. 整合ajax的局部渲染技术

越来越多web网站依赖于ajax,如table的翻页,流行方式是浏览器发出ajax请求,后台处理后返回一个json,浏览器端将json数据拆开,拼成一条一条的行数据,然后生成dom节点,追加到表格里。 作为另外一种可选技术,beetl支持局部渲染技术,允许后台处理返回的是一个完成的html片段,这样,前端浏览器可以直接将这个html片段追加到表格里。在我做的性能测试里,俩种方式性能差别不大(http://beetlajax.oschina.mopaas.com/)

比如模板index.html有很多动态内容,有动态生成的菜单,有右侧的top10,也有核心区域的表格,大概内容如下

 1 2 3 4 5 6 7 8 9101112131415161718192021
<#menu/><#top10> ....</#top10><div id="table-container" ><%//ajax片段开始#ajax userTable: {%><table>        <tr><td width=100>id</td><td width=100>姓名</td></tr>        <%for(user in users){%>        <tr><td>${user.id}</td><td>${user.name}</td></tr>        <%}%></table>当前页面<span id="current">${page!1}</span><span style="width:20px"></span><a href="#"><span  class="page">next</span></a> <a href="#" ><span  class="page">pre</span></a><%//ajax片段结尾}%>

#ajax 用于告诉告诉模板引擎,此处是个局部渲染标记,标记为"userTable",对于正常渲染视图"index.html"页面,#ajax标记没什么用处,table仍能得到正常渲染。如果渲染的视图是index.html#userTable,则模板只会渲染#ajax标记得模板片段,其他部分将忽略。关于完整例子,可以参考http://beetlajax.oschina.mopaas.com/

后台代码如下:

1
render("/index.html#userTable");

ajax 片段渲染也支持默认情况下不渲染,仅仅做为一个片段使用,如一个页面有许多后台交互操作,并返回相应的html片段,可以将这些html片段也放到同一个模板里,使用ajax norender,表示渲染整个模板的时候默认并不需要渲染此ajax片段

 1 2 3 4 5 6 7 8 9101112131415161718192021
<%<html></html>#ajax norender success: {%><div id="success"> 操作成功</div><%}%>#ajax norender failure: {%><div id="failure"> 操作失败</div><%}%>

这样,此页面默认情况下并没有输出success,和 failure片段

注意,Ajax片段本质上是从模版的ajax标记处开始渲染,因此,ajax需要的变量在模版里也必须是全局变量,如果你只是个局部变量,beetl会报出找不到变量,即使你binding了这个变量,beetl也认为这个是局部变量,如:

 1 2 3 4 5 6 7 8 91011
" ><%var tableData = paras.table;#ajax userTable: {for(user in tableData);%><%//ajax片段结尾}%>

变量tableData是从paras里获取的,是个临时变量,因此就算你在后台binding了一个tableData,beetl 也不能识别。在渲染ajax片段的时候会报变量tableData找不到。改正的办法只能是让tableData全局变量。

返回Json好还是返回html片段好?这个难以定论.

  • 从后台性能看,将模型序列化成json性能会比渲染模板性能更好,但是,json还需要前端重新解析生成最终html dom节点,这可能会延迟最终数据的现实效果。而返回的html片段就是已经生成好的dom

  • 从网络传入来看,json无疑更好的,html片段会有额外的html标记,css属性,以及有可能的js调用。传入流量有可能增加50%到100%。但是,对于web应用类,这些额外数据,并不算多。

  • 从开发效率来讲,返回html片段的开发效率更高一些,因为渲染在后台操作,可以随心所欲的用模板语言来渲染,来取得后台数据,完成复杂渲染,而json就比较困难,可以说所有的json lib都没有完美的解决办法。

  • 从用户体验上来讲,Beetl 采用ajax标记,混合了传统的模板渲染和ajax加载。用户进入页面即能看到数据,而经典的ajax json方式还需要异步加载,显示延迟。另外如果页面同时有多个ajax加载,则会对服务器造成很大的压力。

  • 关心服务器cpu消耗? 模板方式消耗更多的cpu,json方式则少点。但是俩者差距并不大。而且更多的web网站面临的情况是有富余的服务器CPU能力

  • 关心客户端CPU消耗? 过多的js无疑是客户端运行慢的主要原因。如果采用经典的json方式,返回的json数据必然还需要经过js的计算和渲染。会影响客户机器cpu。

4.13. 在页面输出错误提示信息

2.2.3版本以后,新增加org.beetl.ext.web.WebErrorHandler,可以在web开发的时候在页面输出提示信息,在产品模式下载后台输出提示信息(通过配置属性ESOURCE.autoCheck= true来认为是开发模式),仅仅需要配置如下:

1
ERROR_HANDLER = org.beetl.ext.web.WebErrorHandler
0 0
原创粉丝点击