基于Web2.0的Web剪切Portlet

这个Portlet采用Web2.0技术实现,其原因在于,如果读取目标HTML页面是同步载入的话,当页面含有大量的此类Portlet的时候,Portal页面必须要等到所有的Web剪切Portlet都载入后才能够显示出来,当目标页面所在的服务器在Internet的时候,Portal页面的载入过程将会变得非常缓慢。采用的Web2.0的异步载入的方式,将能够很大程度的提高页面载入速度。
下面描述的是这个Portlet的实现思路:
1. 首先显示一个展示有“载入内容”的HTML页面,Portal页面打开时首先显示该页面;
2. 通过XMLHttpRequest对象请求服务器端的Servlet将目标HTML页面读出来;
3. 解析HTML页面,将要截取的HTML区段解析出来;
4. 通过正则表达式将HTML区段中的相关资源的相对引用转换为绝对引用;
5. 根据需要,将HTML区段中的CSS定义替换为新的CSS定义。
6. 对Portlet进行局部刷新,显示截取内容。

<%@page language="java" contentType="text/html; charset=GB18030"
pageEncoding="GB18030" session="false"%>
<%@taglib uri="http://java.sun.com/portlet" prefix="portlet"%>
<%@ page import="javax.portlet.PortletPreferences,com.ibm.webclipping.Constants" %>
<portlet:defineObjects />
<div id="content" align="center" style="width:100%;height:100%">
<script name="script" language="JavaScript">{
if (window.XMLHttpRequest){
xmlObj = new XMLHttpRequest();
}else if (window.ActiveXObject){
xmlObj = new ActiveXObject("Microsoft.XMLHTTP");
}
xmlObj.onreadystatechange = handleResponse;

<% PortletPreferences preference = renderRequest.getPreferences(); %>
var params = <%= "\"" + Constants.KEY_URL + '=' + preference.getValue(Constants.KEY_URL, "") + '&' +
Constants.KEY_CHARTSET + '=' + preference.getValue(Constants.KEY_CHARTSET, "") + '&' +
Constants.KEY_BEGINTAG + '=' + preference.getValue(Constants.KEY_BEGINTAG, "") + '&' +
Constants.KEY_ENDTAG + '=' + preference.getValue(Constants.KEY_ENDTAG, "") + '&' +
Constants.KEY_REGULATOR + '=' + preference.getValue(Constants.KEY_REGULATOR, "") + '&' +
Constants.KEY_REPLACEMENT + '=' + preference.getValue(Constants.KEY_REPLACEMENT, "") + "\""%>;
xmlObj.open("POST",'<%= renderResponse.encodeURL(renderRequest.getContextPath()+"/ReadContentServlet")%>',true);
xmlObj.setRequestHeader("content-type", "application/x-www-form-urlencoded");
xmlObj.setRequestHeader("content-length", params.length);
xmlObj.send(params);
}
function handleResponse() {
if (xmlObj.readyState == 4){//xmlObj loaded
if (xmlObj.status == 200){
var datas = xmlObj.responseText;
var obj = document.getElementById("content");
obj.innerHTML = datas;
}
}
}
</script>
<img src='<%= renderResponse.encodeURL(renderRequest.getContextPath()+"/images/loading.gif") %>'/>
</div>


Constants.KEY_URL:目标页面的URL
Constants.KEY_CHARTSET:目标页面的编码
Constants.KEY_BEGINTAG:目标页面要截取内容的开始html内容
Constants.KEY_ENDTAG:目标页面要截取内容的结束html内容
Constants.KEY_REGULATOR:匹配正则表达式
Constants.KEY_REPLACEMENT:匹配内容的替换表达式


通过HTTP请求将目标HTML内容读出来,为了达到这个目标,我们采用java.net.URL对象来实现,通过这个对象,我们可以把指定地址的HTML内容读出到一个字符串中,为下一步的处理做准备。

//读取strURL中的HTML内容
URL url = new URL(strURL);
StringBuffer buffer = new StringBuffer();
String strLine = "";
//从URL中读取内容,
InputStreamReader reader = new InputStreamReader(url.openStream(),charsetName);
BufferedReader br = new BufferedReader(reader);
while ((strLine = br.readLine()) != null) {
buffer.append(strLine.toLowerCase());
buffer.append("\r\n");
}
br.close();


这段代码中有两个需要注意的地方,第一是变量charsetName,这个变量必须与目标HTML页面的编码一致,否则会有乱码出现,尤其是中文环境下。第二个重点是buffer.append("\r\n"),当我们从目标HTML页面读取内容到一个字符串中的时候,我们必须要保证目标HTML的内容原原本本的读入到字符串中。由于我们在后面的步骤中要对其进行切割和替换,所以这一点尤其重要。

第三步就是要将读出的HTML内容进行截取,获得要剪切的那部分页面内容。我们通过字符串的indexOf方法来实现。

int beginIndex = buffer.indexOf(beginTag,0);
if(-1 == beginIndex){
result = "未找到起始字符串";
}
//System.out.println("beginIndex is " + beginIndex);
int endIndex = buffer.indexOf(endTag,0);
if(-1 == endIndex){
result = "未找到结束字符串";
}
buffer.substring(beginIndex, endIndex);


下面,我们就要通过正则表达式对截取的HTML内容进行替换。在进行内容截取的时候,页面上的资源(例如,图片,超链接,js等)都是采用的相对地址,这里需要将这些相对地址替换为绝对地址,当展示在Portal上不会出现空连接的错误。同时还可以根据需要对class进行替换,使其与整个门户的风格一致。下面的这段代码通过循环一次性的对HTML中的内容进行替换。

//获取beginTag和endTag之间的内容,并对其进行匹配
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(buffer.substring(beginIndex, endIndex));
StringBuffer replacementResult = new StringBuffer();
//分解reg和replacement的区段
// regToken是通过”|”进行分割的正则表达式集合
StringTokenizer regToken = new StringTokenizer(reg,"|");
// replacementToken是通过”|”进行分割的替换内容集合,与正则表达式集合一一对应
StringTokenizer replacementToken = new StringTokenizer(replacement,"|");
//对匹配出的内容依次进行替换
while(matcher.find()){
String matched = matcher.group();
//循环判断应该替换哪个内容
while(regToken.hasMoreElements()){
Pattern subPattern = Pattern.compile(regToken.nextToken());
Matcher subMatcher = subPattern.matcher(matched);
if(subMatcher.matches()){
matcher.appendReplacement(replacementResult, replacementToken.nextToken());
break;
}
else
//如果匹配不成功,将replacementToken的指针向下移动一级
replacementToken.nextToken();
}
//初始化两个Token,重新开始比对
regToken = new StringTokenizer(reg,"|");
replacementToken = new StringTokenizer(replacement,"|");
}
matcher.appendTail(replacementResult);
result = replacementResult.toString();
}


上述方式有一定的局限性,但是在大多数场合能够应用,可以通过定制实现更强大的能力。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值