java – 防止在页面加载时将后缀添加到资源中
|
我有一个JSF2应用程序运行没有任何问题.我使用JSF的问题是资源包.所有资源都附加了.xhtml后缀.所以main.css在浏览器中加载时变成main.css.xhtml.我想要这样,所以.xhtml不是资源(不要介意页面本身). 有没有一种我们不能将.xhtml附加到资源的方式? 我最好不用改变网站的内部工作.我已经列出了下面的想法,但我不得不说我不太喜欢这些.希望解决某个地方? 我在Glassfish 3.1.2.2上使用了Majorra v.2.1.17. 当前Faces Servlet加载在web.xml(更新) <servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
</servlet-mapping>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>/javax.faces.resource/*</url-pattern>
</servlet-mapping>
为什么这个问题与别人不同 > JSF 2 resources with CDN?.我不想将资源放在CDN上,而是将资源留在我的服务器上,但是被推向CDN. 推理 当然你可能会问我为什么需要这个.那我们正在把我们的应用程序转移给Akamai CDN. 我们在整合网站时遇到的问题是我们正试图在边缘服务器上缓存静态内容.这通过匹配文件扩展名(即:.js,.doc,.png,css等)来完成.我们无法匹配xhtml,因为这将缓存所有页面以及静态内容.哪个会导致会话等问题. 尝试解决方案 根据BalusC的答案,我已经按照建议执行了资源处理程序.我不会在这里重写代码,因为它在下面的答案. 但是,加载复合组件时我收到错误.我得到一个错误: WARNING: StandardWrapperValve[Faces Servlet]: PWC1406: Servlet.service() for servlet Faces Servlet threw exception
java.lang.NullPointerException
at com.sun.faces.application.ApplicationImpl.createComponent(ApplicationImpl.java:975)
at com.sun.faces.facelets.tag.jsf.CompositeComponentTagHandler.createComponent(CompositeComponentTagHandler.java:162)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.createComponent(ComponentTagHandlerDelegateImpl.java:494)
at com.sun.faces.facelets.tag.jsf.ComponentTagHandlerDelegateImpl.apply(ComponentTagHandlerDelegateImpl.java:169)
...
复合组件正确加载,因为如果我“注销”新的ResourceHandler,我们刚刚创建它将加载.堆栈跟踪使我相信它正在尝试在一个java类中找到这个组件,而不是在资源中找到它.根据grepcode,这将是最后一行(975)发生错误: String packageName = componentResource.getLibraryName();
String className = componentResource.getResourceName();
className = packageName + '.' + className.substring(0,className.lastIndexOf('.'));
意思是resourceName,aka className为null,因为我得到的错误是java.lang.NullPointerException.我似乎无法确定ResourceHandler与复合组件的对应关系.任何帮助弄清楚这最后一个问题? 解决方法这可以在createResource()中返回一个
Resource,然后在
Resource#getRequestPath()返回一个“未映射的”URL的自定义
ResourceHandler.您只需要将默认的JSF资源前缀/javax.faces.resource/*添加到< url-pattern> ; FacesServlet映射的列表,以使其被触发. 此外,您需要覆盖
isResourceRequest()以检查URL是否以JSF资源前缀开头,也可以使用
handleResourceRequest()来定位和流式传输正确的资源.
所有这一切,这应该做: public class UnmappedResourceHandler extends ResourceHandlerWrapper {
private ResourceHandler wrapped;
public UnmappedResourceHandler(ResourceHandler wrapped) {
this.wrapped = wrapped;
}
@Override
public Resource createResource(final String resourceName,final String libraryName) {
final Resource resource = super.createResource(resourceName,libraryName);
if (resource == null) {
return null;
}
return new ResourceWrapper() {
@Override
public String getRequestPath() {
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
String mapping = externalContext.getRequestServletPath();
if (externalContext.getRequestPathInfo() == null) {
mapping = mapping.substring(mapping.lastIndexOf('.'));
}
String path = super.getRequestPath();
if (mapping.charAt(0) == '/') {
return path.replaceFirst(mapping,"");
}
else if (path.contains("?")) {
return path.replace(mapping + "?","?");
}
else {
return path.substring(0,path.length() - mapping.length());
}
}
@Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
public String getResourceName() {
return resource.getResourceName();
}
@Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
public String getLibraryName() {
return resource.getLibraryName();
}
@Override // Necessary because this is missing in ResourceWrapper (will be fixed in JSF 2.2).
public String getContentType() {
return resource.getContentType();
}
@Override
public Resource getWrapped() {
return resource;
}
};
}
@Override
public boolean isResourceRequest(FacesContext context) {
return ResourceHandler.RESOURCE_IDENTIFIER.equals(context.getExternalContext().getRequestServletPath());
}
@Override
public void handleResourceRequest(FacesContext context) throws IOException {
ExternalContext externalContext = context.getExternalContext();
String resourceName = externalContext.getRequestPathInfo();
String libraryName = externalContext.getRequestParameterMap().get("ln");
Resource resource = context.getApplication().getResourceHandler().createResource(resourceName,libraryName);
if (resource == null) {
super.handleResourceRequest(context);
return;
}
if (!resource.userAgentNeedsUpdate(context)) {
externalContext.setResponseStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
externalContext.setResponseContentType(resource.getContentType());
for (Entry<String,String> header : resource.getResponseHeaders().entrySet()) {
externalContext.setResponseHeader(header.getKey(),header.getValue());
}
ReadableByteChannel input = null;
WritableByteChannel output = null;
try {
input = Channels.newChannel(resource.getInputStream());
output = Channels.newChannel(externalContext.getResponSEOutputStream());
for (ByteBuffer buffer = ByteBuffer.allocateDirect(10240); input.read(buffer) != -1; buffer.clear()) {
output.write((ByteBuffer) buffer.flip());
}
}
finally {
if (output != null) try { output.close(); } catch (IOException ignore) {}
if (input != null) try { input.close(); } catch (IOException ignore) {}
}
}
@Override
public ResourceHandler getWrapped() {
return wrapped;
}
}
在faces-config.xml中注册如下: <application>
<resource-handler>com.example.UnmappedResourceHandler</resource-handler>
</application>
使用ResourceHandler.RESOURCE_IDENTIFIER扩展FacesServlet URL模式: <servlet-mapping>
<servlet-name>facesServlet</servlet-name>
<url-pattern>*.xhtml</url-pattern>
<url-pattern>/javax.faces.resource/*</url-pattern>
</servlet-mapping> (编辑:哈尔滨站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
