一、基于注解的控制器
使用基于注解的控制器,具有如下两个优点:
1.在基于注解的控制器类中,可以编写多个处理方法,进而可以处理多个请求(动作)。
2.基于注解的控制器不需要在配置文件中部署映射,仅需要使用RequestMapping注释类型注解一个方法进行请求处理。
1、Controller注解类型
在Spring MVC中,使用org.springframework.stereotype.Controller注解类型声明某类的实例是一个控制器。
package controller;
import org.springframework.stereotype.Controller;
/**“@Controller”表示IndexController的实例是一个控制器
* @Controller相当于@Controller("indexController")
* 或@Controller(value = "indexController")
*/
@Controller
public class IndexController {
//处理请求的方法
}
在Spring MVC中,使用扫描机制找到应用中所有基于注解的控制器类。所以,为了让控制器类被Spring MVC框架扫描到,需要在配置文件中声明spring-context,并使用<context:component-scan/>元素指定控制器类的基本包(请确保所有控制器类都在基本包及其子包下)。
<!-- 使用扫描机制,扫描控制器类,控制器类都在controller包及其子包下 -->
<context:component-scan base-package="controller"/>
2、RequestMapping注解类型
在基于注解的控制器类中,可以为每个请求编写对应的处理方法。使用org.springframework.web.bind.annotation.RequestMapping注解类型将请求与处理方法一一对应。
(1)方法级别注解
@Controller
public class IndexController {
@RequestMapping(value = "/index/login")
public String login() {
/**login代表逻辑视图名称,需要根据Spring MVC配置
* 文件中internalResourceViewResolver的前缀和后缀找到对应的物理视图
*/
return "login";
}
@RequestMapping(value = "/index/register")
public String register() {
return "register";
}
}
(2)类级别注解
@Controller
@RequestMapping("/index")
public class IndexController {
@RequestMapping("/login")
public String login() {
return "login";
}
@RequestMapping("/register")
public String register() {
return "register";
}
}
二、编写请求处理方法
在控制类中每个请求处理方法可以有多个不同类型的参数,以及一个多种类型的返回结果。
除了Servlet API参数类型外,还有输入输出流、表单实体类、注解类型、与Spring框架相关的类型等等,这些类型在后续章节中使用时再详细介绍。但特别重要的类型是org.springframework.ui.Model类型,该类型是一个包含Map的Spring框架类型。每次调用请求处理方法时,Spring MVC都将创建org.springframework.ui.Model对象。
三、Controller接收请求参数的方式
1、通过实体bean接收请求参数
通过一个实体bean来接收请求参数,适用于get和post提交请求方式。需要注意的是,bean的属性名称必须与请求参数名称相同。
2 、通过处理方法的形参接收请求参数
通过处理方法的形参接收请求参数,也就是直接把表单参数写在控制器类相应方法的形参中,即形参名称与请求参数名称完全相同。该接收参数方式适用于get和post提交请求方式。
3、通过HttpServletRequest接收请求参数
通过HttpServletRequest接收请求参数,适用于get和post提交请求方式。
public String register(HttpServletRequest request, Model model) {
String uname = request.getParameter("uname");
String upass = request.getParameter("upass");
4、通过@PathVariable接收URL中的请求参数
@RequestMapping(value="/register/{uname}/{upass}", method=RequestMethod.GET)
//必须加method属性
/**
* 通过@PathVariable获取URL中的参数
*/
public String register(@PathVariable String uname,@PathVariable String upass, Model model) {
5、通过@RequestParam接收请求参数
通过@RequestParam接收请求参数,适用于get和post提交请求方式。 通过@RequestParam接收请求参数“通过处理方法的形参接收请求参数”的区别是:当请求参数与接收参数名不一致时,“通过处理方法的形参接收请求参数”不会报404错误,而“通过@RequestParam接收请求参数”会404错误。
6、通过@ModelAttribute接收请求参数
@ModelAttribute注解放在处理方法的形参上时,用于将多个请求参数封装到一个实体对象,从而简化数据绑定流程,而且自动暴露为模型数据用于视图页面展示时使用。而10.2.1节中只是将多个请求参数封装到一个实体对象,并不能暴露为模型数据。
通过@ModelAttribute注解接收请求参数,适用于get和post提交请求方式。
@RequestMapping("/register")
public String register(@ModelAttribute("user") UserForm user) {
if("zhangsan".equals(user.getUname())
&& "123456".equals(user.getUpass())){
logger.info("成功");
return "login";//注册成功,跳转到login.jsp
}else{
logger.info("失败");
//使用@ModelAttribute("user")与
model.addAttribute("user", user)功能相同
//在register.jsp页面上可以使用EL表达式${user.uname}取 出ModelAttribute的uname值
return "register";//返回register.jsp
}
}
四、重定向和转发
在Spring MVC框架中,控制器类中处理方法的return语句默认就是转发实现,只不过实现的是转发到视图。
五、应用@Autowired和@Service进行依赖注入
在前面学习的控制器中,并没有体现MVC的M层,这是因为控制器即充当C层,又充当M层。这样设计程序的系统结构很不合理,应该将M层从控制器中分离出来。Spring MVC框架本身就是一个非常优秀的MVC框架,它具有一个依赖注入的优点。可以通过org.springframework.beans.factory.annotation.Autowired注解类型将依赖注入到一个属性(成员变量)或方法,如:
@Autowired
public UserService userService;
在Spring MVC中,为了能被作为依赖注入,类必须使用org.springframework.stereotype.Service注解类型注明为@Service(一个服务)。另外,还需要在配置文件中使用<context:component-scan base-package="基本包"/>元素来扫描依赖基本包。
六、@ModelAttribute
1.绑定请求参数到实体对象(表单的命令对象)
@RequestMapping("/register")
public String register(@ModelAttribute("user") UserForm user) {
if("zhangsan".equals(user.getUname())
&& "123456".equals(user.getUpass())){
return "login";
}else{
return "register";
}
}
上述代码中“@ModelAttribute("user") UserForm user”语句的功能有两个,一是将请求参数的输入封装到user对象中;一是创建UserForm实例,以“user”为键值存储在Model对象中,与“model.addAttribute("user", user)”语句功能一样。如果没有指定键值,即“@ModelAttribute UserForm user”,那么创建UserForm实例时,以“userForm”为键值存储在Model对象中,与“model.addAttribute("userForm", user)”语句功能一样。
2.注解一个非请求处理方法
被@ModelAttribute注解的方法,将在每次调用该控制器类的请求处理方法前被调用。这种特性可以用来控制登录权限,当然控制登录权限的方法很多,例如拦截器、过滤器等。