I'm writing a webapp using angularjs and spring mvc as a REST service provider and as a partial view provider(I'm also using angular-ui-router so that I can have multiple nested partials). I currently don't have any use for template languages since I plan on doing everything in angular, however every single view resolver I've tried has some type of template language which clashes with angular and either crashes the application and/or fills my logs with errors.
First I tried using InternalResourceViewResolver but no luck as it seems that it only expects .jsp files and won't show anything else.
Then I tried using Thymeleaf. Thymeleaf follows the XML standard which forced me to rewrite most of my html to follow the xml requirements, and after I'd done that it died upon encountering a &&
inside an ng-show directive. So no luck with that either.
Then I tried Velocity. I've had most luck with velocity so far. It serves up html files nicely, doesn't stop upon encountering parse errors and allows me to serve up partial views the same way InternalResourceViewResolver does. However upon encountering angular variables prefixed by $
Velocity tries to parse them as VTL variables and fills my logs with messages like
velocity - Null reference [template 'clients/createOrEdit.html', line 1, column 65] : $invalid cannot be resolved.
Everything keeps working as it should but I'm not the one to just leave errors be, and I've found no way of disabling VTL.
That's my current experience with view resolvers.
I've also had an idea to treat .html files as static resources(which they kinda are before angular does it's magic) using mvc:resources
but without any view resolver my application failed to start even if I set the main layout.html to be the welcome-file in web.xml
My question is. What should I use as a view resolver so that it plays nice with angularjs, and if I should even use view resolvers?
EDIT: I'm trying to use the ContentNegotiatingViewResolver
and I get:
DEBUG ContentNegotiatingViewResolver - Requested media types are [text/html] based on Accept header types and producible media types [*/*])
DEBUG ContentNegotiatingViewResolver - No acceptable view found; returning null
DEBUG DispatcherServlet - Could not complete request
javax.servlet.ServletException: Could not resolve view with name 'layout.html' in servlet with name 'springDispatcherServlet'
webapp-config.xml (contextconfig in dispatcher servlet)
<mvc:annotation-driven />
<!-- Resources -->
<mvc:resources location="/libs/" mapping="/libs/**" />
<mvc:resources location="/css/" mapping="/css/**" />
<mvc:resources location="/js/" mapping="/js/**" />
<!-- Angular application data -->
<mvc:resources location="/WEB-INF/appjs/" mapping="/appjs/**" />
<!-- View locations -->
<mvc:resources location="/WEB-INF/html/" mapping="/**"/>
<!-- Controllers -->
<context:component-scan base-package="com.mrplow.controller" />
<!-- Views -->
<util:map id="contentMediaTypes">
<entry key="json" value="application/json" />
<entry key="html" value="text/html" />
</util:map>
<!-- <util:list id="defaultViews"> -->
<!-- <bean class="org.springframework.web.servlet.view.json.MappingJackson2JsonView" /> -->
<!-- </util:list> -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver"
p:order="1"
p:ignoreAcceptHeader="false"
p:defaultContentType="text/html"
p:mediaTypes-ref="contentMediaTypes" />
LayoutController.java
@Controller
@RequestMapping("/")
public class LayoutController {
@RequestMapping
public String getIndexPage() {
return "layout";
}
}
Thymeleaf view resolver works by surrounding the view name with a prefix and suffix. The default values of prefix and suffix are 'classpath:/templates/' and '. html', respectively. Spring Boot also provides an option to change the default value of prefix and suffix by setting spring.
The architecture of a Spring MVC + Angular single page web app. The client is MVC-capable and contains all the presentation logic which is separated in a view layer, a controller layer, and a frontend services layer. After the initial application startup, only JSON data goes over the wire between client and server.
2) The InternalResourceViewResolver is also the default view resolver of DispatcherServlet class, which acts as the front controller in the Spring MVC framework.
In order to use static resource(html,css,img,js) in spring, use a directory structure that looks like the following:
src/
package/
LayoutController.java
WebContent/
WEB-INF/
static/
html/
layout.html
images/
image.jpg
css/
test.css
js/
main.js
web.xml
springmvc-servlet.xml
@Controller
public class LayoutController {
@RequestMapping("/staticPage")
public String getIndexPage() {
return "layout.htm";
} }
<!-- in spring config file -->
<mvc:resources mapping="/static/**" location="/WEB-INF/static/" />
layout.html
<h1>Page with image</h1>
<img src="/static/img/image.jpg"/>
Note you have to mention /static/img/image.jpg not just /image.jpg ..Same applies for css and js.
OR
You can also use content negotiating view resolver as shown below:
<bean class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
<property name="order" value="1" />
<property name="mediaTypes">
<map>
<entry key="json" value="application/json" />
<entry key="xml" value="application/xml" />
<entry key="rss" value="application/rss+xml" />
<entry key="html" value="text/html"/>
</map>
</property>
<property name="defaultViews">
<list>
<!-- JSON View -->
<bean
class="org.springframework.web.servlet.view.json.MappingJacksonJsonView">
</bean>
Spring MVC will use “ContentNegotiatingViewResolver” (order=1) to return a suitable view (based on file extension declared in “mediaTypes” property), if not match, then use “InternalResourceViewResolver” (order=2) to return a default JSP page.
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="order" value="2" />
<property name="prefix">
<value>/WEB-INF/pages/</value>
</property>
<property name="suffix">
<value>.jsp</value>
</property>
</bean>
Now from your jsp you can redirect to your static html page as well
@Controller
public class LayoutController {
@RequestMapping("/index")
public String getIndexPage() {
return "index";
}
}
index.jsp
<form:form method="GET" action="/static/html/layout.html">
Now try to access your service through http://yourapp.com//index show the form action mentioned above.It will show the layout.html
click on a button or submit in jsp page to invoke the layout.html page
I think ContentNegotiatingViewResolver is the best view resolver, because you will be able to integrate it with Jackson2 to response the data in JSON, XML or HTML text among others responses types that you need.
For example, look this approach.
http://hillert.blogspot.com.es/2011/01/rest-with-spring-contentnegotiatingview.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With