- Interface Controller
- Workflow
- Notes on design and testing
- 10.2. Controllers with Parameters¶
- 10.2.1. Query Strings are URL Data¶
- 10.2.2. Controllers and Query Parameters — Video¶
- 10.2.3. @RequestParam ¶
- 10.2.4. Controllers and Path Parameters — Video¶
- 10.2.5. @PathVariable ¶
- 10.2.6. Check Your Understanding¶
Interface Controller
All Known Implementing Classes: AbstractController , AbstractUrlViewController , ParameterizableViewController , ServletForwardingController , ServletWrappingController , UrlFilenameViewController Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.
Base Controller interface, representing a component that receives HttpServletRequest and HttpServletResponse instances just like a HttpServlet but is able to participate in an MVC workflow. Controllers are comparable to the notion of a Struts Action .
Any implementation of the Controller interface should be a reusable, thread-safe class, capable of handling multiple HTTP requests throughout the lifecycle of an application. To be able to configure a Controller easily, Controller implementations are encouraged to be (and usually are) JavaBeans.
Workflow
After a DispatcherServlet has received a request and has done its work to resolve locales, themes, and suchlike, it then tries to resolve a Controller, using a HandlerMapping . When a Controller has been found to handle the request, the handleRequest method of the located Controller will be invoked; the located Controller is then responsible for handling the actual request and — if applicable — returning an appropriate ModelAndView . So actually, this method is the main entry point for the DispatcherServlet which delegates requests to controllers.
So basically any direct implementation of the Controller interface just handles HttpServletRequests and should return a ModelAndView, to be further interpreted by the DispatcherServlet. Any additional functionality such as optional validation, form handling, etc. should be obtained through extending AbstractController or one of its subclasses.
Notes on design and testing
The Controller interface is explicitly designed to operate on HttpServletRequest and HttpServletResponse objects, just like an HttpServlet. It does not aim to decouple itself from the Servlet API, in contrast to, for example, WebWork, JSF or Tapestry. Instead, the full power of the Servlet API is available, allowing Controllers to be general-purpose: a Controller is able to not only handle web user interface requests but also to process remoting protocols or to generate reports on demand.
Controllers can easily be tested by passing in mock objects for the HttpServletRequest and HttpServletResponse objects as parameters to the handleRequest method. As a convenience, Spring ships with a set of Servlet API mocks that are suitable for testing any kind of web components, but are particularly suitable for testing Spring web controllers. In contrast to a Struts Action, there is no need to mock the ActionServlet or any other infrastructure; mocking HttpServletRequest and HttpServletResponse is sufficient.
- org.springframework.context.ApplicationContextAware
- org.springframework.context.ResourceLoaderAware
- org.springframework.web.context.ServletContextAware
Such environment references can easily be passed in testing environments, through the corresponding setters defined in the respective awareness interfaces. In general, it is recommended to keep the dependencies as minimal as possible: for example, if all you need is resource loading, implement ResourceLoaderAware only. Alternatively, derive from the WebApplicationObjectSupport base class, which gives you all those references through convenient accessors but requires an ApplicationContext reference on initialization.
Controllers can use the checkNotModified methods on WebRequest for HTTP caching support.
10.2. Controllers with Parameters¶
Now that you know the basics of a controller method, we can start to add some more variables into the mix. Some controller methods can take in parameters in the form of query strings or sections of the URL path. Passing this URL data to the controller is one step closer to more flexible web applications.
A route is the mechanism by which a request path gets assigned to a controller within our application. We’ll explore routes and how data is transferred from a webpage with a given route to a specific controller.
10.2.1. Query Strings are URL Data¶
A brief refresher: query strings are additional bits of information tacked onto the ends of urls. They contain data in key-value pairs.
www.galaxyglossary.net?aKey=aValue&anotherKey=anotherValue&thirdKey=thirdValue
Do HTTP requests and responses feel unfamiliar? Do you remember what a query string is? If you’re feeling rusty on these topics, it’s a good idea to brush up now, as routing requires a foundational understanding of HTTP data transfer.
Here’s our introduction to HTTP for reviewing the concepts.
10.2.2. Controllers and Query Parameters — Video¶
The starter code for this video is found in the static-responses branch of the hello-spring-demo repo. The final code presented in this video is found on the query-parameters branch . Be sure to code along to the videos on your own hello-spring project.
10.2.3. @RequestParam ¶
We can pass @RequestParam as an argument of a controller method. This annotation as an argument lets the handler method know about a given query string based on its own argument.
// Responds to get requests at /hello?coder=LaunchCoder @GetMapping("hello") @ResponseBody public String hello(@RequestParam String coder) return "Hello, " + coder + "!"; >
The controller method looks for the query string in the URL that matches its parameter, coder , and puts the paired value of that coder key into the response text.
10.2.4. Controllers and Path Parameters — Video¶
The starter code for this video is found in the query-parameters branch of the hello-spring-demo repo. The final code presented in this video is found on the path-variables branch . Please code along to the videos on your own hello-spring project.
10.2.5. @PathVariable ¶
Another way to handle data with a controller is by accessing the data via a segment of the URL. This is done with @PathVariable . @PathVariable takes an argument that, if matching a portion of the URL, will deliver this data into the handler.
// Responds to get requests at /hello/LaunchCode @GetMapping("hello/") @ResponseBody public String helloAgain(@PathVariable String name) return "Hello, " + name + "!"; > >
Above, name is a placeholder, indicating where in the URL segment to look for the @PathVariable . From the comment, we know that that the actual value is LaunchCode , but this can easily be changed. If we changed the value of this URL segment to /hello/Ada , then this controller would respond with Hello, Ada when a GET request is made.
Also know that you can redirect a user by removing the @ResponseBody annotation from the controller and returning «redirect:/DESIREDPATH» .
10.2.6. Check Your Understanding¶
Your application is served at myfavoriteplanets.net . What is the path that this controller maps to?
@GetMapping("venus") @ResponseBody public String venusSurface(@RequestParam String terrestrial) if (terrestrial == true) return "Venus is rocky." > else return "Venus is gaseous." >
- myfavoriteplanets.net/venus?terrestrial=true
- net.myfavoriteplanets/venus?terrestrial=true
- myfavoriteplanets/venus?terrestrial=true
- myfavoriteplanets/venus/terrestrial
Your application is served at myfavoriteplanets.net . What URL do you need to hit so that the response is: Akatsuki currently orbits Venus. ?
@GetMapping("venus/") @ResponseBody public String venusOrbiter(@PathVariable String orbiter) return orbiter + " currently orbits Venus." >
- myfavoriteplanets.net/venus/
- myfavoriteplanets.net/venus/orbiter=Akatsuki
- myfavoriteplanets.net/venus/Akatsuki
- myfavoriteplanets.net/venus/name=Akatsuki