Java – prevents suffixes from being added to resources when the page loads

I have a JSF 2 application running without any problems My problem with JSF is the resource bundle All resources are attached XHTML suffix So main CSS becomes main when it is loaded in the browser css. xhtml. I want this, so XHTML is not a resource (don't mind the page itself)

There is no one we can't put How does XHTML attach to resources?

I'd better not change the internal work of the website I've listed the following ideas, but I have to say I don't like them very much Want to solve somewhere?

I'm in GlassFish 3.1 Majorra v.2 is used on 2.2 1.17.

Currently, the faces servlet is loaded on the web XML (update)

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

Why is this problem different from others

> JSF 2 resources with CDN?. I don't want to put resources on the CDN. Instead, I leave resources on my server, but they are pushed to the CDN. > Change /javax. faces. resource prefix of resource URLs. I don't want to change the prefix I just want to change the suffix I want < link type = "text / CSS" rel = "stylesheet" href = "/ javax. Faces. Resource / main03. CSS. XHTML? Ln = styles" > to be: < link type = "text / CSS" rel = "stylesheet" href = "/ javax. Faces. Resource / main03. CSS? Ln = styles" > No XHTML extension. > Changing JSF prefix to suffix mapping forces me to reapply the mapping on CSS background images. Because I have no problem loading resources The site works, we just have difficulty distinguishing a page from a resource (because we only look at extensions)

reasoning

Of course, you might ask me why I need this Then we are transferring our applications to Akamai CDN

The problem we encountered when integrating websites is that we are trying to cache static content on edge servers This is done by matching file extensions (i.e.: JS,. Doc,. PNG, CSS, etc.) We can't match XHTML because it will cache all pages and static content Which causes problems such as conversation

Try a solution

According to balusc's answer, I have implemented the resource handler as recommended I won't rewrite the code here because it's in the answer below

However, I received an error when loading the composite component I got an error:

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

The composite component loads correctly because if I "unregister" the new resourcehandler, we just created it and it will load The stack trace convinced me that it was trying to find the component in a Java class, not in a resource According to grepcode, this will be the error on the last line (975):

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

It means resourcename, aka classname is null, because the error I get is Java lang.NullPointerException. I can't seem to determine the correspondence between resourcehandler and composite component Any help in figuring out this last question?

Solution

This can return a resource in createresource() and then a custom resourcehandler with an "unmapped" URL in resource #getrequestpath() You just need to prefix the default JSF resource / javax faces. Resource / * added to < URL pattern & gt; A list of faces servlet mappings so that they are triggered In addition, you need to override isresourcerequest() to check whether the URL starts with the JSF resource prefix. You can also use handleresourcerequest() to locate and stream the correct resources

All this, this should be done:

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

}

In faces config XML is registered as follows:

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

Use resourcehandler RESOURCE_ Identifier extends facesservlet URL mode:

<servlet-mapping>
    <servlet-name>facesServlet</servlet-name>
    <url-pattern>*.xhtml</url-pattern>
    <url-pattern>/javax.faces.resource/*</url-pattern>
</servlet-mapping>
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>