有哪些Spring MVC控制器编写实用技巧值得吐血推荐?
- 内容介绍
- 文章标签
- 相关推荐
本文共计2038个文字,预计阅读时间需要9分钟。
本文介绍了编写Spring MVC框架中控制器(Controller)的基本技巧和最佳操作。在Spring MVC框架中,编写控制器类通常是为了处理用户提出的请求。编写完成后,控制器会调用一个业务类来处理请求。
本文介绍了编写Spring MVC框架的控制器(controller)的基础技巧和最佳操作。在Spring MVC框架中,编写控制器类通常是为了处理用户提出的请求。
编写完成后,控制器会调用一个业务类来处理业务相关任务,进而重定向客户到逻辑视图名。Springdispatcher servlet会对逻辑视图名进行解析,并渲染结果或输出。这就是一个典型的“请求—响应”的完整流程。
1.使用@controllerstereotype
创建一个能够处理单个或多个请求的控制器类,最简单的方法就是使用@controllerstereotype注解一个类,如:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller publicclassHomeController { @RequestMapping("/") publicString visitHome() { // do something before returning view name return"home"; } }
如上所示,visitHome()方法通过重定向跳转到视图名home来处理应用程序内容路径(/)收到的请求。
注意:只有在Spring配置文件中启用了注解驱动,才能使用@controllerstereotype。
启用注解驱动后,Spring的容器(container)会自动扫描如下包中的类:
带有@controller注解的类会被标记成控制器。由于其简单方便,且不再需要对配置文件中的控制器声明beans,这一方法非常实用。
注意:使用@controller注解可以创建一个多动作控制器类,可同时处理多个不同的请求。如:
@Controller publicclassMultiActionController { @RequestMapping("/listUsers") public ModelAndView listUsers() { } @RequestMapping("/saveUser") public ModelAndView saveUser(User user) { } @RequestMapping("/deleteUser") public ModelAndView deleteUser(User user) { } }
如上所示,有三个处理器(handler)在分别处理三个请求,/listUsers,/saveUser,和/deleteUser。
2.实现控制器接口
在Spring MVC中创建控制器还可以用另一个经典的方法,即对一个类实现Controller接口。如:
import javax.servlet.localhost:8080/spring/login?username=scott&password=tiger
类型转换也自动完成了。如果对一个integer类型的参数声明如下:
则Spring会在处理方法中自动将请求参数的值(String类型)转换为指定类型(integer)。
为防止参数名与变量名不同,可将参数实名指定如下:
@RequestParam注解还有另外两个属性,可在一些情况下发挥作用。其中一个属性是required,可指定一个参数是强制参数还是可选参数。如:
这就意味着参数country是可选的,在请求中可略去。当请求中没有参数country时,则变量country为空值。
另一个属性是defaultValue,可在请求参数为空时充当回退值(fallbackvalue)。如:
当方法参数类型为Map<String,String>时,Spring也支持将所有参数作为Map对象。如:
则映射参数包含所有键值对形式的请求参数。了解更多@RequestParam注解相关知识,参见@RequestParam注解。
7.返回模型和视图
处理器方法在处理完业务逻辑后,会返回一个视图,该视图随后由Springdispatcher servlet进行解析。Spring支持handler方法返回String对象或ModelAndView对象。如下所示,handler方法返回了一个String对象,并表示了视图名LoginForm:
@RequestMapping(value = "/login", method = RequestMethod.GET) public String viewLogin() { return"LoginForm"; }
这是返回视图名最简单的方法。但是如果想要发送其他数据到视图,则必须返回ModelAndView对象。如:
@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; }
如上所示,该处理器方法返回了一个ModelAndView对象,该对象视图名为UserList,并有一个可用在视图中的User对象集。
Spring是一个非常灵活的框架,支持将ModelAndView对象声明为处理器方法的参数,而无需再重新创建一个。因此,上例可以重写为:
@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; }
了解更多ModelAndView类相关知识,参见ModelAndView类。
8.将对象放入模型
在MVC架构的应用程序中,控制器将数据输入到模型中,该模型则被用在视图中。从上一节中的举例中可以看到,ModelAndView类的addObject()用于将对象以名值对的形式放入模型中:
modelView.addObject("listUser", listUser); modelView.addObject("siteName", newString("CodeJava.net")); modelView.addObject("users", 1200000);
Spring同样支持声明处理器方法中的Map类型参数。Spring使用这一映射存储将放入模型的对象。如:
@RequestMapping(method = RequestMethod.GET) publicStringviewStats(Map<String, Object> model) { model.put("siteName", "CodeJava.net"); model.put("pageviews", 320000); return"Stats"; }
这一方法比使用ModelAndView对象更加简单。Spring支持用户灵活选择Map对象和ModelAndView对象。
9.处理器方法中的重定向
当条件允许时,只需在URL前加上redirect:/就可将用户重定向跳转到另一个URL。如:
// check login status.... if (!isLogin) { returnnew ModelAndView("redirect:/login"); } // return a list of Users
在上述代码中,没有登陆的用户将会跳转到/loginURL。
10.处理表单提交和表单验证
Spring中的@ModelAttribute注解支持将表单字段绑定到表单返回对象,BingingRequest接口则支持验证表单字段。这使得处理表单提交变得非常简单。一个处理和验证表单数据的典型处理器方法的代码如下所示:
@Controller publicclassRegistrationController { @RequestMapping(value = "/doRegister", method = RequestMethod.POST) publicString doRegister( @ModelAttribute("userForm") User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { // form validation error } else { // form input is OK } // process registration... return"Success"; } }
了解更多@ModelAttribute注解和BindingResult接口相关知识,参见Spring官方文档:
- Using @ModelAttribute on a method argument
- Using @ModelAttribute on a method
- Interface BindingResult
11.处理文件上传
Spring支持自动将上传数据绑定到CommonsMultiparFile数组对象,这使得在处理器方法中处理文件上传变得非常简单。Spring使用Apache CommonsFileUpload作为深层多部分解析器(underlyingmultipart resolver)。
简单上传用户文件的代码如下所示:
@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST) publicStringhandleFileUpload( @RequestParam CommonsMultipartFile[] fileUpload) throws Exception { for (CommonsMultipartFile aFile : fileUpload){ // stores the uploaded file aFile.transferTo(new File(aFile.getOriginalFilename())); } return"Success"; }
了解Spring MVC处理文件上传的完整方法,参见Spring MVC 文件上传教程。
12.在处理器中自动注入业务类
为了让控制器将业务逻辑处理委托到相关业务类,可以使用@Autowired注解,让Spring自动将业务类的实际实现注入到控制器中。如:
@Controller publicclassUserController { @Autowired private UserDAO userDAO; publicString listUser() { // handler method to list all users userDAO.list(); } publicString saveUser(User user) { // handler method to save/update a user userDAO.save(user); } publicString deleteUser(User user) { // handler method to delete a user userDAO.delete(user); } publicString getUser(int userId) { // handler method to get a user userDAO.get(userId); } }
本例中所有与用户管理相关的业务逻辑都由UserDAO接口的实现提供。如:
interfaceUserDAO { List<User> list(); void save(User user); void checkLogin(User user); }
如上所示,使用@Autowired注解使处理器方法可以将任务委托到业务类:
了解更多@Autowired注解相关知识,参见Annotation TypeAutowired。
13.获取HttpServletRequest和HttpServletResponse
有些情况要求在处理器方法中直接获取HttpServletRequest或HttpServletResponse对象。在Spring灵活的框架中,仅需给处理器方法加上一个相关参数就可以完成此任务。如:
@RequestMapping("/download") publicStringdoDownloadFile( HttpServletRequest request, HttpServletResponse response) { // access the request // access the response return"DownloadPage"; }
Spring支持检测并自动将HttpServletRequest和HttpServletResponse对象注入到方法中。这样一来,就可以直接获取请求和响应,如获取InputStream、OutputStream或返回特定的HTTP代码。
14.遵守单一职责原则
在Spring MVC中设计和编写控制器时,应遵循以下两个非常实用的操作:
不要用控制器类来执行业务逻辑,应该用控制器类将业务处理委托到相关的业务类。这可以保证控制器专注于其指定职责,即控制应用程序的工作流。如:
@Controller publicclassUserController { @Autowired private UserDAO userDAO; publicString listUser() { // handler method to list all users userDAO.list(); } publicString saveUser(User user) { // handler method to save/update a user userDAO.save(user); } publicString deleteUser(User user) { // handler method to delete a user userDAO.delete(user); } publicString getUser(int userId) { // handler method to get a user userDAO.get(userId); } }
给每个业务领域创建一个独立的控制器。如,用UserController控制用户管理的工作流,用OrderController控制订单处理的工作流,等等:
@Controller publicclassUserController { } @Controller publicclassProductController { } @Controller publicclassOrderController { } @Controller publicclassPaymentController { }
以上就是本文全部内容,希望这14个小技巧可以帮助读者准确且高效地编写Spring MVC中的控制器类代码。希望对大家的学习有所帮助,也希望大家多多支持自由互联。
本文共计2038个文字,预计阅读时间需要9分钟。
本文介绍了编写Spring MVC框架中控制器(Controller)的基本技巧和最佳操作。在Spring MVC框架中,编写控制器类通常是为了处理用户提出的请求。编写完成后,控制器会调用一个业务类来处理请求。
本文介绍了编写Spring MVC框架的控制器(controller)的基础技巧和最佳操作。在Spring MVC框架中,编写控制器类通常是为了处理用户提出的请求。
编写完成后,控制器会调用一个业务类来处理业务相关任务,进而重定向客户到逻辑视图名。Springdispatcher servlet会对逻辑视图名进行解析,并渲染结果或输出。这就是一个典型的“请求—响应”的完整流程。
1.使用@controllerstereotype
创建一个能够处理单个或多个请求的控制器类,最简单的方法就是使用@controllerstereotype注解一个类,如:
import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller publicclassHomeController { @RequestMapping("/") publicString visitHome() { // do something before returning view name return"home"; } }
如上所示,visitHome()方法通过重定向跳转到视图名home来处理应用程序内容路径(/)收到的请求。
注意:只有在Spring配置文件中启用了注解驱动,才能使用@controllerstereotype。
启用注解驱动后,Spring的容器(container)会自动扫描如下包中的类:
带有@controller注解的类会被标记成控制器。由于其简单方便,且不再需要对配置文件中的控制器声明beans,这一方法非常实用。
注意:使用@controller注解可以创建一个多动作控制器类,可同时处理多个不同的请求。如:
@Controller publicclassMultiActionController { @RequestMapping("/listUsers") public ModelAndView listUsers() { } @RequestMapping("/saveUser") public ModelAndView saveUser(User user) { } @RequestMapping("/deleteUser") public ModelAndView deleteUser(User user) { } }
如上所示,有三个处理器(handler)在分别处理三个请求,/listUsers,/saveUser,和/deleteUser。
2.实现控制器接口
在Spring MVC中创建控制器还可以用另一个经典的方法,即对一个类实现Controller接口。如:
import javax.servlet.localhost:8080/spring/login?username=scott&password=tiger
类型转换也自动完成了。如果对一个integer类型的参数声明如下:
则Spring会在处理方法中自动将请求参数的值(String类型)转换为指定类型(integer)。
为防止参数名与变量名不同,可将参数实名指定如下:
@RequestParam注解还有另外两个属性,可在一些情况下发挥作用。其中一个属性是required,可指定一个参数是强制参数还是可选参数。如:
这就意味着参数country是可选的,在请求中可略去。当请求中没有参数country时,则变量country为空值。
另一个属性是defaultValue,可在请求参数为空时充当回退值(fallbackvalue)。如:
当方法参数类型为Map<String,String>时,Spring也支持将所有参数作为Map对象。如:
则映射参数包含所有键值对形式的请求参数。了解更多@RequestParam注解相关知识,参见@RequestParam注解。
7.返回模型和视图
处理器方法在处理完业务逻辑后,会返回一个视图,该视图随后由Springdispatcher servlet进行解析。Spring支持handler方法返回String对象或ModelAndView对象。如下所示,handler方法返回了一个String对象,并表示了视图名LoginForm:
@RequestMapping(value = "/login", method = RequestMethod.GET) public String viewLogin() { return"LoginForm"; }
这是返回视图名最简单的方法。但是如果想要发送其他数据到视图,则必须返回ModelAndView对象。如:
@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; }
如上所示,该处理器方法返回了一个ModelAndView对象,该对象视图名为UserList,并有一个可用在视图中的User对象集。
Spring是一个非常灵活的框架,支持将ModelAndView对象声明为处理器方法的参数,而无需再重新创建一个。因此,上例可以重写为:
@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; }
了解更多ModelAndView类相关知识,参见ModelAndView类。
8.将对象放入模型
在MVC架构的应用程序中,控制器将数据输入到模型中,该模型则被用在视图中。从上一节中的举例中可以看到,ModelAndView类的addObject()用于将对象以名值对的形式放入模型中:
modelView.addObject("listUser", listUser); modelView.addObject("siteName", newString("CodeJava.net")); modelView.addObject("users", 1200000);
Spring同样支持声明处理器方法中的Map类型参数。Spring使用这一映射存储将放入模型的对象。如:
@RequestMapping(method = RequestMethod.GET) publicStringviewStats(Map<String, Object> model) { model.put("siteName", "CodeJava.net"); model.put("pageviews", 320000); return"Stats"; }
这一方法比使用ModelAndView对象更加简单。Spring支持用户灵活选择Map对象和ModelAndView对象。
9.处理器方法中的重定向
当条件允许时,只需在URL前加上redirect:/就可将用户重定向跳转到另一个URL。如:
// check login status.... if (!isLogin) { returnnew ModelAndView("redirect:/login"); } // return a list of Users
在上述代码中,没有登陆的用户将会跳转到/loginURL。
10.处理表单提交和表单验证
Spring中的@ModelAttribute注解支持将表单字段绑定到表单返回对象,BingingRequest接口则支持验证表单字段。这使得处理表单提交变得非常简单。一个处理和验证表单数据的典型处理器方法的代码如下所示:
@Controller publicclassRegistrationController { @RequestMapping(value = "/doRegister", method = RequestMethod.POST) publicString doRegister( @ModelAttribute("userForm") User user, BindingResult bindingResult) { if (bindingResult.hasErrors()) { // form validation error } else { // form input is OK } // process registration... return"Success"; } }
了解更多@ModelAttribute注解和BindingResult接口相关知识,参见Spring官方文档:
- Using @ModelAttribute on a method argument
- Using @ModelAttribute on a method
- Interface BindingResult
11.处理文件上传
Spring支持自动将上传数据绑定到CommonsMultiparFile数组对象,这使得在处理器方法中处理文件上传变得非常简单。Spring使用Apache CommonsFileUpload作为深层多部分解析器(underlyingmultipart resolver)。
简单上传用户文件的代码如下所示:
@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST) publicStringhandleFileUpload( @RequestParam CommonsMultipartFile[] fileUpload) throws Exception { for (CommonsMultipartFile aFile : fileUpload){ // stores the uploaded file aFile.transferTo(new File(aFile.getOriginalFilename())); } return"Success"; }
了解Spring MVC处理文件上传的完整方法,参见Spring MVC 文件上传教程。
12.在处理器中自动注入业务类
为了让控制器将业务逻辑处理委托到相关业务类,可以使用@Autowired注解,让Spring自动将业务类的实际实现注入到控制器中。如:
@Controller publicclassUserController { @Autowired private UserDAO userDAO; publicString listUser() { // handler method to list all users userDAO.list(); } publicString saveUser(User user) { // handler method to save/update a user userDAO.save(user); } publicString deleteUser(User user) { // handler method to delete a user userDAO.delete(user); } publicString getUser(int userId) { // handler method to get a user userDAO.get(userId); } }
本例中所有与用户管理相关的业务逻辑都由UserDAO接口的实现提供。如:
interfaceUserDAO { List<User> list(); void save(User user); void checkLogin(User user); }
如上所示,使用@Autowired注解使处理器方法可以将任务委托到业务类:
了解更多@Autowired注解相关知识,参见Annotation TypeAutowired。
13.获取HttpServletRequest和HttpServletResponse
有些情况要求在处理器方法中直接获取HttpServletRequest或HttpServletResponse对象。在Spring灵活的框架中,仅需给处理器方法加上一个相关参数就可以完成此任务。如:
@RequestMapping("/download") publicStringdoDownloadFile( HttpServletRequest request, HttpServletResponse response) { // access the request // access the response return"DownloadPage"; }
Spring支持检测并自动将HttpServletRequest和HttpServletResponse对象注入到方法中。这样一来,就可以直接获取请求和响应,如获取InputStream、OutputStream或返回特定的HTTP代码。
14.遵守单一职责原则
在Spring MVC中设计和编写控制器时,应遵循以下两个非常实用的操作:
不要用控制器类来执行业务逻辑,应该用控制器类将业务处理委托到相关的业务类。这可以保证控制器专注于其指定职责,即控制应用程序的工作流。如:
@Controller publicclassUserController { @Autowired private UserDAO userDAO; publicString listUser() { // handler method to list all users userDAO.list(); } publicString saveUser(User user) { // handler method to save/update a user userDAO.save(user); } publicString deleteUser(User user) { // handler method to delete a user userDAO.delete(user); } publicString getUser(int userId) { // handler method to get a user userDAO.get(userId); } }
给每个业务领域创建一个独立的控制器。如,用UserController控制用户管理的工作流,用OrderController控制订单处理的工作流,等等:
@Controller publicclassUserController { } @Controller publicclassProductController { } @Controller publicclassOrderController { } @Controller publicclassPaymentController { }
以上就是本文全部内容,希望这14个小技巧可以帮助读者准确且高效地编写Spring MVC中的控制器类代码。希望对大家的学习有所帮助,也希望大家多多支持自由互联。

