I have simple Spring configuration
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix">
<value>/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
<!-- Scan for components under this package -->
<context:component-scan base-package="com.osfg.test" />
And my controller is
package com.osfg.test;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
/**
* #author athakur
*/
#Controller
public class TestController {
#RequestMapping(value="/test", method=RequestMethod.GET)
public String welcome() {
return "test";
}
}
And my JSP is
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>OSFG Test Page</title>
<link href="CSS/test.css" rel="stylesheet">
</head>
<body>
<h1>Hello World!</h1>
</body>
</html>
This configuration works fine (CSS does not get applied though).
So I add
<mvc:default-servlet-handler />
to my Spring configuration and now the page itself stops loading giving 404.
Also surprisingly everything works fine (with CSS) will following config
<mvc:view-controller path="/test" view-name="test"/>
<mvc:default-servlet-handler />
Direct rendering no controller involvement.
I think having a simple configuration for resources will suffice.
<mvc:resources mapping="/resources/**" location="/resources/" />
Looks like I found the issue. Somehow the default-sevlet-handler is overriding the DefaultAnnotationHandlerMapping handler? which is why annotation based handler is failing. Following scenarios worked for me -
Use <mvc:annotation-driven/>. This seems to enable default beans including DefaultAnnotationHandlerMapping So combination of
<mvc:annotation-driven/>
<mvc:default-servlet-handler />
worked.
Explicitly define the handler mapping and handler adapter you need with highest preference (chaining). Spring scans all handler mappings and assigns an order property Integer.MAX (if not explicitly defined) which gives it lowest preference. Then these handler mappings are sorted based on this order. Also if two handler mappings are same it looks like it takes bean which is defined first. So following worked for me -
<mvc:default-servlet-handler />
<bean id="annotationUrlMapping" class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="order" value="0" />
</bean>
<bean id="annotationMethodHandlerAdapter" class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter"/>
So I am guessing default-sevlet-handler creates it's own handler mapping which overrides the annotation one all being at same preference.
Related
Is it possible to integrate Spring beans and JSP tags somehow in Spring. That is use a Spring bean as a JSP Tag? And if so is this a good/terrible idea? So something like this would be possible:
#Component
public class SomeBean extends SimpleTagSupport {
#Autowired
SomeBean someBean;
#Override
public void doTag() throws JspException, IOException {
getJspContext().getOut().write(someBean.doSomething());
}
}
What would I do in the tags.tld to get it to use the Spring bean instead of creating a new instance that would not have someBean injected? Or is it something else?
InternalResourceViewResolver allows you use exposition for export beans into jsp context. For example, if you would like to expose list of beans, you should configure view resolver in you dispatcher-servlet.xml next way:
...
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
<property name="exposedContextBeanNames">
<list>
<value>someBean</value>
</list>
</property>
</bean>
...
where someBean is the name of bean you would like to export to jsp context. You can even expose all spring beans:
...
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/"/>
<property name="suffix" value=".jsp"/>
<property name="exposeContextBeansAsAttributes" value="true"/>
</bean>
...
This allows you access to spring beans from jsp context by bean's name.
Lets say your tag's handler looks like this:
package com.mytags;
public class SomeTag extends SimpleTagSupport {
private SomeBean bean;
#Override
public void doTag() throws JspException, IOException {
getJspContext().getOut().write(bean.doSomething());
}
public SomeBean getBean(){...}
public void setBean(SomeBean bean){...}
}
Then in tld your tag will be described next way:
...
<tag>
<name>someTag</name>
<tag-class>com.mytags.SomeTag</tag-class>
<body-content>empty</body-content>
<attribute>
<name>bean</name>
<required>true</required>
<rtexprvalue>true</rtexprvalue>
<type>com.mybeans.SomeBean</type>
</attribute>
</tag>
...
Note, that you have to specify rtexprvalue as true, because you will pass bean into the tag as EL expression. Now you can use this tag in jsp:
<%# taglib prefix="mytags" uri="http://mytags.com" %>
<%# page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title></title>
</head>
<body>
<mytags:someTag bean="${someBean}"/>
</body>
</html>
But actually it is not good idea to access spring bean right from tag's handler directly. Tag have to know how to show data, but should be abstracted from how to obtain this data. Better prepare all data you would like to show in controller and pass it as model to the jsp.
I tried various tutorials but it simply dosen't work.
I am building spring application with boostrap. I want to include bootstrap.min.css in my jsp page.
Here is my project tree:
this is my spring configuration file:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">
<mvc:annotation-driven />
<context:component-scan base-package="com.packt.webstore" />
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
<mvc:resources location="WEB-INF" mapping="/resource"/>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<property name="maxUploadSize" value="10240000"/>
</bean>
</beans>
This line is important:
<mvc:resources mapping="/resources/**" location="/WEB-INF/resources/" />
This is my view page:
I uploaded image on purpose to show that I can't even import it because it dosen't recognize the path. Well I tried other configuration but I can't figure out how to do it the right way.
you can use the jstl :
<link href="<c:url value="/resources/css/main.css" />" rel="stylesheet">
<script src="<c:url value="/resources/js/jquery.1.10.2.min.js" />"></script>
or Spring tags :
<spring:url value="/resources/js/jquery.1.10.2.min.js" var="jqueryJs" />
<spring:url value="/resources/js/main.js" var="bootstrap" />
<link href="${bootstrap}" rel="stylesheet" />
<script src="${jqueryJs}"></script>
or
<link href="${pageContext.request.contextPath}/resources/css/main.css" rel="stylesheet" >
<script src="${pageContext.request.contextPath}/resources/css/jquery.js"></script>
Some time ago I've created simple web app using jsp and servlets and I had same problem. I've resolved this by adding context name at the beginning of every url. Here is example of that url:
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/form-style.css" />
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/css/edit-contact-form-style.css" />
<script src="${pageContext.request.contextPath}/js/edit-contact-form-scripts.js"></script>
<script src="${pageContext.request.contextPath}/js/datetimepicker.js"></script>
Try it. I hope this helps.
configure view resolver and move the css files under the configured location.
you can refer this already answered question: spring mvc where to put css/js/img files
If you want to be not like those xml losers and do an app with zero xml, don't forget to make a class like this:
public class DemoAppConfig implements WebMvcConfigurer {
#Bean
public ViewResolver viewResolver() {
final InternalResourceViewResolver bean = new InternalResourceViewResolver();
bean.setViewClass(JstlView.class);
bean.setPrefix("/WEB-INF/view/pages/");
bean.setSuffix(".jsp");
return bean;
}
public void addResourceHandlers(final ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
}
I'm trying to get Spring 4.1.9 and Thymeleaf 2.1.5 to render XHTML Basic 1.1 pages, which have the following preamble:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
Simply using this in a template doesn't work, as Thymeleaf doesn't recognize the doctype.
org.thymeleaf.exceptions.TemplateProcessingException: Unsupported entity requested with PUBLICID "-//W3C//DTD XHTML Basic 1.1//EN" and SYSTEMID "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd". Make sure a corresponding org.thymeleaf.doctype.resolution.IDocTypeResolutionEntry implementation is provided by you dialect (index:1)
Setup
I went through the Thymeleaf extension documentation and source code and using that as a starting point, defined a new dialect inheriting from SpringStandardDialect. I figured out the missing modules through trial and error, downloading them from w3.org and adding them to the resources directory of my project:
XhtmlBasicDialect.java
import java.util.LinkedHashSet;
import java.util.Set;
import org.thymeleaf.doctype.DocTypeIdentifier;
import org.thymeleaf.doctype.resolution.ClassLoaderDocTypeResolutionEntry;
import org.thymeleaf.doctype.resolution.IDocTypeResolutionEntry;
import org.thymeleaf.spring4.dialect.SpringStandardDialect;
public class XhtmlBasicDialect extends SpringStandardDialect {
private static final String DTD_STANDARD_PATH = "org/thymeleaf/dtd/standard/";
private static final DocTypeIdentifier XHTML_BASIC_11_PUBLICID = DocTypeIdentifier.forValue("-//W3C//DTD XHTML Basic 1.1//EN");
private static final DocTypeIdentifier XHTML_BASIC_11_SYSTEMID = DocTypeIdentifier.forValue("http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd");
private static final DocTypeIdentifier ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ENTITIES XHTML Basic 1.1 Document Model 1.0//EN");
private static final DocTypeIdentifier ELEMENTS_XHTML_BASIC_TABLES_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Basic Tables 1.0//EN");
private static final DocTypeIdentifier ELEMENTS_XHTML_INPUTMODE_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Inputmode 1.0//EN");
private static final DocTypeIdentifier ELEMENTS_XHTML_TARGET_1_PUBLICID = DocTypeIdentifier.forValue("-//W3C//ELEMENTS XHTML Target 1.0//EN");
private static final IDocTypeResolutionEntry XHTML_BASIC_STRICT_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(XHTML_BASIC_11_PUBLICID, XHTML_BASIC_11_SYSTEMID, DTD_STANDARD_PATH + "xhtml-basic11.dtd");
private static final IDocTypeResolutionEntry ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-basic11-model-1.mod");
private static final IDocTypeResolutionEntry ELEMENTS_XHTML_BASIC_TABLES_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_BASIC_TABLES_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-basic-table-1.mod");
private static final IDocTypeResolutionEntry ELEMENTS_XHTML_INPUTMODE_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_INPUTMODE_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-inputmode-1.mod");
private static final IDocTypeResolutionEntry ELEMENTS_XHTML_TARGET_1_DOC_TYPE_RESOLUTION_ENTRY = new ClassLoaderDocTypeResolutionEntry(ELEMENTS_XHTML_TARGET_1_PUBLICID, DocTypeIdentifier.ANY, DTD_STANDARD_PATH + "xhtml-target-1.mod");
#Override
protected Set<IDocTypeResolutionEntry> getAdditionalDocTypeResolutionEntries() {
final Set<IDocTypeResolutionEntry> docTypeResolutionEntries = new LinkedHashSet<IDocTypeResolutionEntry>();
docTypeResolutionEntries.add(XHTML_BASIC_STRICT_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ENTITIES_XHTML_BASIC_11_DOCUMENT_MODEL_1_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ELEMENTS_XHTML_BASIC_TABLES_1_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ELEMENTS_XHTML_INPUTMODE_1_DOC_TYPE_RESOLUTION_ENTRY);
docTypeResolutionEntries.add(ELEMENTS_XHTML_TARGET_1_DOC_TYPE_RESOLUTION_ENTRY);
return docTypeResolutionEntries;
}
}
I configure the custom dialect as follows:
mvc-config.xml
...
<bean id="templateResolver" class="org.thymeleaf.templateresolver.ServletContextTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/" />
<property name="suffix" value=".xhtml" />
<property name="characterEncoding" value="UTF-8" />
<property name="templateMode" value="XHTML" />
<property name="xhtmlTemplateModePatterns" value="*.xhtml" />
</bean>
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="templateResolver" ref="templateResolver" />
<property name="additionalDialects">
<set>
<bean class="demo.XhtmlBasicDialect" />
</set>
</property>
</bean>
<bean id="xhtmlViewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="templateEngine" ref="templateEngine" />
<property name="characterEncoding" value="UTF-8" />
<property name="contentType" value="application/xhtml+xml" />
</bean>
...
My template is as follows:
DemoTemplate.xhtml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN"
"http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<title>Demo</title>
<link th:href="${'style' + '.css'}" rel="stylesheet" type="text/css"/>
</head>
<body>
<div>
<p>Demo content</p>
</div>
</body>
</html>
The Problem
At first glance, this seems to render fine, except that the resulting XHTML is missing the XML header, and has several extra attributes that are added to every element.
Rendered output:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="-//W3C//DTD XHTML Basic 1.1//EN">
<head xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<title xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">Demo</title>
<link rel="stylesheet" type="text/css" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve" href="style.css" />
</head>
<body xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve">
<div xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve">
<p xmlns="http://www.w3.org/1999/xhtml" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xml:space="preserve">Demo content</p>
</div>
</body>
</html>
This doesn't quite match the XHTML Basic preamable; for one, I would like to keep XML declaration <?xml version="1.0" encoding="utf-8"?>
More importantly, I do not want the xmlns="http://www.w3.org/1999/xhtml", xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance", and xml:space="preserve" attributes to be added to just about every element. There's also an version="-//W3C//DTD XHTML Basic 1.1//EN" attribute added to the <html> element.
Am I doing something wrong, do I need to configure something differently, or am I missing something from the custom dialect?
Well I don't have "canonical" evidence that XHTML Basic templates can't be handled the way you want with Thymeleaf 2.x, and there probably is a way given enough effort. But I did see that:
XhtmlAndHtml5NonValidatingSAXTemplateParser in Thymeleaf 2.1 looks fishy and no longer exists in Thymeleaf 3.0
The XHTML TemplateMode is now deprecated, along with xhtmlTemplateModePatterns
That all the parsing code in 2.1 had been rewritten in 3.0
This, along with my own struggles to get something working, leads me to believe that the XHTML handling in Thymeleaf 2.X was never fully baked. However, it seems to work just fine in 3.0 with no special effort. Just configure a ViewResolver as follows:
<bean id="viewResolver" class="org.thymeleaf.spring4.view.ThymeleafViewResolver">
<property name="characterEncoding" value="UTF-8"/>
<property name="templateEngine">
<bean class="org.thymeleaf.spring4.SpringTemplateEngine">
<property name="enableSpringELCompiler" value="true"/>
<property name="templateResolver">
<bean class="org.thymeleaf.spring4.templateresolver.SpringResourceTemplateResolver">
<property name="prefix" value="/WEB-INF/templates/"/>
<property name="suffix" value=".xhtml"/>
<property name="templateMode" value="XML"/>
</bean>
</property>
</bean>
</property>
</bean>
I posted a complete working example on github.
I have created a dynamic web module project usig STS and Spring MVC. The problem is I have add a string into a Model but it cannot be display on the JSP page using EL.
May I know what wrong with it?
Below is the details:
JSP Page
<%# page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1" isELIgnored="false" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<%# taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring MVC</title>
</head>
<body>
Home
<br />
<c:out value="${message}" />
</body>
</html>
Web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
MVC Controller:
#Controller
public class HomeController {
public HomeController() {
super();
}
#RequestMapping(value="/home", method=RequestMethod.GET)
public ModelAndView showHomePage() {
// View Name - Model Name - Model Data
return new ModelAndView("home", "message", "Hello Spring MVC");
}
}
Dispatcher-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- http://www.jpalace.org/docs/tutorials/spring/mvc_10.html -->
<!-- Context Scan -->
<context:component-scan base-package="com.peter.controller"/>
<!-- Handler Mapping -->
<bean id="handlerMapping" class="org.springframework.web.portlet.mvc.annotation.DefaultAnnotationHandlerMapping">
</bean>
<!-- Handler Adapter - AnnotationMethodHandlerAdapter -->
<!-- Invoke Handler Method -->
<bean id="handlerAdapter" class="org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter">
</bean>
<!-- Pre/Post Handler Interceptor -->
<!--
Implement HandlerInterceptor
Declare HandlerInterceptor inside DefaultAnnotationHandlerMapping property or
globally inside <mvc:interceptors>
Need configure Filter object inside web.xml
<bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
<property name="interceptors">
<list>
<bean class="pckg.MyInterceptor1"/>
<bean class="pckg.MyInterceptor2"/>
</list>
</property>
</bean>
<mvc:interceptors>
<bean class="pckg.MyInterceptor1"/>
<bean class="pckg.MyInterceptor2"/>
</mvc:interceptors>
-->
<!-- View Resolver -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView"></property>
<property name="prefix" value="/WEB-INF"></property>
<property name="suffix" value=".jsp"></property>
</bean>
<!-- Exception Resolver -->
<!-- Register Interceptor, Message Resource, Bean validation support, Message conversion and field formatting -->
<mvc:annotation-driven />
</beans>
I have JSTL.jar in my build path. There is warning message about the The tag handler class for "c:out" (org.apache.taglibs.standard.tag.rt.core.OutTag) was not found on the Java Build Path
Please help.
Thanks.
Download jstl-1.2.jar from the maven repo (http://repo1.maven.org/maven2/javax/servlet/jstl/1.2/).
Ensure that
the jar is available in WEB-INF\lib folder of your web application.
I would like to view your viewResolver configuration. Are you able to view the home page?? or there is 404 error?
If home.jsp is displaying properly then according to me the problem is in your jsp.
Look at the first line of the jsp where you have defined the page directive.
In that declaration remove the attribute isELIgnored="false" it is bydefault false everytime. So no need to define it explicitely.
I think if you remove that attribute. Your ${message} would display correctly.
Hope this helps you.
Cheers.
I want to have the same request mapping but resolve to different view depending on the file extension. I have two JSPs one that renders HTML and another that renders XML. Depending on the file extension I should resolve to the corresponding jsp.
This is my controller:
#Controller
public class FileManagementController {
#RequestMapping(value="/filemanagements", method=RequestMethod.GET)
public ModelAndView list() {
//if file extension .xml return /filemanagement/listXml
//if no file extension present return /filemanagement/list
}
}
And I Have the following y Root of my WebApp:
/jsp/filemanagement/list.jsp
<%#page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>
..
/jsp/filemanagement/listXml.jsp
<?xml version="1.0" encoding="UTF-8"?>
<%#page contentType="text/xml" pageEncoding="UTF-8"%>
....
This is how I have configured my ViewResolver in the servletContext.xml:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
Have a look at ContentNegotiatingViewResolver. From the javadoc:
This view resolver uses the requested media type to select a suitable View for a request.
If the requested path has a file extension and if the setFavorPathExtension(boolean) property is true, the mediaTypes property is inspected for a matching media type.
There is also a section of the ref manual covering this resolver.
Following skaffman advice. I did solve this using ContentNegotiatingViewResolver.
servletContext.xml:
<bean id="resourceResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver"/>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
<mvc:annotation-driven/>
The resolvers are picked up automatically by ContentNegotiatingViewResolver.
Controller:
#Controller
#RequestMapping("/filemanagements")
public class FileManagementController {
#RequestMapping(method=RequestMethod.GET)
public ModelAndView list(#RequestParam(required=false) String contentType) {
return new ModelAndView(baseLogicView + "/list");
}
private static final String baseLogicView = "/filemanagement";
}
These jsps:
/WEB-INF/jsp/filemanagements/list.jsp
/WEB-INF/jsp/filemanagements/listXml.jsp
Resource bundle views.properties:
/filemanagement/list.(class)=org.springframework.web.servlet.view.JstlView
/filemanagement/list.url=/WEB-INF/jsp/filemanagement/listXml.jsp
/filemanagement/list.contentType=text/xml
It was necessary to specify the contentType there because if you don't it defaults to this "text/html;charset=ISO-8859-1" even if you set <%# page contentType="text/xml" %> in the JSP that renders the XML.
After that I could do the following requests:
http://localhost:8080/filemanagement-web/filemanagements (list.jsp)
http://localhost:8080/filemanagement-web/filemanagements.html (list.jsp)
http://localhost:8080/filemanagement-web/filemanagements.xml (listXml.jsp)