在 Wicket 中有一个静态 "sub-site" (即:在 Wicket 中安装一个目录)
Having a static "sub-site" in Wicket (i.e.: mounting a directory in Wicket)
我正在使用 Wicket
开发 Web 应用程序。
虽然大部分网站是通过 wicket 动态生成的,但我需要网站的一部分是正常的 "static" html
网站。基本上是主网站内的一个小 "subsite",根本不受 wicket 管理,而只是静态内容的集合(html 页面,css,图像)。
这能做到吗?这个想法是 "mount" 某个子路径指向子站点,但我不知道这是否可能,因为 mountResource()
方法需要一个资源作为输入。
编辑:我需要一个允许我直接在文件系统上修改静态 html 文件的解决方案,这就是我尝试通过 wicket "mount a directory" 的原因。我不能简单地将页面放在我的 webapp 文件夹中,因为这样它们最终会进入应用程序的 WAR 文件,并且每次对静态页面的修改都需要完全部署。
有什么想法吗?
好吧,最后我自己实现了这个,使用动态资源。我不是 Wicket 专家,因此出于某种原因这可能是 "bad" 解决方案,但它似乎有效。在这里发布代码,以便其他人可以根据需要使用它:
我所做的是创建这个资源:
public class DirectoryResolverResource implements IResource {
private static final long serialVersionUID = 1L;
private File servedDirectory;
private String urlPrefix;
//served directory is the directory you want to mount as a static sub-site
//urlPrefix is the mountpoint where you're going to mount this resource, without the leading "/". E.g.: if you mount your directory in "/help" so that the sub-site URL is www.yoursite.com/pages/help the urlPrefix value must be "help"
public DirectoryResolverResource(File servedDirectory, String urlPrefix) {
super();
if (servedDirectory == null || !servedDirectory.isDirectory()) {
throw new IllegalArgumentException("Directory is null or doesn't exist");
}
this.servedDirectory = servedDirectory;
this.urlPrefix = urlPrefix;
}
@Override
public void respond(Attributes attributes) {
Url url = attributes.getRequest().getUrl();
String subPath = "";
try {
//we decode the URL by reversing the percent-encoding, so that filenames are properly resolved
subPath = URLDecoder.decode(url.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_BAD_REQUEST, "Encoding is invalid");
}
if (subPath.startsWith(urlPrefix)) {
subPath = subPath.substring(urlPrefix.length());
} else {
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Url is invalid");
}
File file = new File(servedDirectory.getAbsolutePath() + (subPath.startsWith("/") ? "" : "/") + subPath);
if (file.isDirectory()) {
// In case of a directory, redirect to the path ending in "/", otherwise browsers will fail to resolve relative paths in the page
if (!subPath.endsWith("/")) {
throw new RedirectToUrlException("." + (subPath.isEmpty() ? "/" + urlPrefix : subPath) + "/", HttpServletResponse.SC_MOVED_PERMANENTLY);
}
// no specific file specified, try to return index.html
file = new File(file.getAbsolutePath(), "index.html");
}
if (!file.exists() || file.isDirectory()) {
// file not found
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_NOT_FOUND, "Resource not found");
}
if (!FSManager.isInSubDirectory(servedDirectory, file)) {
// Security check: user is trying to escape the served directory via a non-canonical path
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_FORBIDDEN, "Access to this resource is forbidden");
}
// Serve the file
FileResourceStream fileResourceStream = new FileResourceStream(file);
ResourceStreamResource resource = new ResourceStreamResource(fileResourceStream);
resource.respond(attributes);
}
}
您可以像这样装载此资源:
mountResource("/help", new ResourceReference("helpres") {
private static final long serialVersionUID = 1L;
@Override
public IResource getResource() {
return new DirectoryResolverResource(helpDir, "help");
}
});
希望这对某人有帮助。
非常感谢任何 improvements/comments/corrections/constructive 批评!
注意:isInSubDirectory()
方法只检查文件是否在某个目录树中。不会让你厌烦细节,你可以在这里找到这种方法的实现:Check if file is in (sub)directory
我正在使用 Wicket
开发 Web 应用程序。
虽然大部分网站是通过 wicket 动态生成的,但我需要网站的一部分是正常的 "static" html
网站。基本上是主网站内的一个小 "subsite",根本不受 wicket 管理,而只是静态内容的集合(html 页面,css,图像)。
这能做到吗?这个想法是 "mount" 某个子路径指向子站点,但我不知道这是否可能,因为 mountResource()
方法需要一个资源作为输入。
编辑:我需要一个允许我直接在文件系统上修改静态 html 文件的解决方案,这就是我尝试通过 wicket "mount a directory" 的原因。我不能简单地将页面放在我的 webapp 文件夹中,因为这样它们最终会进入应用程序的 WAR 文件,并且每次对静态页面的修改都需要完全部署。
有什么想法吗?
好吧,最后我自己实现了这个,使用动态资源。我不是 Wicket 专家,因此出于某种原因这可能是 "bad" 解决方案,但它似乎有效。在这里发布代码,以便其他人可以根据需要使用它:
我所做的是创建这个资源:
public class DirectoryResolverResource implements IResource {
private static final long serialVersionUID = 1L;
private File servedDirectory;
private String urlPrefix;
//served directory is the directory you want to mount as a static sub-site
//urlPrefix is the mountpoint where you're going to mount this resource, without the leading "/". E.g.: if you mount your directory in "/help" so that the sub-site URL is www.yoursite.com/pages/help the urlPrefix value must be "help"
public DirectoryResolverResource(File servedDirectory, String urlPrefix) {
super();
if (servedDirectory == null || !servedDirectory.isDirectory()) {
throw new IllegalArgumentException("Directory is null or doesn't exist");
}
this.servedDirectory = servedDirectory;
this.urlPrefix = urlPrefix;
}
@Override
public void respond(Attributes attributes) {
Url url = attributes.getRequest().getUrl();
String subPath = "";
try {
//we decode the URL by reversing the percent-encoding, so that filenames are properly resolved
subPath = URLDecoder.decode(url.toString(), "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_BAD_REQUEST, "Encoding is invalid");
}
if (subPath.startsWith(urlPrefix)) {
subPath = subPath.substring(urlPrefix.length());
} else {
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Url is invalid");
}
File file = new File(servedDirectory.getAbsolutePath() + (subPath.startsWith("/") ? "" : "/") + subPath);
if (file.isDirectory()) {
// In case of a directory, redirect to the path ending in "/", otherwise browsers will fail to resolve relative paths in the page
if (!subPath.endsWith("/")) {
throw new RedirectToUrlException("." + (subPath.isEmpty() ? "/" + urlPrefix : subPath) + "/", HttpServletResponse.SC_MOVED_PERMANENTLY);
}
// no specific file specified, try to return index.html
file = new File(file.getAbsolutePath(), "index.html");
}
if (!file.exists() || file.isDirectory()) {
// file not found
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_NOT_FOUND, "Resource not found");
}
if (!FSManager.isInSubDirectory(servedDirectory, file)) {
// Security check: user is trying to escape the served directory via a non-canonical path
throw new AbortWithHttpErrorCodeException(HttpServletResponse.SC_FORBIDDEN, "Access to this resource is forbidden");
}
// Serve the file
FileResourceStream fileResourceStream = new FileResourceStream(file);
ResourceStreamResource resource = new ResourceStreamResource(fileResourceStream);
resource.respond(attributes);
}
}
您可以像这样装载此资源:
mountResource("/help", new ResourceReference("helpres") {
private static final long serialVersionUID = 1L;
@Override
public IResource getResource() {
return new DirectoryResolverResource(helpDir, "help");
}
});
希望这对某人有帮助。 非常感谢任何 improvements/comments/corrections/constructive 批评!
注意:isInSubDirectory()
方法只检查文件是否在某个目录树中。不会让你厌烦细节,你可以在这里找到这种方法的实现:Check if file is in (sub)directory