Search code examples
springjspspring-annotations

Spring ContentNegotiatingViewResolver - How to use bean name for jsp view not full url with path parameters


My servlet-context file has

<beans:bean
class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
    <beans:property name="useNotAcceptableStatusCode"
        value="false" />
    <beans:property name="contentNegotiationManager">
        <beans:bean
            class="org.springframework.web.accept.ContentNegotiationManager">
            <beans:constructor-arg>
                <beans:bean
                    class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
                    <beans:constructor-arg>
                        <beans:map>
                            <beans:entry key="html" value="text/html" />
                            <beans:entry key="json" value="application/json" />
                        </beans:map>
                    </beans:constructor-arg>
                </beans:bean>
            </beans:constructor-arg>
        </beans:bean>
    </beans:property>

    <beans:property name="viewResolvers">
        <beans:list>
            <beans:bean
                class="org.springframework.web.servlet.view.BeanNameViewResolver"/>
            <beans:bean id="jspView"
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <beans:property name="prefix" value="/WEB-INF/jsp/" />
                <beans:property name="suffix" value=".jsp" />
            </beans:bean>
        </beans:list>
    </beans:property>

    <beans:property name="defaultViews">
        <beans:list>
            <beans:bean
                class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" />
        </beans:list>
    </beans:property>
</beans:bean>

My Controller File has

@Controller("resources")
public class Resources {

     @RequestMapping(value = "/resources/{name}", method = RequestMethod.GET)
     public Map getResource(@PathVariable String name) {
        return new HashMap();
     }
}

But whenever i try to access /server/resources/myfilename.html

Server throws 404 saying /server/WEB-INF/jsp/resources/myfilename.jsp is not found. But it should load /server/WEB-INF/jsp/resources.jsp as im using BeanNameViewResolver. Please help.


Solution

  • What you get:

    • Controller return a null view name, so DefaultRequestToViewNameTranslator generates one from URI = path from servlet path without slashes and filename extension: resources/myfilename

    • BeanNameViewResolver try to get a View from context named resources/myfilename, seem that fails and chain to next ViewResolver

    • InternalResourceViewResolver return a JstlView pointing to jsp prefix + viewName + suffix = /WEB-INF/jsp/resources/myfilename.jsp

    So BeanNameViewResolver seems that don't resolve the view and the return of InternalResourceViewResolver is the expected one.

    What you want (I think)

    You want to remove the filename from the default view name, not only the extension.

    • Implements a RequestToViewNameTranslator and declare it in the DispatcherServlet context with name viewNameTranslator.

    For example:

    public class StripFileNameViewNameTranslator extends DefaultRequestToViewNameTranslator {
    
        @Override
        protected String transformPath(String lookupPath) {
            String path = super.transformPath(lookupPath);
            return  StringUtils.substringBeforeLast(path, "/");
        }
    }