I downloaded the code for the Spring MVC 3 Showcase. One thing puzzles me (well, more than one), why does this (edited for concision) sample return null
?
@Controller
@RequestMapping("/form")
public class FormController {
@RequestMapping(method=RequestMethod.POST)
public String processSubmit(@Valid FormBean form,
BindingResult result,
WebRequest webRequest,
HttpSession session, Model model) {
if (result.hasErrors()) {
return null;
} else {
session.setAttribute("form", form);
return "redirect:/form";
}
}
}
The REST Controller The API will generally simply return raw data back to the client – XML and JSON representations usually – and so the DispatcherServlet bypasses the view resolvers and returns the data right in the HTTP response body.
The @Controller annotation indicates that a particular class serves the role of a controller. Spring Controller annotation is typically used in combination with annotated handler methods based on the @RequestMapping annotation. It can be applied to classes only. It's used to mark a class as a web request handler.
In Spring MVC, controller methods are the final destination point that a web request can reach. After being invoked, the controller method starts to process the web request by interacting with the service layer to complete the work that needs to be done.
Spring MVC controllers are singleton by default and any controller object variable/field will be shared across all the requests and sessions. If the object variable should not be shared across requests, one can use @Scope("request") annotation above your controller class definition to create instance per request.
If a controller returns a null view name, or declares a void
return type, Spring will attempt to infer the view name from the request URL.
In your case, it will assume the view name is form
, and proceed on that assumption.
It does this using an implementation of RequestToViewNameTranslator
, the default implementation of which is DefaultRequestToViewNameTranslator
, the javadoc for which explains the exact rules it applies.
AnnotationMethodHandlerAdapter.invokeHandlerMethod()
takes care of invoking handler methods. Here, a ModelAndView
will be retrieved via ServletHandlerMethodInvoker.getModelAndView()
.
In your case, getModelAndView()
gets provided the handler method's null
return value. The getModelAndView()
method checks for the return value's type, but as in Java null is never an instanceof any class, that method's logic will create a new ModelAndView
. A new ModelAndView
has initially its view property set to null
.
Then later back up the call stack, in DispatcherServlet.doDispatch()
, there is a test if the ModelAndView
object has a View
associated with it ( mv.hasView()
). Because view == null
, doDispatch()
's logic calls mv.setViewName(getDefaultViewName(request))
. It delegates to the registered RequestToViewNameTranslator
, whose default implementation is DefaultRequestToViewNameTranslator
. This subclass translates the request URI into a view name, in your case form
.
Later in doDispatch()
, via render()
-> resolveViewName()
, this sample's ViewResolver
s are provided with the view name form
. Only one ViewResolver
, InternalResourceViewResolver
is used in this sample. Also, this InternalResourceViewResolver
was configured in src/main/webapp/WEB-INF/spring/appServlet/servlet-context.xml
to add the prefix /WEB-INF/views/
and the suffix .jsp
to the view name. So in total, it will create a View
using the JSP file /WEB-INF/views/form.jsp
. Luckily, a JSP file exists at exactly this location.
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