加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 防止在页面加载时将后缀添加到资源中

发布时间:2020-12-14 14:48:14 所属栏目:Java 来源:网络整理
导读:我有一个JSF2应用程序运行没有任何问题.我使用JSF的问题是资源包.所有资源都附加了.xhtml后缀.所以main.css在浏览器中加载时变成main.css.xhtml.我想要这样,所以.xhtml不是资源(不要介意页面本身). 有没有一种我们不能将.xhtml附加到资源的方式? 我最好不用
我有一个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.
> Change /javax.faces.resource prefix of resource URLs.我不想改变前缀.我只想改变后缀.我想要< link type =“text / css”rel =“stylesheet”href =“/ javax.faces.resource / main03.css.xhtml?ln = styles”>成为:< link type =“text / css”rel =“stylesheet”href =“/ javax.faces.resource / main03.css?ln = styles”>没有.xhtml扩展名.
> Changing JSF prefix to suffix mapping forces me to reapply the mapping on CSS background images.由于我没有加载资源的问题.该网站的作品,我们只是很难区分一个网页从一个资源(因为我们仅仅看扩展).

推理

当然你可能会问我为什么需要这个.那我们正在把我们的应用程序转移给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&gt ; 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>

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读