阻止在页面加载时将后缀添加到资源 [英] Prevent suffix from being added to resources when page loads

查看:167
本文介绍了阻止在页面加载时将后缀添加到资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个JSF2应用程序运行并且没有问题。我与JSF的问题在于资源包。所有资源都附加了 .xhtml 后缀。因此,当在浏览器中加载时, main.css 变为 main.css.xhtml 。我想拥有它,所以 .xhtml 没有附加到资源上(不要介意页面本身)。

I have a JSF2 application running and working no problem. The issue I am having with JSF is with the resource bundle. All resources have the .xhtml suffix appended to it. So main.css becomes main.css.xhtml when loaded in the browser. I would like to have it so the .xhtml isn't apended to the resources (don't mind about the pages themselves).

有没有办法让 .xhtml 附加到资源?

Is there a way where we can NOT have .xhtml appended to resources?

理想情况下,我不需要更改网站的内部工作方式。我在下面列出了一些想法,但我不得不说我不喜欢这些。希望在某处找到解决方案?

I would ideally not have to change the internal workings of the site. I have listed ideas below, but I have to say I don't really like these. Hoping for a solution somewhere?

我在Glassfish 3.1.2.2上使用Majorra v.2.1.17。

I am using Majorra v.2.1.17 on Glassfish 3.1.2.2.

<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>



为什么这个问题与其他问题不同




  • 带有CDN的JSF 2资源? 。我不是要将我的资源放在CDN上,而是让我的资源保留在我的服务器上但是被推向CDN。

  • 更改资源URL的/javax.faces.resource前缀。我不想改变前缀。我只想更改后缀。我想要< link type =text / css =stylesheethref =/ javax.faces.resource / main03.css.xhtml?ln = styles> 成为:< link type =text / css =stylesheethref =/ javax.faces.resource / main03.css?ln = styles> 没有 .xhtml 扩展名。

  • 将JSF前缀更改为后缀映射迫使我重新应用在CSS背景图像上映射。因为我没有加载资源的问题。该网站有效,我们只是很难将资源与资源区分开来(因为我们只关注扩展)。

  • Why this questions is different from others

    • JSF 2 resources with CDN?. I am not looking to place my resources on a CDN, but to have my resources stay on my server but are pushed towards a CDN.
    • Change /javax.faces.resource prefix of resource URLs. I don't want to change the prefix. I want only to change the suffix. I would want <link type="text/css" rel="stylesheet" href="/javax.faces.resource/main03.css.xhtml?ln=styles"> to become : <link type="text/css" rel="stylesheet" href="/javax.faces.resource/main03.css?ln=styles"> WITHOUT the .xhtml extension.
    • Changing JSF prefix to suffix mapping forces me to reapply the mapping on CSS background images. Since I have no issue with loading the resources. The site works, we are simply having a hard time differrentiating a webpage from a resource (Since we are looking at the extention alone).
    • 当然,你可能会问我为什么需要这个。好吧,我们正在将我们的应用程序转移到Akamai CDN服务。

      Sure you might be asking me why I need this. Well, we are moving our application to be served by the Akamai CDN.

      我们在整合网站时遇到的问题是我们正在尝试缓存静态内容在边缘服务器上。这是通过匹配文件扩展名来完成的(即:.js,.doc,.png,css等)。我们无法匹配 xhtml ,因为这将缓存所有页面以及静态内容。这会导致会话等问题。

      The issue we are having with the integration of the site is that we are trying to cache static content on the edge servers. This is done by matching file extensions (ie: .js, .doc, .png, css, etc). We cannot match xhtml because this would be caching all pages as well as static content. Which by that would cause problems with sessions and such.

      符合BalusC的答案,我已按照建议实现了资源处理程序。我不会在这里重写代码,因为它在下面回答。

      In line with the answer by BalusC, I have implemented the resource handler as suggested. I will not rewrite code here, since it is in answer below.

      但是,我在加载复合组件时遇到错误。我收到错误:

      However, I am getting an error when loading composite components. I am getting an error as such :

      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)发生错误:

      Composite component is loaded correctly because if I "unregister" the new ResourceHandler we just created it will load. The stack trace leads me to believe that it is trying to find this component in a java class, instead of finding it in the resources. According to grepcode this would be at this last line (975) where the error happens :

      String packageName = componentResource.getLibraryName();
      String className = componentResource.getResourceName();
      className = packageName + '.' + className.substring(0, className.lastIndexOf('.'));
      

      意味着 resourceName ,又名 className null ,因为我得到的错误是 java.lang.NullPointerException 。我似乎无法弄清楚如何/在哪里调用 ResourceHandler 相对于复合组件。有什么帮助可以搞清楚这个问题吗?

      Meaning that the resourceName, aka className is null since the error I am getting is java.lang.NullPointerException. I can't seem to figure out how/where the ResourceHandler is called vis-a-vis a composite component. Any help figuring out this last issue?

      推荐答案

      这可以通过自定义 ResourceHandler createResource() 资源 ,然后在 资源#getRequestPath() 。您只需要将默认的JSF资源前缀 /javax.faces.resource / * 添加到< url-pattern> FacesServlet 映射列表,无论如何都要触发它。

      This is doable with a custom ResourceHandler which returns in createResource() a Resource which in turn returns an "unmapped" URL on Resource#getRequestPath(). You only need to add the default JSF resource prefix /javax.faces.resource/* to the <url-pattern> list of the FacesServlet mapping in order to get it to be triggered anyway.

      此外,你需要覆盖 isResourceRequest() 检查URL是否以JSF资源前缀开头,还是 handleResourceRequest() 查找和流式传输适当的资源。

      Further, you need to override isResourceRequest() to check if the URL starts with the JSF resource prefix and also the handleResourceRequest() to locate and stream the proper resource.

      全部,这应该做:

      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;
          }
      
      }
      

      在<$中注册如下c $ c> faces-config.xml :

      <application>
          <resource-handler>com.example.UnmappedResourceHandler</resource-handler>
      </application>
      

      使用<$扩展 FacesServlet 网址格式c $ c> ResourceHandler.RESOURCE_IDENTIFIER :

      Extend the FacesServlet URL pattern with ResourceHandler.RESOURCE_IDENTIFIER:

      <servlet-mapping>
          <servlet-name>facesServlet</servlet-name>
          <url-pattern>*.xhtml</url-pattern>
          <url-pattern>/javax.faces.resource/*</url-pattern>
      </servlet-mapping>
      

      这篇关于阻止在页面加载时将后缀添加到资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆