關於在freemarker模板中遍歷數據模型List的經驗

       本文采用簡單的servlet做爲後臺處理數據的工具,前臺使用freemarker的ftl模板做爲輸出工具,簡單說明怎樣將封裝有實體類對象的List集合注入到ftl模板中而且成功的在遍歷顯示出來,以前在網上找了不少這方面的資料,可是都沒有解決這個問題,因此本身就從頭認真的研讀的一番freemarker的API文檔,閱讀了相關的類和接口的功能說明,終於找到了突破口,在這裏寫出來供和我有相同經歷的孩紙(初學者)使用:html

首先看我寫的domain實體類:News.javajava

public class News {
private Integer news_id;
private String news_title;
private String news_publish_date;
private String news_url;
public Integer getNews_id() {
return news_id;
}
public void setNews_id(Integer news_id) {
this.news_id = news_id;
}app

.....如下的set和get方法都省略..dom

接着看我寫的newsSql.xml文件中查詢全部News對象的並返回List<News>或者Map<String,News>型數據的配置信息:eclipse

<typeAlias alias="news" type="cn.domain.News"/>
<resultMap class="news" id="getMap">
<result property="news_id" column="news_id"/>
<result property="news_title" column="news_title"/>
<result property="news_publish_date" column="news_publish_date"/>
<result property="news_url" column="news_url"/>
</resultMap>
<select id="queryAllNews" resultMap="getMap">
select *from news
</select>函數

下面是本身第一次寫的NewsListServlet代碼:工具

public class NewsListServlet extends HttpServlet {oop

private static final long serialVersionUID = 1L;
private NewsDao dao;
private Configuration cfg;this

public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
dao = new NewsDao();
List<News> newslist = dao.getAllNews();
Map<String,List<News>> map=new HashMap<String, List<News>>();
map.put("newslist",newslist);
cfg = new Configuration();
cfg.setServletContextForTemplateLoading(this.getServletContext(),"/ftl");
Template template = cfg.getTemplate("newsList.ftl");
try {
template.process(map,response.getWriter());
} catch (TemplateException e) {
e.printStackTrace();
}url

}}

下面是newslist.ftl模板代碼:

<html>
<div style="background-color:#AABBCD">
<table style="border:0px">
<tr style="border:0px" align="center">
<td colspan="4">如下是今天的主要新聞</td>
</tr>
<tr align="center">
<td>編號</td>
<td>標題</td>
<td>發佈時間</td>
<td>操做</td>
</tr>
<#if newslist?exists >
<#list newslist as news>
<tr align="center">
<td>${news.news_id}</td>
<td align="left">${news.news_title}</td>
<td>${news.news_publish_date}</td>
<td><a href="${news.news_url}">查看詳情</a></td>
</tr>
</#list></#if>
</table>
</div>
</html>

可是運行時會出現下面的異常信息,着實讓人很頭疼:

freemarker.template.TemplateModelException: Don't know how to present an object of this type to a template: cn.domain.News
at freemarker.template.SimpleObjectWrapper.handleUnknownType(SimpleObjectWrapper.java:139)
at freemarker.template.SimpleObjectWrapper.wrap(SimpleObjectWrapper.java:116)
at freemarker.template.WrappingTemplateModel.wrap(WrappingTemplateModel.java:131)
at freemarker.template.SimpleSequence.get(SimpleSequence.java:197)
at freemarker.template.IteratorBlock$Context.runLoop(IteratorBlock.java:163)
at freemarker.template.Environment.visit(Environment.java:316)
at freemarker.template.IteratorBlock.accept(IteratorBlock.java:94)
at freemarker.template.Environment.visit(Environment.java:180)
at freemarker.template.ConditionalBlock.accept(ConditionalBlock.java:78)
at freemarker.template.Environment.visit(Environment.java:180)
at freemarker.template.MixedContent.accept(MixedContent.java:91)
at freemarker.template.Environment.visit(Environment.java:180)
at freemarker.template.Environment.process(Environment.java:166)
at freemarker.template.Template.process(Template.java:238)

這裏我聲明一下,數據的封裝和傳遞絕對沒有問題,這個異常信息的關鍵是:

Don't know how to present an object of this type to a template: cn.domain.News

沒法引述新聞類對象到模版,也就是說模板不認識list裏面的數據是News對象,因此沒法經過news.news_title來訪問屬性對象

到這裏我想你們明白我說的是什麼意思了吧,經過查詢API文檔,能夠容易看到Template.process()函數有兩種形式,一個是含有兩個參數的,而另外一個則含有三個參數,他們分別爲:

void freemarker.template. Template.process( Object dataModel, Writer out) throws TemplateException, IOException
void freemarker.template. Template.process( Object dataModel, Writer out, ObjectWrapper wrapper) throws TemplateException, IOException
其實兩者沒什麼大的區別,只是第二個方法比第一個多增長了一個 ObjectWrapper wrapper參數而已,那個增長這個參數有什麼做用呢?
答案是:第一個方法中默認了 ObjectWrapper wrapper參數是ObjectWrapper.SIMPLE_WRAPPER型的,可是在咱們的狀況下須要另外一種類型,也即:ObjectWrapper.BEANS_WRAPPER,觀看英文單詞也理解是什麼意思了吧,再看看官方的文檔說明:
An ObjectWrapper that exposes the object methods and JavaBeans properties as hash elements, and has custom handling for Java Map-s, ResourceBundle-s, etc. It doesn't treat org.w3c.dom.Node-s and Jython objects specially, however.
 Object wrapper that uses SimpleXXX wrappers only. It behaves like the DEFAULT_WRAPPER, but for objects that it does not know how to wrap as a SimpleXXX it throws an exception. It makes no use of reflection-based exposure of anything, which may makes it a good candidate for security-restricted applications. 
因此錯誤的修改就本簡單了:

Map<String,List<News>> map=new HashMap<String, List<News>>();
map.put("newslist",newslist);
cfg = new Configuration();

cfg.setServletContextForTemplateLoading(this.getServletContext(),"/ftl");
Template template = cfg.getTemplate("newsList.ftl");
try {
template.process(map,response.getWriter(),ObjectWrapper.BEANS_WRAPPER);
} catch (TemplateException e) {
e.printStackTrace();
}

如下是改正後的運行效果:

如下是今天的主要新聞
編號 標題 發佈時間 操做
1 MH-17航班又在烏克蘭和俄羅斯邊境出事了 2014-07-15 22:19:45.0 查看詳情
2 中國和巴西簽定了不少外貿上的關係文件 2014-07-17 21:23:45.0 查看詳情
3 全國大學生軟件大賽初賽成績公佈了,三人組合團隊表現很出色 2014-07-14 15:18:22.0 查看詳情
4 山東交通學院未來要成爲一所名副其實的大學真的很困難 2012-06-11 13:18:49.0 查看詳情

呵呵,本身的一點總結,大手們不要見笑。。。

相關文章
相關標籤/搜索