Chris Greenhalgh, 2007-01-29
Contents:
"I just want to get a web page...".
No EQUIP2 required - just J2EE and Spring.
See also EQUIP2_WebApp_Dynamic_Pages_with_JSP.html.
Files outside the web application's WEB-INF/ directory will be
served directly by Tomcat (assuming that the underlying file
permissions allow it).
For example, a request for the top-level index.html file from the
web application:
A J2EE servlet container such as Tomcat also has built-in support
for Java Server Pages, so a request for (e.g.) index2.jsp will
also look for a file webapp/index2.jsp,
and if it is present try to process it as a JSP and return the result.
Images, stylesheet files, applet files and other static content
should normally be placed in the webapp
directory (or subdirectories), outside of the WEB-INF/ subdirectory.
This is also overviewed in the first few sections of EQUIP2_WebApp_Structure_Overview.html.
For a request to be handled by Spring:
<bean id="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="/index.html">filenameViewController</prop>
</props>
</property>
</bean>
What happens next depends completely on the Spring Controller that
is called.
Note that mapping can contain wildcards, e.g. key="/view/*.html".
Spring has a number of standard reusable (configurable) controllers, as well as an hierarchy of abstract Controllers that can be specifialised - see the Spring documentation.
Static pages can often be handled using the simple
UrlFilenameViewController, e.g. (as configured in simplerequest-servlet.xml):
<bean id="filenameViewController"
class="org.springframework.web.servlet.mvc.UrlFilenameViewController">
<property name="prefix" value="simplerequest/" />
</bean>
This Controller extracts the last filename (without extension) from
the request URL and returns this as the name of the Spring 'View' that
should be rendered as the response. This view name (here, 'index' from the URL '.../index.html') is optionally
modified by the Controller's configuration options, here a prefix
string 'simplerequest/',
which is applied to every view name which it returns.
This is a standard strategy that we have used - to map the servlet
name (from the request) right through to the view name (and JSP file
page - see below). This makes it relatively easy to identify which
directories are relevant to which pieces of an application, e.g. JSPs
in WEB-INF/jsp/simplerequest/.
A Spring View is a Java object which knows how to render itself.
Spring support various view technologies (see Spring's documentation),
but so far we have exclusively used Java Server Pages. A Controller can
return an actual View object, however it can also - as in this example
- return just the name of a view. The Spring dispatcher servlet then
refers to its 'view resolution' configuration to get an actual view
object to render.
The following generic configuration tells the Spring dispatcher that
a named view should be a reference to a similarly named Java Server
Page:
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
For the case of the index page, above, the view name 'simplerequest/index' is
therefore mapped othe resource path '/WEB-INF/jsp/simplerequest/index.jsp'
(this path is within the scope of the web application); the
corresponding JSP, WEB-INF/jsp/simplerequest/index.jsp
is processed to get the result.
Note that Spring (and J2EE) also allows data to be passed from the
Controller to the view, via the usual J2EE mechanisms, i.e.:
ModelAndView handleRequest(HttpServletRequest request,
HttpServletResponse response)
throws Exception
There are various abstract implementations base classes of
this which implement the handleRequest()
method itself, but provide various other override/extension points in
their own processing. For example org.springframework.web.servlet.mvc.AbstractController
has configuration options to specify the supported HTTP method(s) (GET,
POST) and session and cacheing information, and requires
implementations
to override:
protected ModelAndView handleRequestInternal(HttpServletRequest request,
HttpServletResponse response)
throws Exception;
For example, the simplerequest-servlet.xml
configures the URL http://.../simplerequest/abstract_controller.html
to be handled by the bean 'myAbstractController'
which it turn is an instance of class equip2.webapptutorial.simplerequest.MyAbstractController.
This has configuration properties 'viewPrefix'
and 'viewName', which are
specified in this case as 'simplerequest/'
and 'abstract_controller_ok',
respectively. Consequently, the request is finally handled by rendering
the JSP WEB-INF/jsp/simplerequest/abstract_controller_ok.jsp.
This controller also passes the string "Magic!" to the view as model
attribute "model_info":
ModelAndView mav = new ModelAndView();
mav.setViewName(getViewPrefix()+getViewName());
Map model = mav.getModel();
model.put("model_info", "Magic!");
return mav;
This is displayed by the view JSP:
<%= requestScope.getAttribute("model_info") %>
Alternatively, a Controller can use the J2EE response object directly to
provide a complete response; it should then return null from the handleRequest method, e.g.
// return a HTTP Bad Request error
response.sendError(response.SC_BAD_REQUEST);
return null;