就现在Web框架铺天盖地的局面下,Spring依然还是那么有吸引力,毕竟好的产品总不会被人们忽略的。因最在Portal环境下开发,一点小小经验和大家分享,如有不解,尽可联系本人哦!
首先我们应该有的环境就不多说了,之前写过一篇文章是关于在Liferay下Spring Mvc的开发。本文就是基于这个环境,大体说下:
1、运行的Portal环境为Liferay Portal tomcat 6.0.5;
2、自己的项目是使用Spring MVC搭建的。
其他不多说,在上述环境下使用Ajax返回自己想要的数据是本文需要说明的问题;
一、客户端JS
此处客户端JS,即需要发送请求的一段采用的是Jquery 1.4.2,当然你可以使用你自己喜欢的Ajax方式。在Portal模式下最关键的地方是发送Ajax请求的地址,本人开始也很疑惑,但是Liferay的wiki还是给了咱很大的帮助。地址的取法如下:
<portlet:renderURL var="loadDisTagByParentIdUrl"
windowState="<%= LiferayWindowState.EXCLUSIVE.toString()%>">
<portlet:param name="action" value="loadDisTagByParentId"></portlet:param>
</portlet:renderURL>
最关键的地方是要设置windowState属性,看看属性值就应该明白,当这种状态时,portlet默认的Response是不会输出任何内容的,只是为了在服务端执行一个动作而已。此处采用actionUrl效果一样,注意发送请求是Jquery.ajax 参数类型 type 要设置为 post。客户端就是如此简单,其他的事情就到服务端再说。
二、服务端
首先看看Spring的MVC模式:
其实还是很简单的,对于开发者来讲只需要关心两点,第一是将请求转到Controller,这个过程是配置handler完成,第二是将输出交由Resolver完成,无论是Servlet还是Portlet环境都一样,这点Spring做的太好了,这点是由配置viewResolver来完成。明白了要做的事情,不难看出,要想请求输出能够按照你自己的想法来输出,最关键是要搞定Resolver。
1) AjaxViewResolver
我们可以自定义一个自己的Resolver,用来处理我们自己的Ajax请求,大致代码片段如下:
public class AjaxViewResolver extends AbstractCachingViewResolver {
public static final String AJAX_PREFIX = "ajax_";
protected String ajaxPrefix = AJAX_PREFIX;
private View ajaxView;
@Override
protected View loadView(String viewName, Locale locale) throws Exception {
View view = null;
if (viewName.startsWith(this.ajaxPrefix)) {
view = ajaxView;
}
return view;
}
public String getAjaxPrefix() {
return ajaxPrefix;
}
public void setAjaxPrefix(String ajaxPrefix) {
this.ajaxPrefix = ajaxPrefix;
}
public View getAjaxView() {
return ajaxView;
}
public void setAjaxView(View ajaxView) {
this.ajaxView = ajaxView;
}
}
此类的作用是将一个特殊的前最View交由AjaxView来处理,功能就如此简单,此处留意我们的View前缀;
2) AjaxView
来个自定的View处理器来处理有AjaxViewResolver转过来的请求,此类代码片段如下:、
public class AjaxView extends AbstractView {
public static final String JSONCONFIG_ATTRIBUTE = AjaxView.class.getName()+ ".JsonConfig";
private static final String DEFAULT_AJAX_CONTENT_TYPE = "text/plain; charset=UTF-8";
@Override
public String getContentType() {
String orgiContentType = super.getContentType();
if (StringUtils.isEmpty(orgiContentType))
orgiContentType = DEFAULT_AJAX_CONTENT_TYPE;
return orgiContentType;
}
@Override
public void setContentType(String contentType) {
super.setContentType(contentType);
}
// TODO filter and log
@Override
protected void renderMergedOutputModel(Map<String, Object> map,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
if (map == null || map.isEmpty()) {
JSONObject.fromObject("{}").write(response.getWriter());
return;
}
Object result = null;
for (Map.Entry<String, Object> entry : map.entrySet()) {
result = entry.getValue();
break;
}
JSON json = this.createJson(request, result);
json.write(response.getWriter());
}
private JSON createJson(HttpServletRequest request, Object obj) {
JsonConfig jsonConfig = (JsonConfig) request.getAttribute(JSONCONFIG_ATTRIBUTE);
if (jsonConfig == null)
return JSONSerializer.toJSON(obj);
else
return JSONSerializer.toJSON(obj, jsonConfig);
}
}
此类也很简单,注意两点,应为我们Ajax通常返回Json数据,所以此类就返回Json,其他的你可以自己重载了,第二注意重载的方法renderMergedOutputModel。方法最后一段所写出的东西就是最终返回到客户端的东西了。json.write(response.getWriter());也很简单,继续。
3)MyController
Controller 是Spring最最普通的Controller,正如前面地址所写,我们要执行一个action=loadDisTagByParentId的渲染,所以在Controller中有了如下的方法:
@RenderMapping(params = "action=loadDisTagByParentId")
public String loadDisTagByParentId(
@RequestParam(value = "tagId", required = false) Long tagId,
ModelMap map, PortletRequest req, PortletResponse response) {
List<Tag> tags = tagSvc.getTagsByParentId(tagId);
List<TreeNode> nodes = new ArrayList<TreeNode>();
for (Tag tag : tags) {
TreeNode node = new TreeNode();
node.setData(tag.getName());
JSONObject jsonAttrs = new JSONObject();
jsonAttrs.put("id", "tagid_" + tag.getId());
node.setAttr(jsonAttrs);
node.setState("closed");
nodes.add(node);
}
map.clear();
map.addAttribute("tags", nodes);
return AjaxViewResolver.AJAX_PREFIX;
}
此方法没什么特殊,唯一不同的是注意了,方法返回的View是 AjaxViewResolver.AJAX_PREFIX,即在AjaxViewResolver中指定的视图前缀,此时就明白了,当执行完此方法之后,就交由AjaxView去处理了。此方法中我们可以准备一下我们要放回到客户端的数据。依然放在ModelMap中,在AjaxView中可以通过Map取出来。是不是很简单呢。
到此我们客户端发送的请求已经经过我们的Resolver和AjaxView处理完毕,当然我们要感谢Liferay给了我们一个很好的模式,这个模式就是Portal默认不输出任何数据。返回到客户端的数据你可以通过自定义AjaxView来达到各种格式的效果。再次不再衍生。
三、总结下好处
1、在使用这种模式下的好处是不依赖任何Ajax框架,你可以使用最普通的XMLHttpRequest来发送请求,只需将发送请求的地址给对即可;
2、不跑出Portlet之外,此点和DWR+SPRING在Portlet模式有所不同,Dwr是通过一个单独的Servlet来处理他的Ajax请求。
3、原生的地址,无需构建其他地址。
4、Spring注入毫不影响,我们依然使用的是Spring的Controller方法,方法签名依然可以保持为Spring原有的模式,参数依然可以注入;
5、标准的Spring配置,无需其他文件的配置,如web,dwr.xml等。
也许你在使用Portlet,也许你在使用Liferay,希望此文能给你帮助,顶吧!谢谢!
- 大小: 51.2 KB
分享到:
相关推荐
使用 Maven 的 Liferay Spring Portlet MVC 项目模板。 Liferay EE 6.2.10.11 (GA1, SP710) Java 1.7 小门户 2.0 弹簧框架 4.1.5 基于注解的控制器配置 用法 $ git clone ...
spring portletMVC
liferay-spring-mvc-freemarker-portlet-archetype 这是用于创建 Liferay Spring MVC Freemarker portlet 的 maven 原型。 由于 Liferay 不正式支持这种类型的 portlet,因此当前不存在原型。 这个原型修正了这一点...
liferay portlet 开发的例子介绍
自己研究出来的spring-portlet的一个war包,放在liferay里面直接可以运行,下次再把hibernate加进来,我花了两天的代价,希望大家能理解这个10分,呵呵
可供参考的liferay开发的portlet示例工程,学习参考的简单示例
liferay portlet例子 liferay portlet例子
Liferay5.2.3的样例,通过war.bat打包后发布到相应的liferay环境即可。 另外,需要配置context,tomcat中的代码如下: </Context>
Liferay-Portlet-SDK 5.2.3操作说明.ppt
Liferay 的 Control-Panel、Portlet DTD 5.2 和 MVC Portlet。
Liferay跨页面Portlet之间的调用与数据传递,Portlet之间的通信方法有多种,比如PortletSession,Public Render Parameter,Portlet event等。但是这些方法使用起来都很复杂,像Public Render Parameter和event等,...
详解portlet技术,是帮助你学习进步的好助手哦。快来下载吧
liferay 使用struts2 结合 eclipse IDE 进行portlet开发环境的搭建,以及基本开发实例。
liferay_使用struts2开发portlet
一个Liferay Soy Portlet使用web service进行可视化数据的实例。
Liferay porta 清理不需要的Portlet 代码
liferay-portlet-development
liferay portlet demo
里面有四个小型的liferay portal mvc实例,所需要的jar文件大家可以在eclipse里面新建一个portlet项目,再将里面的实例代码拷贝进去即可运行
liferay_4_portlet