import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class HomeController { @RequestMapping("/") public String visitHome() { // do something before returning view name return "home"; } }As you can see, the visitHome()method handles requests coming to the application’s context path (/) by redirecting to the view named home.NOTE: the @Controller stereotype can only be used with annotation-driven is enabled in the Spring’s configuration file:
<annotation-driven />When annotation-driven is enabled, Spring container automatically scans for classes under the package specified in the following statement:
<context:component-scan base-package="net.codejava.spring" />The classes annotated by the @Controller annotation are configured as controllers. This is the most preferable way because its simplicity: no need to declare beans for controllers in the configuration file.NOTE: By using the @Controller annotation, you can have a multi-actions controller class that is able to serve multiple different requests. For example:
@Controller public class MultiActionController { @RequestMapping("/listUsers") public ModelAndView listUsers() { } @RequestMapping("/saveUser") public ModelAndView saveUser(User user) { } @RequestMapping("/deleteUser") public ModelAndView deleteUser(User user) { } }
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.Controller; public class MainController implements Controller { @Override public ModelAndView handleRequest(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("Welcome main"); return new ModelAndView("main"); } }The implementing class must override the handleRequest() method which will be invoked by the Spring dispatcher servlet when a matching request comes in. The request URL pattern handled by this controller is defined in the Spring’s context configuration file as follows:
<bean name="/main" class="net.codejava.spring.MainController" />However, a drawback of this approach is the controller class cannot handle multiple request URLs.
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.AbstractController; public class BigController extends AbstractController { @Override protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception { System.out.println("You're big!"); return new ModelAndView("big"); } }This creates a single-action controller with configurations regarding supported methods, session and caching can be specified in the bean declaration of the controller. For example:
<bean name="/big" class="net.codejava.spring.BigController"> <property name="supportedMethods" value="POST"/> </bean>This configuration indicates that the only POST method is supported by this controller’s hander method. For other configuration (session, caching) see: AbstractController.Spring MVC also offers several controller classes which are designed for specific purposes: AbstractUrlViewController, MultiActionController, ParameterizableViewController, ServletForwardingController, ServletWrappingController, UrlFilenameViewController.
@RequestMapping("/login")That maps the URL pattern /login to be handled by the annotated method or class. When this annotation is used at class level, the class becomes a single-action controller. For example:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller @RequestMapping("/hello") public class SingleActionController { @RequestMapping(method = RequestMethod.GET) public String sayHello() { return "hello"; } }When the @RequestMapping annotation is used at method level, you can have a multi-action controller. For example:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class UserController { @RequestMapping("/listUsers") public String listUsers() { return "ListUsers"; } @RequestMapping("/saveUser") public String saveUser() { return "EditUser"; } @RequestMapping("/deleteUser") public String deleteUser() { return "DeleteUser"; } }The @RequestMapping annotation can be also used for specifying multiple URL patterns to be handled by a single method. For example:
@RequestMapping({"/hello", "/hi", "/greetings"})In addition, this annotation has other properties which may be useful in some cases, e.g. the method property which is covered next.
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; @Controller public class LoginController { @RequestMapping(value = "/login", method = RequestMethod.GET) public String viewLogin() { return "LoginForm"; } @RequestMapping(value = "/login", method = RequestMethod.POST) public String doLogin() { return "Home"; } }As you can see, this controller has two methods that handle the same URL pattern /login, but the former is for GET method and the latter is for POST method.For more information about using the @RequestMapping annotation, see: @RequestMapping annotation.
@RequestMapping(value = "/login", method = RequestMethod.POST) public String doLogin(@RequestParam String username, @RequestParam String password) { }Spring binds the method parameters username and password to the HTTP request parameters with the same names. That means you can invoke a URL as follows (if request method is GET):
http://localhost:8080/spring/login?username=scott&password=tiger
Type conversion is also done automatically. For example, if you declare a parameter of type integer as follows:@RequestParam int securityNumberThen Spring will automatically convert value of the request parameter (String) to the specified type (integer) in the handler method.In case the parameter name is different than the variable name. You can specify actual name of the parameter as follows:
@RequestParam("SSN") int securityNumberThe @RequestParam annotation also has additional 2 attributes which might be useful in some cases. The requiredattribute specifies whether the parameter is mandatory or not. For example:
@RequestParam(required = false) String countryThat means the parameter country is optional, hence can be missing from the request. In the above example, the variable country will be null if there is no such parameter present in the request.Another attribute is defaultValue, which can be used as a fallback value when the request parameter is empty. For example:
@RequestParam(defaultValue = "18") int ageSpring also allows us to access all parameters as a Map object if the method parameter is of type Map<String, String>. For example:
doLogin(@RequestParam Map<String, String> params)Then the map params contains all request parameters in form of key-value pairs.For more information about using the @RequestParam annotation, see: @RequestParam annotation.
@RequestMapping(value = "/login", method = RequestMethod.GET) public String viewLogin() { return "LoginForm"; }That’s the simplest way of returning a view name. But if you want to send additional data to the view, you must return a ModelAndView object. Consider the following handler method:
@RequestMapping("/listUsers") public ModelAndView listUsers() { List<User> listUser = new ArrayList<>(); // get user list from DAO... ModelAndView modelView = new ModelAndView("UserList"); modelView.addObject("listUser", listUser); return modelView; }As you can see, this handler method returns a ModelAndView object that holds the view name “UserList” and a collection of User objects which can be used in the view.Spring is also very flexible, as you can declare the ModelAndView object as a parameter of the handler method instead of creating a new one. Thus, the above example can be re-written as follows:
@RequestMapping("/listUsers") public ModelAndView listUsers(ModelAndView modelView) { List<User> listUser = new ArrayList<>(); // get user list from DAO... modelView.setViewName("UserList"); modelView.addObject("listUser", listUser); return modelView; }You can learn more about the ModelAndView class by visiting: ModelAndView class.
modelView.addObject("listUser", listUser); modelView.addObject("siteName", new String("CodeJava.net")); modelView.addObject("users", 1200000);Again, Spring is very flexible. You can declare a parameter of type Map in the handler method, Spring uses this map to store objects for the model. Let’s see another example:
@RequestMapping(method = RequestMethod.GET) public String viewStats(Map<String, Object> model) { model.put("siteName", "CodeJava.net"); model.put("pageviews", 320000); return "Stats"; }This is even simpler than using ModelAndView object. Depending on your taste, you can use either Map or ModelAndView object. Thanks for the flexibility of Spring.
// check login status.... if (!isLogin) { return new ModelAndView("redirect:/login"); } // return a list of UsersIn the above code, the user will be redirected to the /login URL if he is not logged in.
@Controller public class RegistrationController { @RequestMapping(value = "/doRegister", method = RequestMethod.POST) public String doRegister( @ModelAttribute("userForm") User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { // form validation error } else { // form input is OK } // process registration... return "Success"; } }Learn more about the @ModelAttribute annotation and the BindingResultinterface from Spring’s official documentation:You can learn more and in-depth about form handling and form validation in Spring MVC by reading Spring MVC Form Handling Tutorial and Spring MVC Form Validation Tutorial.
@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST) public String handleFileUpload( @RequestParam CommonsMultipartFile[] fileUpload) throws Exception { for (CommonsMultipartFile aFile : fileUpload){ // stores the uploaded file aFile.transferTo(new File(aFile.getOriginalFilename())); } return "Success"; }You can learn the complete solution for handling file upload with Spring MVC by following the Spring MVC File Upload Tutorial.
@Controller public class UserController { @Autowired private UserDAO userDAO; public String listUser() { // handler method to list all users userDAO.list(); } public String saveUser(User user) { // handler method to save/update a user userDAO.save(user); } public String deleteUser(User user) { // handler method to delete a user userDAO.delete(user); } public String getUser(int userId) { // handler method to get a user userDAO.get(userId); } }Here, all the business logics related to User management is provided by an implementation of the UserDAO interface. For example:
interface UserDAO { List<User> list(); void save(User user); void checkLogin(User user); }By using the @Autowired annotation, the handler methods can delegate tasks to the business class, as we can see in the above example:
List<User> listUser = userDAO.list();For more information about the @Autowired annotation, see: Annotation Type Autowired.
@RequestMapping("/download") public String doDownloadFile( HttpServletRequest request, HttpServletResponse response) { // access the request // access the response return "DownloadPage"; }Spring detects and automatically injects the HttpServletRequest and HttpServletResponse objects into the method. Then you can access the request and response such as getting InputStream, OutputStream or returning a specific HTTP code.
@Controller public class UserController { @Autowired private UserDAO userDAO; public String listUser() { // handler method to list all users userDAO.list(); } public String saveUser(User user) { // handler method to save/update a user userDAO.save(user); } public String deleteUser(User user) { // handler method to delete a user userDAO.delete(user); } public String getUser(int userId) { // handler method to get a user userDAO.get(userId); } }
@Controller public class UserController { } @Controller public class ProductController { } @Controller public class OrderController { } @Controller public class PaymentController { }