webx是一个开源的web框架,主页地址:http://www.openwebx.org/。这里我们主要说下使用http协议对网络中任意资源进行装载,来增强webx资源装载的功能。
用webx官网的mvn命令,生成tutorial1项目,里面webx的pom如下:
...
<webx-version>3.2.4</webx-version>
...
<dependency>
<groupId>com.alibaba.citrus</groupId>
<artifactId>citrus-webx-all</artifactId>
</dependency>
...
这个版本里,webx的resourceLoader有2种扩展:
[res-loaders:webapp-loader /]:通过servletContext.getResource(resourceName)来获取资源。
[res-loaders:classpath-loader /]:通过classLoader.getResource(resourceName)来获取资源。
[res-loaders:super-loader/]:通过resource.xml里配置的资源别名,结合配置的资源加载器,来进行资源加载。这种是在前面2种的基础之上。
基于springExt,这里扩展点是res-loaders,捐献是webapp-loader,classpath-loader和super-loader。
新增一个http-loader,即[res-loaders:http-loader/],具体的捐献实现和配置在后面会再进行介绍,。
HttpResourceLoader简单类实现:
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import javax.servlet.ServletContext;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.runtime.RuntimeConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.context.WebApplicationContext;
import com.alibaba.citrus.service.resource.Resource;
import com.alibaba.citrus.service.resource.ResourceLoader;
import com.alibaba.citrus.service.resource.ResourceLoaderContext;
import com.alibaba.citrus.service.resource.ResourceLoadingOption;
import com.alibaba.citrus.service.resource.ResourceLoadingService;
import com.alibaba.citrus.service.resource.support.InputStreamResource;
import com.alibaba.citrus.service.template.TemplateService;
import com.alibaba.citrus.service.velocity.impl.VelocityEngineImpl;
import com.alibaba.citrus.service.velocity.impl.VelocityRuntimeInstance;
import static org.springframework.web.context.WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE;
/**
*
* @author yankai913@gmail.com
* @date 2016年4月11日
*/
public class HttpResourceLoader implements ResourceLoader, ServletContextAware,
ApplicationListener<ContextRefreshedEvent> {
private static final Logger logger = LoggerFactory.getLogger(HttpResourceLoader.class);
String resourceRemoteHost = "http://localhost:6666";
String vmEncoding = "UTF-8";
String[] additionalPathArr = new String[] { "", "/common" };
ApplicationContext applicationContext;
ServletContext servletContext;
@Override
public void init(ResourceLoadingService resourceLoadingService) {
}
@Override
public Resource getResource(ResourceLoaderContext context, Set<ResourceLoadingOption> options) {
String resourceName = context.getResourceName();
try {
for (String additionalPath : additionalPathArr) {
String remoteFileURL = this.resourceRemoteHost + additionalPath + resourceName;
HttpUtils.HttpResult httpRequest =
HttpUtils.httpGet(remoteFileURL, null, null, vmEncoding, 3000);
if (httpRequest.code == HttpURLConnection.HTTP_OK) {
String htmlText = httpRequest.content;
wrapHtmlContent(resourceName, htmlText);
ByteArrayInputStream bais = new ByteArrayInputStream(htmlText.getBytes(vmEncoding));
InputStreamResource resource = new PrototypeInputStreamResource(bais);
return resource;
} else {
continue;
}
}
throw new IOException("http get template failed! resourceName=" + resourceName);
} catch (Exception e) {
logger.error("http get template failed! resourceName=" + resourceName + e.getMessage(), e);
}
return null;
}
void wrapHtmlContent(String resourceName, String htmlText) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String timestamp = sdf.format(new Date());
String content = "<!-- http get " + resourceName + "\t" + timestamp + " start -->\n";
content = content + htmlText;
content = "\n<!-- http get " + resourceName + "\t" + timestamp + " end -->\n";
}
@Override
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
if (event.getApplicationContext().getParent() == null) {
WebApplicationContext wac =
(WebApplicationContext) servletContext
.getAttribute(ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
TemplateService ts = (TemplateService) wac.getBean("templateService");
VelocityEngineImpl ve = (VelocityEngineImpl) ts.getTemplateEngine("vm");
VelocityRuntimeInstance vri = (VelocityRuntimeInstance) ve.getRuntimeServices();
vmEncoding = StringUtils.trimToNull((String) vri.getProperty(RuntimeConstants.INPUT_ENCODING));
}
}
// 保证实时数据,不缓存。
static class PrototypeInputStreamResource extends InputStreamResource {
public PrototypeInputStreamResource(InputStream stream) {
super(stream);
}
public long lastModified() {
return System.currentTimeMillis();
}
}
}
remoteResourceHost:资源所在的地方,例如,vm目录放在本地,nginx指向vm目录,nginx作为文件服务器提供文件资源服务。
httpUtils是一个http工具类。
这样一个扩展好处就是,服务器部署某个应用后,配置vm目录指向本地,如果需要修改vm看效果,不用重启应用,不用登录服务器修改vm文件,不用本地文件改了再传到服务器,只用在本地修改即可。用于开发阶段。
