1. Use @Controller stereotype
This is the easiest way to create a controller class that can handle one or more requests. Just by annotating a class with a stereotype @Controller
, for example:
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class HomeController {
@RequestMapping("/")
public String visitHome() {
return "home";
}
}
As you can see, the visitHome() method handles requests from the application context path (/) by redirecting to the view named home.
Note: The @Controller prototype can only be used when annotation-driven is enabled in the Spring configuration file:
<annotation-driven />
When annotation-driven is enabled, the Spring container automatically scans classes under the package specified by the following statement:
<context:component-scan base-package="net.codejava.spring" />
@Controller
The class annotated by the annotation is configured as a controller. This is the most desirable because it is simple: no need to declare beans for the controller in the configuration file.
Note: By using @Controller
annotations, you can have a multi-action controller class that can handle multiple different requests. E.g:
@Controller
public class MultiActionController {
@RequestMapping("/listUsers")
public ModelAndView listUsers() {
}
@RequestMapping("/saveUser")
public ModelAndView saveUser(User user) {
}
@RequestMapping("/deleteUser")
public ModelAndView deleteUser(User user) {
}
}
As you can see above controller class, there are three kinds of processing three different request processing method /listUsers
, /saveUser
, and /deleteUser
, respectively.
2. Implement the controller interface
Another (perhaps classic) way to create a controller in Spring MVC is to let the class implement the Controller
interface. E.g:
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 implementation class must override this handleRequest()
method. When a matching request comes in, this method will be called by the Spring scheduler Servlet. The request URL pattern processed by this controller is defined in Spring's context configuration file as follows:
<bean name="/main" class="net.codejava.spring.MainController" />
However, the disadvantage of this method is that the controller class cannot handle multiple request URLs.
3. Extend the AbstractController class
If you want to easily control the supported HTTP methods, sessions and content caching. Extending your controller AbstractController
class is ideal. Consider the following example:
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 will create a single-action controller with configurations about supported methods, sessions, and caches, which can then be specified in the controller's bean declaration. E.g:
<bean name="/big" class="net.codejava.spring.BigController">
<property name="supportedMethods" value="POST"/>
</bean>
This configuration indicates that POST
this controller's hander
method only supports that method.
Spring MVC also provides several controller classes designed for specific purposes, including:
-
AbstractUrlViewController
-
MultiActionController
-
ParameterizableViewController
-
ServletForwardingController
-
ServletWrappingController
-
UrlFilenameViewController
4. Specify URL mapping for handler method
This is a mandatory task that must be performed when coding a controller class designed to handle one or more specific requests. Spring MVC provides @RequestMapping
annotations that are used to specify URL mapping. E.g:
@RequestMapping("/login")
This maps the /login
URL pattern to be handled by the annotated method or class. When this annotation is used at the class level, the class will become a single-action controller. E.g:
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 @RequestMapping
annotations are used at the method level, you can have a multi-action controller. E.g:
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 also be used to specify multiple URL patterns to be processed by a method. E.g:
@RequestMapping({"/hello", "/hi", "/greetings"})
In addition, this annotation also has other attributes that may be useful in certain situations, for example method
.
5. Specify the HTTP request method for the handler method
Annotated method
attributes can be used to specify which HTTP methods (GET, POST, PUT, etc.) the handler method supports. @RequestMapping。
This is an example:
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";
}
}
This controller has two methods for handling the same URL pattern /login
, but the former is used for GET
methods and the latter is used for POST
methods. For @RequestMapping
more information on using annotations, see @RequestMapping annotation.
6. Map request parameters to handler methods
One of the cool features of Spring MVC is that you can use @RequestParam
annotations to retrieve request parameters as regular parameters of the handler method. This is HttpServletRequest
a good way to separate the controller from the Servlet API interface.
@RequestMapping(value = "/login", method = RequestMethod.POST)
public String doLogin(@RequestParam String username,
@RequestParam String password) {
}
Spring binds the method parameters username and password to HTTP request parameters with the same name. This means that you can call the URL as follows (if the request method is GET):
http:// localhost:8080 / spring / login?username = scott&password = tiger
Type conversion is also done automatically. For example, if you declare the integer
following types of parameters:
@RequestParam int securityNumber
Then, Spring will automatically convert the value of the request parameter (string) to the specified type (integer) in the handler method.
If the parameter name is different from the variable name, you can specify the actual name of the parameter as follows:
@RequestParam("SSN") int securityNumber
The @RequestParam
annotation also has two additional attributes, which may be useful in certain situations. This attribute specifies whether the parameter is required. E.g: required
@RequestParam(required = false) String country
This means that the parameter country
is optional; therefore, it may be lost from the request. In the example above, country
if no such parameter exists in the request, the variable will be null.
Another attribute is defaultValue
that it can be used as a fallback value when the request parameter is empty. E.g:
@RequestParam(defaultValue = "18") int age
Map
If the method parameter is type, Spring also allows us to access all parameters as objects Map<String, String>
. E.g:
doLogin(@RequestParam Map<String, String> params)
Then, the mapping parameters include all request parameters in the form of key-value pairs. For @RequestParam
more information on using annotations, see @RequestParam annotation. Pay attention to the WeChat public account: Java technology stack, and reply in the background: spring, you can get the N latest Spring tutorials I have compiled, all of which are dry goods.
7. Return to model and view
After processing the business logic, the handler method should return a view, which is then parsed by Spring's scheduler servlet. Spring allows us to return String or Object ModelAndView
from handler
method.
In the following example, the handler
method returns a String and represents a view named LoginForm
:
@RequestMapping(value = "/login", method = RequestMethod.GET)
public String viewLogin() {
return "LoginForm";
}
This is the easiest way to return the name of the view. However, if you want to send other data to the view, you must return an ModelAndView
object. Consider the following handler method:
@RequestMapping("/listUsers")
public ModelAndView listUsers() {
List<User> listUser = new ArrayList<>();
// 从DAO获取用户列表…
ModelAndView modelView = new ModelAndView("UserList");
modelView.addObject("listUser", listUser);
return modelView;
}
As you can see, this handler method returns an object that ModelAndView
holds the name UserList
of the view User
and a collection of objects that can be used in the view.
Spring is also very flexible, because you can ModelAndView
declare objects as parameters of handler methods instead of creating a new object. Therefore, the above example can be rewritten as follows:
@RequestMapping("/listUsers")
public ModelAndView listUsers(ModelAndView modelView) {
List<User> listUser = new ArrayList<>();
//从DAO获取用户列表…
modelView.setViewName("UserList");
modelView.addObject("listUser", listUser);
return modelView;
}
For more information about this class, see: ModelAndView class.
8. Put the object into the model
In applications that follow the MVC architecture, the controller (C) should pass data to the model (M), and then use the model in the view (V). As we saw in the previous example, the addObject()
methods ModelAndView
of this class put objects in the model in the form of name-value pairs:
modelView.addObject("listUser", listUser);
modelView.addObject("siteName", new String("CodeJava.net"));
modelView.addObject("users", 1200000);
Likewise, Spring is very flexible. You can Map
declare type parameters in the handler method. Spring uses this mapping to store the objects of the model. Let's look at 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 ModelAndView
simpler than using objects. Depending on your preference, you can use Map
or use ModelAndView
objects. I would like to thank Spring for its flexibility.
9. Redirection in handler method
If you want to redirect the user to another URL when the conditions are met, please redirect:/
append before the URL. The following code snippet gives an example:
// 检查登录状态....
if (!isLogin) {
return new ModelAndView("redirect:/login");
}
// 返回用户列表
In the above code, /login
if not logged in, the user will be redirected to that URL.
10. Processing form submission and form verification
Spring makes it easy to handle form submissions by providing @ModelAttribute
annotations BindingResult
for binding form fields to form support objects and an interface for validating form fields. The following code snippet shows a typical handler method, which is responsible for processing and validating form data:
@Controller
public class RegistrationController {
@RequestMapping(value = "/doRegister", method = RequestMethod.POST)
public String doRegister(
@ModelAttribute("userForm") User user, BindingResult bindingResult) {
if (bindingResult.hasErrors()) {
// 表单验证错误
} else {
// 表单输入没问题
}
// 注册过程……
return "Success";
}
}
Learn more about @ModelAttribute
annotations and BindingResult
interfaces from Spring's official documentation :
-
Use @ModelAttribute on method parameters
-
Use @ModelAttribute on the method
-
Interface binding result
11. Process file upload
By automatically binding upload data to CommonsMultipartFile
an array of objects, Spring also makes it easy to handle file uploads in handler methods. Spring uses Apache Commons FileUpload as the basic multi-part parser.
The following code snippet shows how easy it is to upload files from the client
@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST)
public String handleFileUpload(
@RequestParam CommonsMultipartFile[] fileUpload) throws Exception {
for (CommonsMultipartFile aFile : fileUpload){
// 存储上传的文件
aFile.transferTo(new File(aFile.getOriginalFilename()));
}
return "Success";
}
12. Automatically assemble business classes in the controller
The controller should delegate the processing of business logic to the relevant business class. For this, you can use @Autowired
annotations to let Spring automatically inject the actual implementation of the business class into the controller. Pay attention to the WeChat public account: Java technology stack, reply in the background: sp, you can get the N latest Spring Boot tutorials I have compiled, all of which are dry goods.
Consider the following code snippet for the controller class:
@Controller
public class UserController {
@Autowired
private UserDAO userDAO;
public String listUser() {
// 列出所有用户的处理方法
userDAO.list();
}
public String saveUser(User user) {
// 保存/更新用户的处理方法
userDAO.save(user);
}
public String deleteUser(User user) {
// 删除用户的处理方法
userDAO.delete(user);
}
public String getUser(int userId) {
// 获取用户的处理方法
userDAO.get(userId);
}
}
Here, all business logic related to user management is UserDAO
provided by the implementation of this interface. E.g:
interface UserDAO {
List<User> list();
void save(User user);
void checkLogin(User user);
}
For @Autowired
more information about the attention solution, see Note Type Automatic Assembly.
13.访问HttpServletRequest和HttpServletResponse
In some cases, you need to access the HttpServletRequest
or HttpServletResponse
object directly in the handler method .
With Spring's flexibility, you only need to add relevant parameters to the processing method. E.g:
@RequestMapping("/download")
public String doDownloadFile(
HttpServletRequest request, HttpServletResponse response) {
// 访问请求
// 访问响应
return "DownloadPage";
}
Spring detects and automatically injects the HttpServletRequest
sum HttpServletResponse
object into the method. Then, you can access the request and response such as get InputStream
, OutputStream
or return a specific HTTP code.
14. Follow the single responsibility principle
Finally, when designing and writing Spring MVC controllers, there are two good practices you should follow:
1) The controller class should not execute business logic. Instead, it should delegate business processing to related business categories. This allows the controller to always focus on its design responsibility to control the workflow of the application. E.g:
@Controller
public class UserController {
@Autowired
private UserDAO userDAO;
public String listUser() {
userDAO.list();
}
public String saveUser(User user) {
userDAO.save(user);
}
public String deleteUser(User user) {
userDAO.delete(user);
}
public String getUser(int userId) {
userDAO.get(userId);
}
}
2) Create each individual controller for each business domain. For example, it is UserController
used to control the OrderController
workflow of user management and the workflow of order processing. E.g:
@Controller
public class UserController {
}
@Controller
public class ProductController {
}
@Controller
public class OrderController {
}
@Controller
public class PaymentController {
}
These 14 tips can help you write controller classes in Spring MVC correctly and effectively. If you have other tips or suggestions, please feel free to share your thoughts in the comments.